Amazon EKS — Production Readiness Lab

3 minute read

Run through a production readiness audit on your EKS cluster. This lab uses real kubectl and AWS CLI commands to identify gaps.

Prerequisites:

  • Running EKS cluster with kubectl access
  • AWS CLI configured

Step 1 — Cluster Overview

# Cluster details
aws eks describe-cluster --name my-cluster \
  --query 'cluster.{Name:name,Version:version,Status:status,Endpoint:endpoint}'

# Platform version
aws eks describe-cluster --name my-cluster --query 'cluster.platformVersion'

# Node inventory
kubectl get nodes -o custom-columns='NAME:.metadata.name,VERSION:.status.nodeInfo.kubeletVersion,OS:.status.nodeInfo.osImage,INSTANCE:.metadata.labels.node\.kubernetes\.io/instance-type,AZ:.metadata.labels.topology\.kubernetes\.io/zone'

Step 2 — Security Audit

echo "=== Security Audit ==="

# Check secrets encryption
echo "--- Secrets Encryption ---"
aws eks describe-cluster --name my-cluster --query 'cluster.encryptionConfig' || echo "⚠ No encryption config"

# Check control plane logging
echo "--- Control Plane Logs ---"
aws eks describe-cluster --name my-cluster \
  --query 'cluster.logging.clusterLogging[?enabled==`true`].types[]'

# Check endpoint access
echo "--- Endpoint Access ---"
aws eks describe-cluster --name my-cluster \
  --query 'cluster.resourcesVpcConfig.{Public:endpointPublicAccess,Private:endpointPrivateAccess,CIDRs:publicAccessCidrs}'

# Pod security labels
echo "--- Pod Security Standards ---"
kubectl get namespaces -o json | jq -r '.items[] | "\(.metadata.name): enforce=\(.metadata.labels["pod-security.kubernetes.io/enforce"] // "NOT SET")"'

# Service accounts with default automount
echo "--- Default Service Accounts ---"
kubectl get serviceaccounts -A -o json | jq -r '.items[] | select(.automountServiceAccountToken != false) | "\(.metadata.namespace)/\(.metadata.name)"' | head -20

Step 3 — Networking Audit

echo "=== Networking Audit ==="

# Subnet IP availability
echo "--- Subnet IPs ---"
aws ec2 describe-subnets \
  --filters "Name=tag:kubernetes.io/cluster/my-cluster,Values=*" \
  --query 'Subnets[*].{SubnetId:SubnetId,AZ:AvailabilityZone,FreeIPs:AvailableIpAddressCount}' \
  --output table

# VPC CNI version
echo "--- VPC CNI ---"
aws eks describe-addon --cluster-name my-cluster --addon-name vpc-cni --query 'addon.addonVersion'

# CoreDNS health
echo "--- CoreDNS ---"
kubectl get deployment coredns -n kube-system -o wide
kubectl get pdb -n kube-system 2>/dev/null | grep coredns || echo "⚠ No CoreDNS PDB"

# Network policies
echo "--- Network Policies ---"
NP_COUNT=$(kubectl get networkpolicies -A --no-headers 2>/dev/null | wc -l)
echo "Network Policy count: $NP_COUNT"
[[ $NP_COUNT -eq 0 ]] && echo "⚠ No network policies found"

Step 4 — Reliability Audit

echo "=== Reliability Audit ==="

# Pod Disruption Budgets
echo "--- PDBs ---"
kubectl get pdb -A --no-headers 2>/dev/null | wc -l
kubectl get pdb -A 2>/dev/null || echo "⚠ No PDBs found"

# HPA status
echo "--- HPA ---"
kubectl get hpa -A 2>/dev/null || echo "⚠ No HPAs found"

# Pods without resource requests
echo "--- Pods Missing Resource Requests ---"
kubectl get pods -A -o json | jq -r '
  .items[] | 
  select(.spec.containers[].resources.requests == null) | 
  "\(.metadata.namespace)/\(.metadata.name)"' | head -10

# Single replica deployments
echo "--- Single Replica Deployments ---"
kubectl get deployments -A -o json | jq -r '
  .items[] | 
  select(.spec.replicas == 1) | 
  "\(.metadata.namespace)/\(.metadata.name)"'

# Pods without liveness probes
echo "--- Pods Missing Liveness Probes ---"
kubectl get pods -A -o json | jq -r '
  .items[] | 
  select(.spec.containers[].livenessProbe == null) | 
  "\(.metadata.namespace)/\(.metadata.name)"' | head -10

Step 5 — Generate Report

echo "=== Production Readiness Summary ===" > /tmp/eks-audit-report.txt
echo "Cluster: my-cluster" >> /tmp/eks-audit-report.txt
echo "Date: $(date)" >> /tmp/eks-audit-report.txt
echo "" >> /tmp/eks-audit-report.txt

# Collect findings
echo "[Nodes]" >> /tmp/eks-audit-report.txt
kubectl get nodes -o wide >> /tmp/eks-audit-report.txt
echo "" >> /tmp/eks-audit-report.txt

echo "[System Pods]" >> /tmp/eks-audit-report.txt
kubectl get pods -n kube-system >> /tmp/eks-audit-report.txt
echo "" >> /tmp/eks-audit-report.txt

echo "[Unhealthy Pods]" >> /tmp/eks-audit-report.txt
kubectl get pods -A --field-selector status.phase!=Running,status.phase!=Succeeded >> /tmp/eks-audit-report.txt
echo "" >> /tmp/eks-audit-report.txt

echo "[PDBs]" >> /tmp/eks-audit-report.txt
kubectl get pdb -A >> /tmp/eks-audit-report.txt
echo "" >> /tmp/eks-audit-report.txt

echo "[HPAs]" >> /tmp/eks-audit-report.txt
kubectl get hpa -A >> /tmp/eks-audit-report.txt

echo "Report saved to /tmp/eks-audit-report.txt"
cat /tmp/eks-audit-report.txt

Key Findings Template

Category Finding Severity Remediation
Security No secrets encryption High Enable KMS envelope encryption
Security Public endpoint unrestricted Medium Add publicAccessCidrs
Networking No network policies Medium Add default deny per namespace
Reliability 3 single-replica deployments High Scale to 2+ replicas
Reliability 5 pods missing probes Medium Add liveness + readiness probes
Operations No PDBs configured Medium Add PDBs for all deployments

Updated: