What Is Amazon EKS?
Amazon Elastic Kubernetes Service (Amazon EKS) is a managed Kubernetes service from AWS. It allows teams to deploy, run, and scale containerized applications using standard Kubernetes APIs without operating the Kubernetes control plane themselves. AWS manages the control plane infrastructure, including the API servers and distributed cluster state, while applications run on worker capacity provided through managed node groups, self-managed nodes, AWS Fargate, or EKS Auto Mode.
EKS is commonly used for microservices, REST APIs, background workers, scheduled jobs, and container-based application platforms. It combines Kubernetes orchestration with AWS networking, IAM, storage, and monitoring services. However, managed Kubernetes is not maintenance-free. Teams still need to design application deployments, resource limits, networking, access control, cluster upgrades, autoscaling, and failure recovery.
Table of Contents
- What Amazon EKS Provides
- How Amazon EKS Works
- Networking, IAM, and Storage
- Scaling, Deployments, and Cluster Upgrades
- Production Design Example: Multi-Service SaaS Platform
- Ready-to-Use Example: Deploy FastAPI on Amazon EKS
- Performance, Pricing, and Observability
- Common Mistakes and Production Checklist
- Frequently Asked Questions
- Conclusion
What Amazon EKS Provides
Kubernetes is an open-source orchestration platform that manages containerized workloads across clusters of machines. It schedules Pods, maintains desired application state, provides service discovery, and supports rolling updates and autoscaling.
EKS provides Kubernetes as an AWS managed service. Instead of installing and maintaining Kubernetes API servers, etcd, and control-plane infrastructure, teams create an EKS cluster and interact with it using familiar Kubernetes tools such as kubectl, Helm, and GitOps controllers.
Amazon EKS vs. Self-Managed Kubernetes
A self-managed Kubernetes cluster requires engineers to install, secure, monitor, and upgrade the control plane as well as operate the worker infrastructure.
EKS reduces those responsibilities, but it does not eliminate the operational work involved in running workloads.
| Responsibility | Self-Managed Kubernetes | Amazon EKS |
|---|---|---|
| Control-plane infrastructure | Customer-managed | AWS-managed |
| Kubernetes API availability | Customer-managed | AWS-managed |
| Worker compute | Customer-managed | Multiple managed and self-managed options |
| Application manifests | Customer-managed | Customer-managed |
| Pod resource configuration | Customer-managed | Customer-managed |
| Application security | Customer-managed | Shared responsibility |
| Kubernetes version planning | Customer-managed | Customer-planned with AWS tooling |
The main advantage is access to the Kubernetes ecosystem without directly operating control-plane servers. Helm charts, Kubernetes operators, Deployments, StatefulSets, and standard workload definitions can run on EKS, subject to compatibility and infrastructure requirements.
For the underlying orchestration model, see What Is Kubernetes?.
Amazon EKS vs. ECS and AWS Lambda
AWS provides several ways to run application code. EKS is not automatically the best option simply because an application uses containers.
| Characteristic | Amazon EKS | Amazon ECS | AWS Lambda |
|---|---|---|---|
| Orchestration model | Kubernetes | AWS-native services and tasks | Function invocations |
| Workload unit | Pod | Task | Function |
| Long-running services | Yes | Yes | Not its primary execution model |
| Customization | Extensive Kubernetes ecosystem | AWS-native integrations | Managed function runtime |
| Operational complexity | Higher platform complexity | Often simpler for AWS-only workloads | Often simpler for short event-driven jobs |
For a handful of AWS-hosted APIs, ECS can be simpler to operate. EKS becomes more attractive when teams need Kubernetes-native controllers, operators, Helm-based deployments, sophisticated scheduling, or a standardized platform across many services.
How Amazon EKS Works
An EKS cluster has two broad layers: the Kubernetes control plane and the compute infrastructure where application Pods run. AWS operates the control plane, while workload compute is provided through the deployment mode selected by the customer.
The Kubernetes control plane exposes an API for declaring desired state. Controllers reconcile that state, the scheduler selects suitable nodes, and node agents start and supervise application containers.
Managed Kubernetes Control Plane
The control plane contains the components responsible for Kubernetes cluster coordination:
- API server: Receives Kubernetes API requests from tools, controllers, and workloads.
- etcd: Stores Kubernetes configuration and cluster state.
- Scheduler: Selects nodes for Pods awaiting placement.
- Controllers: Reconcile resources such as Deployments and ReplicaSets.
AWS manages control-plane availability and infrastructure. EKS uses AWS-managed infrastructure distributed across Availability Zones to reduce the impact of individual infrastructure failures.
However, a highly available control plane does not guarantee the application is highly available. If all application replicas run on one worker node or depend on one unhealthy database, the application can still fail.
Worker Nodes, Pods, and Scheduling
Worker nodes provide the CPU, memory, networking, and container runtime required to execute Pods. In managed node group configurations, these nodes are typically EC2 instances registered with the EKS cluster.
A Pod contains one or more containers that share network and lifecycle boundaries. A Deployment manages ReplicaSets that maintain the desired number of application Pods.
For example, a Deployment with three replicas expresses a request for three application Pods. Kubernetes attempts to schedule and maintain those replicas, subject to available capacity and scheduling constraints.
Pod CPU and memory requests influence scheduling. If no node has sufficient allocatable resources, the Pod remains pending until capacity or configuration changes.
See Kubernetes Explained: Pods, Nodes, and Clusters for details about these boundaries.
Managed Node Groups, Fargate, and Auto Mode
EKS supports different approaches to application compute. They share the Kubernetes API but differ in infrastructure responsibilities and workload compatibility.
- EKS managed node groups: AWS automates supported provisioning and lifecycle operations for EC2 worker nodes. Teams still select instance types, capacity, scaling configuration, and many node-management settings.
- Self-managed nodes: Teams control EC2-backed node configuration more directly, including their own node lifecycle automation.
- AWS Fargate: Runs eligible Pods without managing EC2 worker instances. Supported Kubernetes capabilities and workload types have platform-specific restrictions.
- EKS Auto Mode: Extends AWS infrastructure management to node provisioning, autoscaling, supported storage integration, networking, and load balancing.
EKS Auto Mode is particularly useful when teams want standard Kubernetes APIs but fewer infrastructure components to install and maintain. Its managed capabilities also come with specific customization and compatibility constraints, so it should be evaluated against the requirements of existing controllers and workloads.
Traditional EKS with managed node groups remains appropriate when teams need greater control over worker instance types, add-ons, scheduling configuration, and cluster infrastructure.
Networking, IAM, and Storage
EKS connects Kubernetes workloads to AWS networking and security infrastructure. Pods require network addresses, Services provide stable communication, and external traffic must be routed through suitable load balancing or ingress components.
Identity and authorization involve both AWS IAM and Kubernetes permissions. Keeping these responsibilities separate prevents broad infrastructure access from becoming accidental application access.
VPC Networking and Load Balancing
In traditional EKS clusters, the Amazon VPC CNI commonly assigns VPC-network addresses to Pods. This allows workloads to communicate using familiar AWS networking controls, while also making subnet address capacity an important scaling consideration.
Typical production networking uses:
- Private subnets: Host worker nodes and application Pods where supported by the compute configuration.
- Public subnets: Host internet-facing load balancers.
- Security groups: Control network access at supported AWS interfaces.
- Kubernetes Services: Provide stable internal service addresses.
- Ingress or Gateway resources: Define application-level routing through compatible controllers.
- VPC endpoints or NAT: Provide access to ECR, CloudWatch, STS, and other required services.
With traditional EKS, exposing an HTTP application through an Application Load Balancer commonly requires the AWS Load Balancer Controller and appropriate IAM permissions. EKS Auto Mode has integrated load-balancing capabilities that reduce this setup for supported resources.
Creating an Ingress resource alone does not guarantee an ALB will appear. The required controller or integrated implementation must be available and correctly configured.
IAM, Kubernetes RBAC, and Pod Identity
EKS security involves multiple authorization layers:
- IAM: Controls permissions to AWS APIs and resources.
- EKS access entries: Associate AWS principals with Kubernetes access policies or Kubernetes identity mappings.
- Kubernetes RBAC: Controls permissions to Kubernetes resources such as Pods, Deployments, and Secrets.
- EKS Pod Identity: Associates IAM roles with Kubernetes service accounts for supported workload access to AWS services.
For example, an application Pod that uploads documents to S3 should receive a narrowly scoped IAM role through an appropriate workload identity mechanism. Giving broad S3 permissions to every worker node is generally undesirable.
Pod Identity reduces the need for long-lived AWS credentials inside containers. Traditional EKS configurations require the appropriate Pod Identity agent where applicable; EKS Auto Mode provides the relevant integration without separately installing that agent.
Authentication to the Kubernetes API and authorization to AWS services are separate operations. A developer's ability to call aws eks describe-cluster does not automatically grant unrestricted kubectl access.
Persistent Storage and Configuration
Containers and Pods should generally be treated as replaceable. Files written to a container's local filesystem are not a safe location for authoritative application data.
Kubernetes uses PersistentVolumes and PersistentVolumeClaims to connect workloads to supported persistent storage systems. On AWS, this commonly includes EBS-backed block storage or EFS-backed shared filesystem storage through compatible CSI drivers and configurations.
Applications commonly use external managed services for durable state:
- Amazon RDS: Transactional relational data.
- Amazon DynamoDB: Key-value and document workloads.
- Amazon S3: Object storage for files and datasets.
- Amazon EFS: Shared filesystem workloads.
Use ConfigMaps for nonsensitive configuration and appropriate Secret-management mechanisms for credentials. Kubernetes Secrets are not a substitute for comprehensive secret access controls, encryption configuration, or rotation procedures.
Scaling, Deployments, and Cluster Upgrades
There are two different scaling problems in Kubernetes: determining how many Pods an application needs and ensuring the cluster has sufficient compute capacity to run them.
Scaling the number of Pods does not automatically add nodes in every EKS configuration. Both layers must be planned and coordinated.
Pod and Node Autoscaling
The Horizontal Pod Autoscaler (HPA) can adjust a workload's replica count according to supported resource or custom metrics.
For example, an API might scale from three to twelve Pods based on CPU utilization. This increases desired workload capacity, but new Pods cannot run unless the cluster has sufficient available resources.
Node scaling can be handled by components such as Cluster Autoscaler, Karpenter, or EKS Auto Mode, depending on cluster configuration.
Karpenter and Auto Mode can provision capacity based on pending workload requirements rather than relying only on fixed node-group sizes.
Accurate resource requests are essential. Understated requests can cause resource contention, while significantly overstated requests can waste capacity and trigger unnecessary node provisioning.
Rolling Deployments and Health Checks
Kubernetes Deployments support rolling updates. New Pods become available while old Pods are gradually removed according to the Deployment strategy and readiness conditions.
Important controls include:
- Readiness probes: Indicate whether a Pod should receive application traffic.
- Liveness probes: Detect conditions that justify restarting a container.
- Startup probes: Protect slow-starting applications from premature liveness failures.
- PodDisruptionBudgets: Limit voluntary disruptions to supported workload replicas.
- Topology spread constraints: Distribute Pods across nodes or Availability Zones.
A Deployment showing the desired number of Pods does not prove that the service is healthy. Readiness failures, DNS problems, exhausted database pools, and application errors may still affect users.
For the behavior of rolling updates and rollbacks, see What Is Rolling Deployment?.
Kubernetes Version Upgrades
Amazon EKS supports Kubernetes minor versions through standard and extended support periods. As of October 2026, standard support lasts approximately 14 months from the version's EKS release, followed by an additional extended support period at a higher cluster fee.
Control-plane upgrades must be planned together with node groups, kubelet versions, add-ons, API compatibility, admission controllers, and application manifests.
Before upgrading, check for deprecated APIs and controller compatibility. Test representative workloads, then upgrade the cluster and its supporting components according to AWS-supported version-skew requirements.
EKS can automate certain upgrade operations, but application compatibility remains the team's responsibility. A supported Kubernetes version does not guarantee that every Helm chart or custom operator will work without changes.
Production Design Example: Multi-Service SaaS Platform
Consider a SaaS platform with a public FastAPI service, several internal APIs, SQS workers, and scheduled reporting jobs. The system uses PostgreSQL for transactional data, S3 for documents, and Redis for caching.
EKS is attractive when the platform team wants common deployment tooling, standardized service definitions, workload policies, autoscaling, and environment management across many independent teams.
Production Architecture
A production architecture can use the following components:
- Application Load Balancer: Accepts HTTPS requests and routes them through supported ingress configuration.
- EKS cluster: Runs application Deployments, Services, workers, and scheduled Jobs.
- Managed nodes or Auto Mode: Provides scalable compute capacity across multiple Availability Zones.
- Horizontal Pod Autoscaler: Adjusts API replica counts using appropriate metrics.
- Amazon RDS: Stores transactional records.
- Amazon SQS: Buffers background processing tasks.
- Amazon S3: Stores uploaded and generated documents.
- EKS Pod Identity: Assigns specific AWS permissions to workload service accounts.
- CloudWatch or compatible observability tools: Collects metrics, logs, and traces.
API Pods can scale with request traffic while queue workers scale with backlog. The two workloads use separate Deployments and can have different resource requests, rollout strategies, and scheduling constraints.
Production databases typically remain outside the cluster using managed database services. This avoids coupling critical persistent data availability to routine application node replacement.
Failure Scenario: Availability Zone Outage
Suppose an EKS cluster operates in three Availability Zones with six API Pods. If four Pods are placed in one Zone and two in another, losing the first Zone removes most of the application's capacity.
Kubernetes may attempt to schedule replacements, but sufficient nodes, subnet addresses, and available compute capacity must exist in surviving Zones.
A more resilient design spreads replicas across failure domains and maintains enough reserve or quickly provisionable capacity to restore service. The load balancer must also route traffic only to available, healthy endpoints.
PodDisruptionBudgets help control voluntary disruptions such as node maintenance, but they cannot prevent an infrastructure outage.
For a broader discussion of failure-domain design, see Designing Highly Available Cloud Systems.
Ready-to-Use Example: Deploy FastAPI on Amazon EKS
This example creates an EKS cluster with a managed EC2 node group, builds a FastAPI image, pushes it to ECR, and deploys the application using Kubernetes Deployment and Service resources.
It assumes an existing VPC with at least two private subnets in different Availability Zones. The subnets must have the required outbound connectivity through NAT or appropriately configured VPC endpoints, including access needed for ECR image pulls, AWS APIs, and the Kubernetes control plane.
The sample uses kubectl port-forward rather than creating a public load balancer. This keeps the deployment focused on Kubernetes fundamentals while avoiding unnecessary public ingress and additional load-balancing infrastructure.
1. Prepare the Application
Install Docker, Terraform, AWS CLI, and kubectl. Configure an AWS identity permitted to create EKS clusters, IAM roles, ECR repositories, and related resources.
Create the following project structure:
eks-demo/
app/
main.py
requirements.txt
Dockerfile
infrastructure/
main.tf
outputs.tf
terraform.tfvars
kubernetes/
deployment.yaml
Create app/main.py:
import os
import socket
from fastapi import FastAPI
app = FastAPI()
@app.get("/health")
def health():
# Basic process liveness endpoint.
return {"status": "ok"}
@app.get("/ready")
def ready():
# In production, check only the dependencies
# required to serve normal requests.
return {"ready": True}
@app.get("/")
def index():
return {
"message": "Hello from Amazon EKS!",
"pod": socket.gethostname(),
"version": os.getenv("APP_VERSION", "1.0.0"),
}
Create app/requirements.txt:
fastapi>=0.115,<1
uvicorn>=0.30,<1
For production builds, pin and lock dependencies to tested versions. Floating version ranges are convenient for demonstrations but reduce reproducibility.
Create app/Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY main.py .
# Avoid running the application as root.
RUN useradd --create-home appuser
USER appuser
EXPOSE 8000
CMD [
"uvicorn",
"main:app",
"--host", "0.0.0.0",
"--port", "8000"
]
The application exposes separate liveness and readiness endpoints. The example keeps readiness simple; production applications should distinguish between temporary unavailability and conditions that justify restarting the process.
2. Create the EKS Cluster with Terraform
Create infrastructure/main.tf. The example uses an existing VPC and creates the cluster IAM role, node IAM role, EKS cluster, managed node group, and ECR repository.
terraform {
required_version = ">= 1.5.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
variable "private_subnet_ids" {
type = list(string)
description = "Private subnets across at least two AZs."
validation {
condition = length(var.private_subnet_ids) >= 2
error_message = "Provide at least two subnets."
}
}
variable "admin_cidr" {
type = string
description = "Public IPv4 CIDR allowed to use the Kubernetes API."
}
# -----------------------------
# IAM roles
# -----------------------------
data "aws_iam_policy_document" "cluster_trust" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["eks.amazonaws.com"]
}
}
}
resource "aws_iam_role" "cluster" {
name_prefix = "eks-demo-cluster-"
assume_role_policy = data.aws_iam_policy_document.cluster_trust.json
}
resource "aws_iam_role_policy_attachment" "cluster" {
role = aws_iam_role.cluster.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
}
data "aws_iam_policy_document" "node_trust" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["ec2.amazonaws.com"]
}
}
}
resource "aws_iam_role" "nodes" {
name_prefix = "eks-demo-nodes-"
assume_role_policy = data.aws_iam_policy_document.node_trust.json
}
resource "aws_iam_role_policy_attachment" "nodes" {
role = aws_iam_role.nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
}
resource "aws_iam_role_policy_attachment" "ecr" {
role = aws_iam_role.nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly"
}
# Demo simplification: for production, assign VPC CNI
# permissions to its own IAM service-account role.
resource "aws_iam_role_policy_attachment" "cni" {
role = aws_iam_role.nodes.name
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
}
# -----------------------------
# Managed Kubernetes cluster
# -----------------------------
resource "aws_eks_cluster" "demo" {
name = "eks-demo"
role_arn = aws_iam_role.cluster.arn
version = "1.36"
vpc_config {
subnet_ids = var.private_subnet_ids
endpoint_private_access = true
endpoint_public_access = true
public_access_cidrs = [
var.admin_cidr
]
}
access_config {
authentication_mode = "API"
# Allow the cluster creator to administer
# this disposable demonstration cluster.
bootstrap_cluster_creator_admin_permissions = true
}
upgrade_policy {
support_type = "STANDARD"
}
depends_on = [
aws_iam_role_policy_attachment.cluster
]
}
# Use managed EKS add-ons.
resource "aws_eks_addon" "vpc_cni" {
cluster_name = aws_eks_cluster.demo.name
addon_name = "vpc-cni"
}
resource "aws_eks_addon" "kube_proxy" {
cluster_name = aws_eks_cluster.demo.name
addon_name = "kube-proxy"
}
resource "aws_eks_node_group" "nodes" {
cluster_name = aws_eks_cluster.demo.name
node_group_name = "general"
node_role_arn = aws_iam_role.nodes.arn
subnet_ids = var.private_subnet_ids
capacity_type = "ON_DEMAND"
instance_types = ["t3.medium"]
ami_type = "AL2023_x86_64_STANDARD"
scaling_config {
desired_size = 2
min_size = 2
max_size = 4
}
update_config {
max_unavailable = 1
}
depends_on = [
aws_iam_role_policy_attachment.nodes,
aws_iam_role_policy_attachment.ecr,
aws_iam_role_policy_attachment.cni,
aws_eks_addon.vpc_cni
]
}
resource "aws_eks_addon" "coredns" {
cluster_name = aws_eks_cluster.demo.name
addon_name = "coredns"
depends_on = [
aws_eks_node_group.nodes
]
}
# -----------------------------
# Application image registry
# -----------------------------
resource "aws_ecr_repository" "api" {
name = "eks-demo-api"
image_scanning_configuration {
scan_on_push = true
}
}
This configuration restricts public Kubernetes API access to the supplied CIDR and enables the private endpoint for cluster-internal communication. The managed node group runs two t3.medium instances.
The EKS version is pinned for reproducibility; update it to a currently supported release compatible with the selected add-ons and node images when deploying. The example does not install an autoscaler, so the node group's maximum size does not mean nodes will automatically scale based on pending Pods.
The VPC CNI permissions are placed on the node role to simplify the demo. Production clusters should prefer separately scoped add-on permissions and appropriate workload identities instead of expanding general node permissions.
Create infrastructure/outputs.tf:
output "cluster_name" {
value = aws_eks_cluster.demo.name
}
output "cluster_endpoint" {
value = aws_eks_cluster.demo.endpoint
}
output "ecr_repository_url" {
value = aws_ecr_repository.api.repository_url
}
Create infrastructure/terraform.tfvars using your actual private subnet identifiers and a restricted administrator CIDR:
private_subnet_ids = [
"subnet-0123456789abcdef0",
"subnet-0fedcba9876543210"
]
# Replace with your public IP address and /32.
admin_cidr = "203.0.113.10/32"
These are example identifiers. Your subnets must belong to a suitable VPC, span distinct Availability Zones, and provide working network paths for node registration and ECR image pulls. Because the control plane endpoint also has public access enabled, the management workstation must use a public IP included in admin_cidr.
3. Configure Kubernetes Deployment and Service
Create kubernetes/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: eks-demo-api
labels:
app: eks-demo-api
spec:
replicas: 2
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
selector:
matchLabels:
app: eks-demo-api
template:
metadata:
labels:
app: eks-demo-api
spec:
terminationGracePeriodSeconds: 30
containers:
- name: api
# Replaced during deployment with the ECR URI.
image: IMAGE_URI
ports:
- name: http
containerPort: 8000
env:
- name: APP_VERSION
value: "1.0.0"
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
memory: "256Mi"
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 2
periodSeconds: 5
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 10
periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
name: eks-demo-api
spec:
type: ClusterIP
selector:
app: eks-demo-api
ports:
- name: http
port: 80
targetPort: http
The Deployment maintains two replicas and uses readiness checks to avoid routing Service traffic to Pods before they are ready.
The Service is internal to Kubernetes. It does not automatically provision an AWS load balancer or expose the application to the internet.
For a real production application, also consider topology spread constraints, PodDisruptionBudgets, startup probes, a dedicated Kubernetes service account, and network policies supported by the cluster's networking implementation.
4. Build, Deploy, and Test
Provision the ECR repository first, push the container image, create the rest of the cluster resources, and configure kubectl access.
export AWS_REGION="us-west-2"
cd infrastructure
terraform init
terraform fmt
terraform validate
# Bootstrap the ECR repository.
terraform apply -target=aws_ecr_repository.api
ECR_URL="$(terraform output -raw ecr_repository_url)"
# Authenticate Docker.
aws ecr get-login-password \
--region "$AWS_REGION" \
| docker login \
--username AWS \
--password-stdin \
"$(echo "$ECR_URL" | cut -d/ -f1)"
# Build and push the container.
cd ../app
docker build -t eks-demo-api:1.0.0 .
docker tag \
eks-demo-api:1.0.0 \
"$ECR_URL:1.0.0"
docker push "$ECR_URL:1.0.0"
# Deploy EKS and its node group.
cd ../infrastructure
terraform plan
terraform apply
# Configure kubectl authentication and endpoint.
aws eks update-kubeconfig \
--region "$AWS_REGION" \
--name "$(terraform output -raw cluster_name)"
# Check cluster connectivity and nodes.
kubectl get nodes
# Render the deployment with the pushed image URI.
cd ..
sed "s|IMAGE_URI|$ECR_URL:1.0.0|g" \
kubernetes/deployment.yaml \
> /tmp/eks-demo-deployment.yaml
kubectl apply -f /tmp/eks-demo-deployment.yaml
# Check rollout progress.
kubectl rollout status deployment/eks-demo-api
# Inspect the running Pods and Service.
kubectl get pods -o wide
kubectl get service eks-demo-api
The cluster is managed through standard Kubernetes commands. The rendered deployment uses the image stored in your ECR repository.
To test the API without exposing it publicly, forward a local port to the Kubernetes Service:
# Run this in one terminal.
kubectl port-forward service/eks-demo-api 8000:80
# In another terminal:
curl http://127.0.0.1:8000/health
curl http://127.0.0.1:8000/ready
curl http://127.0.0.1:8000/
The application should return a healthy response and identify its running Pod.
Port forwarding is appropriate for testing and troubleshooting, not for serving production traffic. Production access should use an appropriately secured ingress or load-balancing configuration.
5. Scale, Update, and Clean Up
You can adjust the number of application replicas and inspect how Kubernetes schedules the resulting Pods.
# Scale the API workload.
kubectl scale deployment/eks-demo-api --replicas=3
# Observe placement and status.
kubectl get pods -o wide
# Inspect resource requests and events.
kubectl describe deployment eks-demo-api
kubectl get events --sort-by=.lastTimestamp
# Check rollout history.
kubectl rollout history deployment/eks-demo-api
# View application logs.
kubectl logs deployment/eks-demo-api --tail=50
# Restore the original replica count.
kubectl scale deployment/eks-demo-api --replicas=2
# Delete workload resources before cluster teardown.
kubectl delete -f /tmp/eks-demo-deployment.yaml
# Delete infrastructure.
cd infrastructure
terraform destroy
To release a new version, build and push a new uniquely tagged or digest-pinned image, update the Deployment image, and monitor kubectl rollout status. If the rollout fails, use kubectl describe, Pod logs, and the rollout history to investigate before deciding whether to roll back.
Terraform may not be able to delete a nonempty ECR repository. Remove the disposable image before destroying the repository, or use an explicitly controlled repository cleanup process.
The EKS cluster, EC2 nodes, EBS volumes, network resources, image storage, and related services can incur charges. Confirm that the node group and cluster have been deleted after completing the demonstration.
Performance, Pricing, and Observability
EKS can scale to large containerized platforms, but application performance depends on more than Kubernetes. CPU and memory requests, node availability, Pod startup time, storage performance, network behavior, and downstream dependencies all influence request latency and throughput.
The cost of running a Kubernetes platform also includes control-plane charges and the infrastructure used by application workloads.
Understanding EKS Costs
Amazon EKS has a per-cluster charge in addition to underlying infrastructure charges. AWS currently lists standard Kubernetes version support at $0.10 per cluster-hour and extended support at $0.60 per cluster-hour for the standard EKS cluster pricing model.
Other cost drivers can include:
- EC2 worker nodes or Fargate compute.
- EKS Auto Mode charges where applicable.
- Application Load Balancers and Network Load Balancers.
- EBS and EFS storage.
- NAT gateways, VPC endpoints, and network transfer.
- Public IPv4 addresses.
- CloudWatch logs and monitoring.
- Amazon ECR storage and image transfer.
A small cluster with limited traffic can still have meaningful baseline costs because the Kubernetes control plane and minimum worker capacity remain provisioned.
For production cost optimization, measure workload requests versus actual usage, identify idle nodes, and evaluate node packing, suitable instance families, Spot capacity for tolerant workloads, and more automated capacity provisioning.
Monitoring and Troubleshooting
Production EKS monitoring should cover both Kubernetes resources and AWS infrastructure.
Important signals include:
- Pending Pods: Scheduling constraints or insufficient node capacity.
- Pod restarts: Application crashes, probe failures, or resource exhaustion.
- OOMKilled containers: Memory limits or application memory problems.
- Node conditions: Worker availability and resource pressure.
- Deployment availability: Difference between desired, available, and updated replicas.
- API latency and error rate: User-visible application health.
- CPU and memory utilization: Workload and node resource usage.
- Cluster autoscaler behavior: Whether pending workloads trigger suitable capacity.
- Load balancer target health: Whether application endpoints are reachable and ready.
Useful tools include kubectl describe, kubectl logs, Kubernetes events, CloudWatch, Prometheus-compatible metrics, and OpenTelemetry-based tracing.
Metrics show when performance changes, logs help identify the source of errors, and traces connect requests across services. For serious production incidents, all three are useful.
Common Mistakes and Production Checklist
EKS simplifies Kubernetes control-plane operations but still requires a carefully operated application platform. Many incidents involve mistakes in resource sizing, Pod placement, IAM permissions, networking, or deployment procedures.
The most effective approach is to treat cluster infrastructure and application workloads as separately managed layers with clear ownership and observable health.
Common EKS Mistakes
Common mistakes include:
- Assuming EKS manages everything: Worker capacity, applications, and many add-ons still require management.
- Confusing Pod scaling with node scaling: Replicas remain pending when compute capacity is unavailable.
- Ignoring subnet IP capacity: Pod networking can exhaust available addresses.
- Using broad node IAM roles: Applications receive more AWS permissions than necessary.
- Exposing the Kubernetes API unnecessarily: Cluster management access becomes a security risk.
- Deploying without readiness probes: Uninitialized applications receive traffic.
- Omitting resource requests: Scheduling and scaling decisions become unreliable.
- Keeping critical state in container filesystems: Data disappears when Pods are replaced.
- Ignoring Kubernetes version lifecycle: Deprecated APIs and extended support charges accumulate.
- Relying on one Availability Zone: Multiple replicas share the same infrastructure failure boundary.
- Installing unnecessary controllers: Platform cost, complexity, and security exposure increase.
Production Checklist
Before running a critical application on Amazon EKS, verify that:
- The Kubernetes version is supported and an upgrade process exists.
- API server endpoint access is appropriately restricted.
- Worker nodes and Pods use suitable private networking.
- Workload IAM permissions use a least-privilege identity mechanism.
- Application replicas are distributed across failure domains.
- CPU and memory requests reflect observed workload requirements.
- Readiness, liveness, and startup probes are configured appropriately.
- Pod autoscaling and node provisioning are coordinated.
- Ingress and load-balancing controllers are installed and secured where needed.
- Persistent data has a suitable storage and recovery design.
- Application and cluster logs, metrics, and traces are collected.
- Deployments have tested rollback procedures.
- Node, control-plane, network, and storage costs are monitored.
Frequently Asked Questions
Amazon EKS is frequently compared with Kubernetes, ECS, and serverless container platforms. The key distinction is which parts of orchestration and infrastructure AWS manages and which decisions remain with the application team.
What Is Amazon EKS Used For?
Amazon EKS is used to run containerized applications using Kubernetes on AWS. Common workloads include REST APIs, microservices, background workers, scheduled jobs, data-processing applications, and internal developer platforms.
Is Amazon EKS the Same as Kubernetes?
EKS is a managed service that runs upstream-compatible Kubernetes. Kubernetes is the open-source orchestration platform, while EKS provides AWS-managed control-plane infrastructure and integrations with AWS services.
Standard Kubernetes resources and tools generally work with EKS, subject to API versions, installed controllers, and the selected compute configuration.
Should I Choose EKS or ECS?
ECS can be simpler for teams focused on AWS-native container deployment without needing the Kubernetes ecosystem. EKS is attractive when teams require Kubernetes APIs, Helm charts, operators, specialized scheduling, or standardized platform tooling.
The best choice depends on operational expertise, workload complexity, infrastructure requirements, and platform strategy.
Is Amazon EKS Serverless?
EKS can run eligible workloads on AWS Fargate, which removes the need to manage EC2 worker instances. EKS Auto Mode also automates a substantial portion of worker infrastructure management.
However, EKS clusters still use managed Kubernetes control-plane infrastructure, and serverless compute does not eliminate application and cluster configuration responsibilities.
Does EKS Manage Worker Nodes?
EKS manages worker node lifecycle operations to different degrees depending on the compute option. Managed node groups automate supported EC2 node provisioning and updates, while EKS Auto Mode assumes additional responsibility for provisioning and maintaining compatible node infrastructure.
Self-managed node configurations leave more of this work to the customer.
Is Amazon EKS Free?
No. Standard Amazon EKS clusters have a per-cluster hourly charge, and workload infrastructure is billed separately. Extended Kubernetes version support costs more than standard support.
Additional charges can include EC2, Fargate, EKS Auto Mode, storage, load balancing, networking, and monitoring resources.
Conclusion
Amazon EKS is a managed Kubernetes service that allows teams to run containerized applications on AWS using standard Kubernetes APIs. AWS manages the Kubernetes control plane and provides integrations for compute, networking, storage, security, and observability.
Its value is greatest when Kubernetes capabilities justify the additional platform complexity. Managed node groups offer a familiar balance of control and automation, Fargate reduces worker-server management for supported workloads, and EKS Auto Mode further automates infrastructure operations.
Production success still depends on application architecture. Workloads need appropriate resource requests, secure identities, healthy deployment strategies, autoscaling coordination, availability across failure domains, and tested recovery procedures.
Key Takeaway: Amazon EKS provides managed Kubernetes, not automatic application reliability. Use it when your platform benefits from Kubernetes APIs and ecosystem tooling, and design worker capacity, networking, deployments, security, and observability as first-class production concerns.
More Articles to Read
Explore these additional articles about container infrastructure, workload management, deployment strategies, automation, and scalability.
Comments (0)