A production-ready Amazon EKS cluster requires eight controls in place before you ship traffic: (1) enable IRSA so pods get short-lived AWS credentials via OIDC instead of instance-level roles; (2) provision everything through IaC using Terraform or eksctl — never touch the Console for production clusters; (3) deploy Karpenter for node autoscaling, which provisions nodes in 30–60 seconds versus 3–5 minutes with Cluster Autoscaler; (4) enforce Pod Security Standards at the restricted profile cluster-wide; (5) enable envelope encryption for Kubernetes secrets using AWS KMS; (6) apply a default-deny NetworkPolicy to every production namespace; (7) enable Container Insights and control-plane logging from day one; (8) configure a tested upgrade path and Velero backups before you need them. IT-Magic operates 24/7 infrastructure management for EKS clusters across all of these dimensions — the sections below explain exactly how to implement each one.
Pro Tip: Run kubectl auth can-i --list --as system:serviceaccount:<namespace>:<sa-name> against every service account in production today. Most teams find at least one with wildcard permissions they did not intend to grant.
Table of Contents
- What are the EKS best practices for security?
- How do you design EKS for high availability?
- How does autoscaling work in EKS, and which tool should you use?
- How should you configure EKS networking for production?
- What causes EKS performance problems and how do you fix them?
- How do you build observability for EKS clusters?
- How do you manage EKS infrastructure as code and CI/CD?
- How do you upgrade EKS safely and roll back if something breaks?
- What are the most effective EKS cost optimization strategies?
- How do you back up EKS and plan for disaster recovery?
- How do you implement these practices in a 90-day operational plan?
- How do taints and tolerations improve workload scheduling?
- Key Takeaways
- The controls that actually matter in practice
- IT-Magic handles the operational weight of production EKS
- Useful sources
- FAQ
What are the EKS best practices for security?
Running this on your own AWS setup? IT-Magic is an AWS Advanced Tier Partner — we audit, fix, or fully manage it for you.
Get a free consultationSecurity on EKS is not a single toggle. It is a stack of controls that each reduce a different blast radius, and skipping any one of them tends to be the control that gets exploited.
IRSA and least-privilege identity
IRSA (IAM Roles for Service Accounts) is the correct pattern for pod-to-AWS access. It binds a Kubernetes ServiceAccount to an IAM role via your cluster’s OIDC provider and injects short-lived credentials automatically. The trust policy must scope to the exact namespace and service account name — a wildcard trust policy defeats the purpose entirely. Audit usage by filtering CloudTrail for AssumeRoleWithWebIdentity events and correlating them to the pod that triggered them.
Run one ServiceAccount per component, not one per namespace. Periodic audits with kubectl auth can-i catch role drift before it becomes a finding. Never store AWS credentials in environment variables or ConfigMaps.
Secrets encryption and runtime hardening
Enable etcd envelope encryption with AWS KMS for all Kubernetes Secrets at rest. For runtime secrets, pull from AWS Secrets Manager or Parameter Store using the Secrets Store CSI driver rather than mounting Secrets as environment variables, which leak into process listings.
Runtime hardening defaults that belong in every Pod spec:
securityContext.runAsNonRoot: truereadOnlyRootFilesystem: trueallowPrivilegeEscalation: false- Drop all Linux capabilities; add back only what the container genuinely needs
- Enforce IMDSv2 in your Launch Templates by setting
HttpTokens: required— this blocks SSRF-based metadata credential theft
Image supply chain and admission control
Build-time scanning via ECR enhanced scanning catches known CVEs before an image reaches the cluster. Sign images with Cosign/Sigstore and verify signatures at admission time using Kyverno policies. Kyverno is easier to operate than OPA/Gatekeeper for most teams because policies are plain Kubernetes YAML rather than Rego. Use OPA where you already have Rego investment or need fine-grained attribute-based logic.
Compliance and auditing
Enable all five control-plane log types in CloudWatch: api, audit, authenticator, controllerManager, and scheduler. Feed audit logs into AWS Config or a SIEM for compliance evidence. For PCI DSS and SOC 2 workloads, the audit log is the primary evidence artifact — missing it means a finding.
How do you design EKS for high availability?
High availability on EKS is a design decision made at provisioning time. Retrofitting it later is painful.
Multi-AZ node distribution
Spread node groups across at least three Availability Zones. With Karpenter, define NodePools that use topology-aware constraints so new nodes land in the AZ where the pending pod needs capacity. With Cluster Autoscaler, use one Auto Scaling Group per AZ rather than a single multi-AZ ASG — this gives the autoscaler accurate per-AZ capacity signals.
Workload availability patterns
Every production Deployment needs:
- At least two replicas, spread across AZs using
topologySpreadConstraintswithwhenUnsatisfiable: DoNotSchedule - A
PodDisruptionBudgetthat keeps at least one pod running during voluntary disruptions (node drains, upgrades) - Readiness probes that accurately reflect whether the pod can serve traffic — not just whether the process started
- Liveness probes with a
failureThresholdgenerous enough to survive GC pauses or cold starts without triggering restart loops
Anti-affinity rules (requiredDuringSchedulingIgnoredDuringExecution) are the blunt instrument; topologySpreadConstraints is more flexible and should be the default for stateless services.
Control plane protection
Keep the API server endpoint private. If public access is required for CI/CD runners, restrict it to known CIDR ranges. Enable control-plane logging before you need it — diagnosing an incident without audit logs is guesswork.
Pro Tip: Before any planned maintenance, verify PodDisruptionBudgets are in place with kubectl get pdb -A. A missing PDB on a stateful workload during a node drain is one of the most common causes of unplanned downtime during upgrades.
Failure mode runbook
- Node pressure: cordon the node (
kubectl cordon <node>), drain it (kubectl drain --ignore-daemonsets --delete-emptydir-data <node>), then investigate or replace - AZ failure: Karpenter or Cluster Autoscaler should compensate automatically; verify PDBs are not blocking rescheduling
- API server overload: check
apiserver_request_duration_secondsandetcd_request_duration_secondsin CloudWatch; reduce LIST calls from controllers if throttling is the cause
How does autoscaling work in EKS, and which tool should you use?
The honest answer: use Karpenter unless you have a specific reason not to.
Karpenter vs. Cluster Autoscaler
| Dimension | Karpenter | Cluster Autoscaler |
|---|---|---|
| Scale speed | 30–60 seconds | 3–5 minutes |
| Instance selection | Any EC2 instance type matching constraints | Pre-defined node group instance types |
| Cost efficiency | Consolidation policies reduce waste continuously | Scales down slowly; no bin-packing |
| Operational complexity | NodePool CRDs; no node groups required | Node group management required |
| Spot handling | Native interruption handling and fallback | Requires separate configuration |
Karpenter provisions nodes directly via the EC2 API, bypassing node-group quotas (the 450-per-group limit that bites large clusters). It also uses the latest EKS-optimized AMI automatically, which keeps nodes patched without manual intervention. For most teams starting a new cluster in 2026, Karpenter is the right default.
Cluster Autoscaler still makes sense when you need strict node-group boundaries for compliance, or when you are running a managed service that does not yet support Karpenter NodePools.
HPA and VPA guidance
Use autoscaling/v2 for HPA and configure application-level metrics rather than CPU alone. CPU-only HPA triggers unnecessary scale events because CPU utilization does not reflect actual request saturation. Queue depth, p95 latency, or active connection count are better signals for most web services. Expose them via the Prometheus adapter or a custom metrics API.
Run VPA in Recommendation mode for stateful workloads — it gives you right-sizing data without the disruptive pod restarts that Auto mode causes on databases or message brokers.
Node strategies
- Managed node groups with custom Launch Templates: the right default for most workloads. Custom Launch Templates let you enforce IMDSv2, set
--max-podsfor prefix delegation, and preinstall security agents — none of which are reliably achievable with default managed templates. - Fargate: good for batch jobs or workloads that need per-pod isolation without node management; not suitable for DaemonSets or workloads with high network throughput requirements.
- Spot + Graviton: combine Karpenter’s consolidation with Graviton instance types for non-critical workloads. Always define a fallback to on-demand in your NodePool’s
spec.disruptionsettings so a spot interruption does not cascade.
How should you configure EKS networking for production?
Networking mistakes on EKS are hard to fix after the fact because they often require re-provisioning node groups or changing VPC CIDR allocations.
Amazon VPC CNI configuration
The Amazon VPC CNI assigns real VPC IP addresses to pods, which simplifies routing but exhausts IP space faster than overlay networks. Enable prefix delegation (ENABLE_PREFIX_DELEGATION=true) to assign /28 prefixes to ENIs instead of individual IPs — this multiplies pod density per node significantly. Set --max-pods in your kubelet arguments to match the new limit, which requires a custom Launch Template.
Enable Security Groups for Pods (ENABLE_POD_ENI=true) for workloads that need SG-based access control to RDS, ElastiCache, or other AWS services. This requires Nitro-based instances — check the VPC CNI compatibility matrix before selecting instance types.
Default-deny NetworkPolicy
Apply a default-deny ingress and egress policy to every production namespace on day one:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
Then add explicit allow rules for each traffic path: ingress from the load balancer, egress to the database, egress to the AWS API endpoints your pods need. This posture catches misconfigured services before they become lateral movement paths.
Pro Tip: Use Cilium or Calico in addition to the VPC CNI if you need L7 network policies or DNS-based egress filtering. The VPC CNI handles IP assignment; a CNI plugin handles policy enforcement — they are not mutually exclusive.
Ingress and load balancer patterns
Use the AWS Load Balancer Controller for all ingress resources. It provisions ALBs natively and supports target group binding, which lets you route traffic directly to pod IPs without a NodePort hop. For internal services, use scheme: internal on the Ingress annotation. Terminate TLS at the ALB using ACM certificates rather than inside the pod — this keeps certificate rotation out of your deployment pipeline.
VPC CNI tuning checklist:
- Enable prefix delegation and update
--max-podsin Launch Template - Enable
ENABLE_POD_ENIonly on Nitro instances - Spread nodes across multiple instance families to avoid regional capacity errors
- Set
AWS_VPC_K8S_CNI_EXTERNALSNAT=trueif pods need to reach the internet through a NAT Gateway
What causes EKS performance problems and how do you fix them?
Most EKS performance problems trace back to three sources: API server saturation, node right-sizing decisions made at cluster creation and never revisited, and HPA metrics that do not reflect actual load.
Node sizing tradeoffs
Fewer large nodes reduce control-plane load because each node is one kubelet connection, one set of DaemonSet pods, and one heartbeat. Smaller nodes improve blast radius isolation — a noisy neighbor on a 64-core node affects more workloads than on a 4-core node. The right answer depends on your workload profile: batch jobs favor large nodes; microservices favor smaller ones with strict resource limits.
API server and control-plane signals
Watch these metrics in CloudWatch or Prometheus:
apiserver_request_duration_seconds(p99 above 1 second is a warning)apiserver_current_inflight_requests(sustained above 400 is a problem)etcd_request_duration_seconds(p99 above 100ms warrants investigation)workqueue_depthper controller (a growing queue means a controller is falling behind)
Reduce LIST calls from custom controllers — they are the most common cause of API server saturation at scale. Use watch with resource version instead of polling.
Workload saturation metrics
CPU utilization tells you a node is busy. It does not tell you requests are queuing. For web services, track request queue depth and p95 latency as your primary saturation signals and feed them into HPA v2 via the Prometheus adapter. For JVM workloads, watch GC pause duration and heap utilization — a pod that is CPU-idle but GC-thrashing will fail latency SLOs without triggering any CPU-based alert.
Kubelet tuning: set memory.min and memory.high in cgroup v2 to protect critical pods from OOM kills during memory pressure. For prefix delegation, always set --max-pods explicitly in the Launch Template rather than relying on the default calculation.
How do you build observability for EKS clusters?
Three signals, no exceptions: metrics, logs, and traces. Missing any one of them means you will spend the first 20 minutes of an incident reconstructing what happened instead of fixing it.
Observability stack options
The native AWS stack (Container Insights + Fluent Bit + X-Ray) is the fastest path to production observability. Container Insights gives you node, pod, and container-level metrics in CloudWatch with minimal configuration. Fluent Bit ships logs to CloudWatch Logs or OpenSearch. X-Ray handles distributed tracing with SDK integration.
The portable stack (Prometheus + Grafana + OpenTelemetry + Loki) takes more effort to operate but avoids CloudWatch costs at high log volumes and gives you full control over retention and dashboards. Three-signal observability is mandatory for SLO-driven alerting regardless of which stack you choose.
SLO-driven alerting
Define SLIs and SLOs before you write alert rules. For a typical web service:
- Availability SLO: 99.9% of requests return a non-5xx response over a 30-day window
- Latency SLO: p95 response time below 300ms for 99% of the 30-day window
- Error budget alert: fire when error budget burn rate exceeds 5x the sustainable rate over a 1-hour window
Alert on SLO burn rate, not raw error rate. Raw error rate alerts fire too late or too early depending on traffic volume.
Pro Tip: Link traces to logs by injecting the trace ID into your structured log output. When an alert fires, you can jump from the Grafana panel directly to the offending trace and its associated log lines — this cuts mean time to diagnosis significantly.
Incident runbook structure
- Detection: alert fires; on-call engineer acknowledges within SLA
- Triage: check Container Insights dashboard for node pressure, pod restarts, and OOM events
- Isolation: cordon affected nodes if node-level; scale deployment if workload-level
- Remediation: apply fix, verify metrics return to baseline
- Post-incident: update runbook with new failure mode and add alert if gap identified
Feed observability signals back into autoscaling decisions: if your HPA is using Prometheus metrics, the same dashboards that show saturation should also show scaling events.
How do you manage EKS infrastructure as code and CI/CD?
IaC is not optional for production EKS. A cluster provisioned through the Console is a cluster you cannot reproduce, audit, or roll back.
IaC patterns
Use Terraform with the terraform-aws-modules/eks/aws module or eksctl with a YAML manifest for cluster provisioning. Both support GitOps workflows where cluster configuration lives in a Git repository and changes go through pull request review before applying. Never apply infrastructure changes directly from a developer laptop in production.
Pro Tip: Separate your platform repo (cluster config, add-ons, RBAC) from your application repo (Deployments, Services, HPA). Platform changes go through a slower review process; application changes can move faster. Mixing them in one repo creates bottlenecks.
Recommended repo structure:
platform/— cluster config, Karpenter NodePools, add-on manifests, RBACapps/— application Deployments, Services, Ingress, HPApolicies/— Kyverno or OPA policies, NetworkPolicies
GitOps promotion workflow
- Developer opens PR against
apps/dev/ - CI pipeline runs image scan, policy gate (Kyverno dry-run), and unit tests
- Merge triggers ArgoCD or Flux sync to dev cluster
- Promotion PR to
apps/staging/requires passing integration tests - Promotion to
apps/production/requires manual approval and canary analysis
Safe deployment patterns
Use progressive delivery for production rollouts. Argo Rollouts supports canary and blue/green strategies with automatic rollback on metric degradation. Pre-deployment checks should include: image signature verification, vulnerability gate (block on critical CVEs), and admission webhook dry-run.
EKS managed add-ons handle versioning and compatibility testing against the control plane automatically. Prefer them for CoreDNS, kube-proxy, VPC CNI, and the EBS CSI driver. Self-manage only add-ons that require configuration the managed version does not expose.
How do you upgrade EKS safely and roll back if something breaks?
Upgrades are where clusters that looked healthy reveal hidden configuration debt. The order matters: control plane first, then managed node groups, then add-ons.
Upgrade sequence
- Review the Kubernetes changelog and EKS release notes for the target version
- Run the upgrade in staging and verify all workloads pass smoke tests
- Check PodDisruptionBudgets are in place for every stateful workload
- Upgrade the control plane:
aws eks update-cluster-version --name <cluster> --kubernetes-version <version> - Wait for control plane to report
ACTIVE - Upgrade managed node groups:
eksctl upgrade nodegroup --cluster <cluster> --name <ng> --kubernetes-version <version> - Update EKS managed add-ons:
aws eks update-addon --cluster-name <cluster> --addon-name <addon> --resolve-conflicts OVERWRITE - Run integration tests and verify SLO metrics are within baseline
EKS supports n-1 skew — nodes can run one minor version behind the control plane — but upgrade promptly. Staying two versions behind means you are running unsupported node software.
Pre-flight checklist
- Verify all PDBs allow at least one disruption
- Scale Karpenter or Cluster Autoscaler to allow node replacement
- Take a Velero backup of cluster objects before starting
- Confirm staging upgrade completed without errors
Rollback playbook
Rolling back a control plane upgrade is not supported by EKS — the control plane is immutable once upgraded. This is why staging validation matters. For node groups, you can roll back by provisioning a new node group at the previous version and draining the upgraded one. For add-ons, revert using aws eks update-addon with the previous version string.
For data recovery, Velero restores cluster objects and persistent volume snapshots. EBS snapshots provide volume-level recovery for stateful workloads. Test both paths before you need them.
What are the most effective EKS cost optimization strategies?
The biggest cost leaks on EKS are idle node groups, over-provisioned resource requests, and on-demand instances running workloads that tolerate interruption.
Right-sizing workloads
Run VPA in Recommendation mode for two weeks before changing resource requests. The recommendations surface actual p95 CPU and memory consumption, which is almost always lower than what engineers initially request. Use CloudWatch Container Insights to identify node groups with consistently low utilization — these are candidates for consolidation or deletion.
Cost reduction steps in priority order:
- Delete idle node groups (utilization below 20% sustained)
- Apply VPA recommendations to over-provisioned Deployments
- Move interrupt-tolerant workloads (batch, CI runners, dev environments) to Spot
- Add Graviton instance types to Karpenter NodePools for additional savings
- Enable Karpenter consolidation policies to bin-pack nodes continuously
Spot and Graviton strategy
Karpenter’s consolidation mode continuously evaluates whether running workloads could fit on fewer or cheaper nodes and replaces them without manual intervention. Combine this with a NodePool that includes multiple instance families and sizes — this reduces the chance of Spot capacity unavailability causing a scale failure. Always define an on-demand fallback in the NodePool’s spec.disruption.budgets so a Spot interruption wave does not take down your entire fleet.
For predictable baseline capacity, compute savings plans offer discounts on on-demand pricing when you commit to a usage level. Apply savings plans to your on-demand baseline; let Spot handle the variable portion.
Tagging and governance
Tag every node group and namespace with cost center, environment, and team. Feed tags into AWS Cost Explorer and set up budget alerts per cost center. Review cost allocation monthly — teams that see their own spend tend to right-size faster than those who see a shared bill. For deeper FinOps practices, the EKS cost reduction guide covers right-sizing, Spot governance, and chargeback in detail.
How do you back up EKS and plan for disaster recovery?
A backup strategy that has never been tested is not a backup strategy.
Velero and EBS snapshots
Velero handles cluster object backups (Deployments, ConfigMaps, Secrets, PVCs) and can trigger EBS snapshots for persistent volumes via the AWS plugin. Recommended schedule: hourly backups of cluster objects with a 24-hour retention, daily backups with a 30-day retention, and weekly backups stored in a separate AWS region for cross-region DR.
Backup checklist:
- Velero installed with an IAM role scoped to the backup S3 bucket (use IRSA)
- EBS snapshot policy configured via AWS Data Lifecycle Manager
- Backup storage in a separate AWS account or region from the cluster
- Automated restore verification running weekly
Application-level backups
Velero does not replace application-level backups for databases. PostgreSQL on RDS needs automated snapshots and point-in-time recovery enabled. For self-managed databases running on EKS (which you should avoid for production unless you have a specific reason), use a consistent snapshot tool like pgBackRest or Percona XtraBackup alongside Velero.
DR runbook and testing
- Define RTO and RPO per workload class: stateless services (RTO 15 minutes, RPO near-zero); stateful services (RTO 1 hour, RPO 1 hour)
- Run a full restore drill quarterly: restore cluster objects from Velero, verify PVs mount correctly, run smoke tests
- Document the restore sequence — which namespaces restore first, which depend on others
- Verify IAM roles for backup operations have not drifted from the required permissions
How do you implement these practices in a 90-day operational plan?
The goal of the first 90 days is to get from “cluster exists” to “cluster is production-grade and observable.” Three phases, explicit deliverables.
Phase 1: Stabilize (weeks 0–2)
- Migrate cluster provisioning to Terraform or eksctl; commit config to Git
- Enable control-plane logging and Container Insights
- Apply default-deny NetworkPolicy to all production namespaces
- Verify PodDisruptionBudgets exist for all stateful workloads
- Configure Velero with daily backups to S3
Phase 2: Secure and instrument (weeks 2–6)
- Enable IRSA for all pods currently using instance roles
- Enable KMS envelope encryption for Secrets
- Enforce Pod Security Standards at
restrictedprofile - Deploy Kyverno with image signing verification policies
- Set up SLO-driven alerting in Grafana or CloudWatch
- Run first Velero restore drill and document findings
Phase 3: Scale and optimize (weeks 6–12)
- Migrate from Cluster Autoscaler to Karpenter with consolidation enabled
- Run VPA in recommendation mode; apply right-sizing to top 10 Deployments by cost
- Move batch and CI workloads to Spot NodePools
- Implement GitOps promotion workflow (dev → staging → production)
- Establish monthly cost review cadence with per-team tagging reports
Pro Tip: The single highest-ROI action in weeks 0–2 is enabling control-plane logging. It costs almost nothing and is the difference between a 20-minute incident diagnosis and a 4-hour one.
Sample IaC snippet (eksctl)
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: production
region: us-east-1
version: "1.30"
managedNodeGroups:
- name: app-nodes
instanceType: m5.2xlarge
minSize: 2
maxSize: 20
desiredCapacity: 3
volumeSize: 100
volumeType: gp3
labels:
role: application
cloudWatch:
clusterLogging:
enableTypes: ["api","audit","authenticator","controllerManager","scheduler"]
IT-Magic typically operationalizes EKS for clients by delivering monitoring handover documentation, runbook creation for the top 10 failure modes, remediation automation for common alerts, and 24/7 infrastructure support from day one of production traffic.
How do taints and tolerations improve workload scheduling?
Taints and tolerations are the mechanism for dedicating nodes to specific workload classes without relying on namespace boundaries alone.
A taint on a node (kubectl taint nodes <node> dedicated=gpu:NoSchedule) prevents any pod from scheduling there unless the pod has a matching toleration. This is how you reserve GPU nodes for ML workloads, isolate security-sensitive pods, or dedicate nodes to system add-ons like monitoring agents.
Common production patterns:
- System node taint:
CriticalAddonsOnly=true:NoScheduleon system node groups keeps application pods off nodes running CoreDNS and the VPC CNI - Spot taint:
spot=true:NoScheduleon Spot nodes, with tolerations only on workloads explicitly designed to handle interruption - GPU taint:
nvidia.com/gpu=present:NoScheduleapplied automatically by the GPU device plugin; only pods requestingnvidia.com/gpuresources get scheduled there
Combine taints with nodeAffinity for positive selection and topologySpreadConstraints for distribution. Taints alone prevent unwanted scheduling; affinity rules pull workloads toward the right nodes. Using both together gives you precise placement without over-constraining the scheduler.
For Karpenter, define NodePool-level taints in the spec.template.spec.taints field. Karpenter will only provision a node from that NodePool when a pending pod has a matching toleration, which prevents over-provisioning dedicated capacity.
Key Takeaways
Running EKS in production requires security, reliability, and observability to be built in from day one, not retrofitted after the first incident.
| Point | Details |
|---|---|
| IRSA over instance roles | Bind every pod to a scoped IAM role via OIDC; audit with CloudTrail AssumeRoleWithWebIdentity events. |
| IaC is non-negotiable | Provision all clusters with Terraform or eksctl; never use the Console for production changes. |
| Karpenter for autoscaling | Karpenter provisions nodes significantly faster and consolidates continuously, compared to the slower provisioning speed of Cluster Autoscaler. |
| Default-deny networking | Apply a default-deny NetworkPolicy to every production namespace before workloads deploy. |
| IT-Magic for managed operations | IT-Magic delivers 24/7 EKS infrastructure management, runbook creation, and remediation automation for production clusters. |
The controls that actually matter in practice
The official AWS EKS best practices documentation covers the right ground. What it cannot tell you is which gaps show up most often in real clusters that have been running for more than six months.
The pattern that causes the most incidents is not a missing security control. It is manual drift. A cluster that was provisioned with Terraform but has had node groups, security groups, and add-on versions modified through the Console is no longer the cluster the IaC describes. The next Terraform apply will either fail or overwrite something unexpected. The fix is not better tooling — it is a team norm that Console changes to production infrastructure are not allowed, enforced by IAM policy if necessary.
The second most common problem is CPU-only autoscaling. A service that is CPU-idle but saturated on database connections or request queue depth will not trigger HPA until it is already dropping requests. The teams that catch this early are the ones that defined SLOs before they wrote alert rules, because SLOs force you to think about what “working” actually means for your service.
Image signing is the control most teams skip because it feels like overhead until a supply chain incident makes it feel like the most obvious thing in the world. Cosign and Kyverno together take a few hours to configure. The blast radius of an unsigned image making it to production is much larger.
The last pitfall worth naming: mixing production and development workloads in the same cluster to save money. The cost savings are real. The blast radius when a dev workload exhausts node capacity or triggers a misconfigured NetworkPolicy is also real, and it tends to happen at the worst possible time.
IT-Magic handles the operational weight of production EKS
Running EKS at production quality is a full-time operational commitment, not a one-time setup. The security controls need auditing, the upgrade path needs testing, the cost governance needs a monthly review, and the runbooks need to be current when an incident fires at 2 AM.
IT-Magic is an AWS Advanced Tier Services Partner that has delivered 700+ infrastructure projects since 2010, with a team of certified AWS experts in DevOps, security, and networking. For EKS specifically, engagements typically cover cluster architecture design, IaC migration, security hardening to PCI DSS or SOC 2 standards, Karpenter migration, and 24/7 managed operations with defined SLAs.
What clients get from a managed EKS engagement:
- A cluster provisioned entirely through IaC with GitOps promotion workflows
- Security posture aligned to AWS best practices and compliance requirements
- Cost governance with monthly reporting and right-sizing recommendations
- 24/7 incident response with documented runbooks for the top failure modes
If your team is spending engineering time on cluster maintenance instead of product work, or if a compliance audit is coming up and your EKS security posture is not documented, talk to IT-Magic’s AWS consultants about a scoped engagement. For security-specific work, the AWS security consulting practice covers EKS hardening, IRSA audits, and compliance evidence packages.
Useful sources
The following references back the recommendations in this article and are worth bookmarking for deeper reading:
- Amazon EKS Best Practices Guides — the official AWS guide covering security, reliability, and cost; the primary reference for production EKS configuration
- AWS EKS Best Practices GitHub (aws/aws-eks-best-practices) — the open-source companion with detailed scalability and data-plane guidance including Karpenter benchmarks
- Karpenter documentation — NodePool configuration, consolidation policies, and instance selection reference
- Cluster Autoscaler documentation — node group scaling configuration and FAQ
- IRSA documentation (EKS User Guide) — OIDC setup, trust policy scoping, and credential injection details
- Velero documentation — backup schedules, restore procedures, and AWS plugin configuration
- ECR enhanced scanning documentation — Inspector-powered vulnerability scanning for container images
- Amazon EKS Node and Workload Efficiency — right-sizing guidance, HPA v2 metrics, and kubelet tuning
- OWASP Docker Security Cheat Sheet — container hardening baseline applicable to EKS pod specs
- EKS Production Cluster Setup Guide (DevOpsil) — practical eksctl and Terraform configuration examples with cost optimization patterns
These sources, combined with IT-Magic’s operational experience across 300+ client environments, form the evidence base for the recommendations throughout this article.
FAQ
What is IRSA and why does it matter for EKS security?
IRSA (IAM Roles for Service Accounts) lets pods assume scoped IAM roles via OIDC without storing credentials. It replaces instance-level IAM roles, which grant every pod on a node the same permissions regardless of what each pod actually needs.
How fast does Karpenter provision new nodes compared to Cluster Autoscaler?
Karpenter provisions nodes in 30–60 seconds by calling the EC2 API directly. Cluster Autoscaler typically takes 3–5 minutes because it works through Auto Scaling Groups.
What is the correct upgrade order for an EKS cluster?
Upgrade the control plane first, then managed node groups, then EKS managed add-ons. Test in staging before touching production, and verify PodDisruptionBudgets are in place before draining nodes.
How do you back up an EKS cluster?
Use Velero for cluster object backups and EBS snapshots for persistent volume recovery. Store backups in a separate AWS region and run restore drills quarterly to verify the process works before you need it.
Can IT-Magic help with EKS security hardening and compliance?
Yes. IT-Magic’s AWS security consulting practice covers IRSA audits, Pod Security Standards enforcement, KMS encryption setup, and compliance evidence packages for PCI DSS, SOC 2, and HIPAA workloads running on EKS.
Recommended
- How to Reduce EKS Costs: A 2026 Engineer’s Guide
- AWS EKS explained: streamline Kubernetes for scalable success
- ECS vs EKS: Which is Better for Container Orchestration?
- ECS on AWS: Scale containers reliably in 2026
Alexander founded IT-Magic, an AWS Advanced Tier Services Partner delivering DevOps, cloud architecture, and managed services since 2010. He holds:
- AWS Certified Solutions Architect – Professional
- AWS Certified DevOps Engineer – Professional
- AWS Certified Security – Specialty
- AWS Certified Advanced Networking – Specialty
Talk to a certified AWS team trusted by INTERTOP, Foxtrot, Pandora, and J.Hilburn.
Get a free consultation


