Amazon EKS — Production Readiness Lab
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
kubectlaccess - 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 |