What is Amazon EKS?
Amazon Elastic Kubernetes Service (EKS) is a managed Kubernetes platform that simplifies running Kubernetes on AWS without needing to install, operate, and maintain your own Kubernetes control plane. It provides a production-grade, scalable, and highly available Kubernetes environment integrated deeply with AWS services like IAM, VPC, and Load Balancers. EKS is certified as conformant by the CNCF, ensuring compatibility with the standard Kubernetes ecosystem.
Why EKS Matters for Developers
For development teams, EKS eliminates the operational burden of managing the Kubernetes control plane—components like etcd, API server, and scheduler are fully managed across multiple Availability Zones. This lets you focus on building applications, while still leveraging native Kubernetes APIs, community tools, and declarative configurations. Key benefits include:
- Reduced operational overhead – AWS handles control plane patching, scaling, and high availability.
- Deep AWS integration – IAM roles for service accounts, native VPC networking, and seamless load balancer provisioning.
- Security and compliance – Control plane isolated in a dedicated VPC, support for security groups per pod, and encryption options.
- Flexibility – Use managed node groups, self-managed nodes, or Fargate for serverless compute.
- Ecosystem compatibility – Works with standard Kubernetes tooling: kubectl, Helm, Terraform, ArgoCD, and more.
Prerequisites and Preparation
🚀 Deploy your AI agent in 10 minutes
Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.
Try it free →Before setting up an EKS cluster, ensure you have the following tools installed and an AWS account configured:
- AWS CLI (version 2+ recommended) – installed and configured with credentials (
aws configure) - kubectl – Kubernetes command-line tool (match version to the Kubernetes version you plan to use)
- eksctl – official EKS CLI tool for cluster creation and management (simplest approach)
- IAM permissions – Your AWS user/role needs permissions to create EKS clusters, VPC resources, EC2 instances, IAM roles, and more. Attach the
AdministratorAccesspolicy or a scoped policy for testing.
Installing Required Tools
Install eksctl and kubectl on your local machine. Example for macOS via Homebrew:
brew install eksctl kubectl
# Verify installations
eksctl version
kubectl version --client
For Linux or Windows, follow the official docs to download binaries or use package managers.
Step-by-Step EKS Cluster Setup
We will create a cluster using eksctl, the fastest and most developer-friendly method. This provisions the control plane, a managed node group, networking, and IAM resources in one command.
Creating a Basic Cluster
Run the following command to create a cluster named dev-cluster in the us-east-1 region with 2 t3.medium nodes:
eksctl create cluster \
--name dev-cluster \
--region us-east-1 \
--nodegroup-name standard-workers \
--node-type t3.medium \
--nodes 2 \
--nodes-min 1 \
--nodes-max 4 \
--managed
This command takes about 10–15 minutes. It creates:
- An EKS control plane in a dedicated VPC managed by AWS.
- A managed node group with two t3.medium instances (in a new or existing VPC, depending on flags).
- IAM roles for the cluster and nodes.
- A
kubeconfigfile automatically merged into~/.kube/config.
Specifying Advanced Networking (Optional)
To use an existing VPC with private subnets and custom networking, define a cluster config file. Example cluster.yaml:
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: advanced-cluster
region: us-west-2
version: "1.28"
vpc:
id: "vpc-0abc12345def67890"
subnets:
private:
private-one: { id: "subnet-0aaa1111" }
private-two: { id: "subnet-0bbb2222" }
public:
public-one: { id: "subnet-0ccc3333" }
nodeGroups:
- name: private-workers
instanceType: t3.medium
desiredCapacity: 3
privateNetworking: true
subnets:
- private-one
- private-two
managedNodeGroups:
- name: managed-ng
instanceType: t3.large
desiredCapacity: 2
subnets:
- private-one
- private-two
Create the cluster with:
eksctl create cluster -f cluster.yaml
Configuring kubectl and Cluster Access
Once the cluster is created, verify that your local kubectl context is set correctly:
kubectl config current-context
# Should show something like arn:aws:eks:us-east-1:123456789:cluster/dev-cluster
kubectl cluster-info
kubectl get nodes
If the context is missing, eksctl usually updates it automatically. You can manually update kubeconfig with:
aws eks update-kubeconfig --region us-east-1 --name dev-cluster
Deploying a Sample Application
Let's deploy a simple Nginx web server and expose it via an AWS Load Balancer.
Creating a Deployment and Service
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.23
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
type: LoadBalancer
selector:
app: nginx
ports:
- port: 80
targetPort: 80
Apply the manifest:
kubectl apply -f deployment.yaml
Check the service and wait for the external IP (AWS will provision a Classic Load Balancer or Network Load Balancer depending on configuration):
kubectl get svc nginx-service --watch
# Note the EXTERNAL-IP once it appears
Access the application via http://<EXTERNAL-IP>.
Using an Ingress with AWS Load Balancer Controller
For more advanced routing (path-based, host-based), install the AWS Load Balancer Controller and create an Ingress resource. First, add the EKS Helm chart repository:
helm repo add eks https://aws.github.io/eks-charts
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
--set clusterName=dev-cluster \
--set serviceAccount.create=false \
--set region=us-east-1 \
--set vpcId=vpc-xxxxxxxx
Then create an Ingress (requires an existing service):
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
Apply and retrieve the ALB address:
kubectl apply -f ingress.yaml
kubectl get ingress nginx-ingress
Managing Worker Nodes
EKS offers both managed node groups (recommended) and self-managed node groups. Managed node groups simplify updates, scaling, and termination handling.
Scaling Nodes
You can scale a managed node group imperatively:
eksctl scale nodegroup --cluster=dev-cluster --name=standard-workers --nodes=4 --nodes-min=2 --nodes-max=6
For declarative scaling, update the node group in your cluster config file and run:
eksctl create nodegroup -f cluster.yaml --update
Using Cluster Autoscaler
For automatic scaling based on pending pods, deploy the Kubernetes Cluster Autoscaler (requires IAM policy for ASG access). Example deployment via Helm:
helm repo add autoscaler https://kubernetes.github.io/autoscaler
helm install cluster-autoscaler autoscaler/cluster-autoscaler \
--set 'autoDiscovery.clusterName'=dev-cluster \
--set awsRegion=us-east-1
Then annotate your node groups with the required tags (eksctl handles this automatically for managed node groups).
Networking and Security
VPC and Subnet Design
By default, eksctl creates a dedicated VPC with public and private subnets. For production, design a VPC with private subnets for worker nodes and public subnets only for load balancers. Use security groups to restrict pod-to-pod communication.
Security Groups for Pods
EKS supports assigning security groups directly to pods, enabling fine-grained network rules. Enable the feature by adding the securityGroup field in a pod spec or using the SecurityGroupPolicy CRD with the AWS VPC CNI plugin.
IAM Roles for Service Accounts (IRSA)
Instead of distributing AWS credentials to pods, use IRSA to associate an IAM role with a Kubernetes service account. Steps:
- Create an IAM OIDC provider for the cluster (eksctl does this automatically if created via eksctl).
- Create an IAM role with a trust policy allowing the service account to assume it.
- Annotate the service account with the role ARN.
Example using eksctl to create an IRSA association:
eksctl create iamserviceaccount \
--cluster=dev-cluster \
--name=s3-reader \
--namespace=default \
--attach-policy-arn=arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approve
Then reference the service account in a pod spec:
apiVersion: v1
kind: Pod
spec:
serviceAccountName: s3-reader
containers:
- name: my-app
image: my-app-image
The pod will have the permissions of the attached IAM role without static credentials.
Network Policies
Install a network policy engine like Calico to restrict pod communication. Calico can be installed via:
kubectl apply -f https://raw.githubusercontent.com/aws/amazon-vpc-cni-k8s/master/config/v1.12/calico.yaml
Then define a policy to deny all traffic except what you explicitly allow.
Integrating with AWS Services
EKS shines when combined with other AWS services:
- CloudWatch Logs – Stream pod logs using the CloudWatch agent or Fluent Bit daemonset.
- Prometheus/Grafana – Deploy the Prometheus community Helm chart and visualize metrics on Grafana.
- AWS Secrets Manager – Use the Secrets Store CSI Driver to mount secrets as volumes.
- ECR – Store container images in Elastic Container Registry and pull without additional authentication (with proper IAM roles).
- AWS X-Ray – Trace requests across microservices using the X-Ray daemon.
Monitoring and Logging
Enable control plane logging to CloudWatch for audit, API, scheduler, and controller manager logs:
eksctl utils cluster-logging enable --cluster=dev-cluster --types=all
Deploy a Fluent Bit daemonset to collect container logs and send them to CloudWatch:
kubectl apply -f https://raw.githubusercontent.com/aws/aws-for-fluent-bit/main/config/fluent-bit-cluster.yaml
For metrics, install the Prometheus Node Exporter and kube-state-metrics, then visualize with Grafana (deploy via Helm).
Best Practices
- Use managed node groups for easier patching and lifecycle management.
- Leverage IRSA – never embed long-lived AWS credentials in pods.
- Enable private subnets for workers and restrict SSH access using security groups.
- Regularly update the EKS control plane and node AMIs via the EKS update process or node replacement.
- Apply resource limits and quotas to avoid noisy neighbors and cost overruns.
- Use Cluster Autoscaler or Karpenter for dynamic node scaling based on workload demands.
- Enable encryption for EKS secrets (envelope encryption with KMS) and etcd (when using self-managed etcd, but managed control plane uses AWS-managed encryption by default).
- Tag all resources for cost allocation and organization.
- Implement GitOps with tools like ArgoCD or Flux to manage cluster state declaratively.
- Test updates in a staging cluster before rolling out to production.
Conclusion
Amazon EKS provides a robust, managed foundation for running containerized workloads at scale. By using eksctl and following the configuration patterns outlined here—from cluster creation and worker node management to security hardening and AWS service integration—you can accelerate your Kubernetes adoption while maintaining operational excellence. The key is to treat your cluster as code, automate everything possible, and stay aligned with Kubernetes and AWS best practices. Whether you're deploying a simple web service or a complex microservice mesh, EKS gives you the control and flexibility you need without the burden of managing the control plane.