Amazon EKS (Elastic Kubernetes Service)
Overview
Amazon Elastic Kubernetes Service (EKS) is a managed Kubernetes service that makes it easy to run Kubernetes on AWS without needing to install, operate, and maintain your own Kubernetes control plane. As of May 2025, EKS supports Kubernetes versions 1.26 through 1.30 and automatically manages the availability and scalability of the Kubernetes control plane nodes.
Key Concepts
EKS Architecture
- Control Plane: Managed by AWS across multiple availability zones
- Worker Nodes: EC2 instances that run your containerized applications
- Node Groups: Collection of EC2 instances managed as a group
- Fargate Profiles: Serverless compute for EKS pods
- VPC CNI Plugin: Provides networking for pods using AWS VPC
Access Management
- IAM Integration: Role-based access using AWS IAM
- OIDC Provider: Authentication via OpenID Connect
- Cluster IAM Role: Role that allows EKS to manage resources
- Node IAM Role: Role that allows worker nodes to access AWS services
Networking
- VPC Requirements: EKS has specific networking requirements
- Pod Networking: Managed through AWS VPC CNI
- LoadBalancer Services: Integration with AWS ALB/NLB
- Cluster Endpoint Access: Public, private, or both
Deploying EKS with Terraform
Basic EKS Cluster
provider "aws" {
region = "us-west-2"
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 4.0"
name = "eks-vpc"
cidr = "10.0.0.0/16"
azs = ["us-west-2a", "us-west-2b", "us-west-2c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
single_nat_gateway = true
enable_dns_hostnames = true
public_subnet_tags = {
"kubernetes.io/cluster/my-eks-cluster" = "shared"
"kubernetes.io/role/elb" = "1"
}
private_subnet_tags = {
"kubernetes.io/cluster/my-eks-cluster" = "shared"
"kubernetes.io/role/internal-elb" = "1"
}
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 19.15"
cluster_name = "my-eks-cluster"
cluster_version = "1.30"
vpc_id = module.vpc.vpc_id
subnet_ids = module.vpc.private_subnets
cluster_endpoint_public_access = true
cluster_endpoint_private_access = true
eks_managed_node_groups = {
main = {
min_size = 2
max_size = 10
desired_size = 2
instance_types = ["t3.medium"]
capacity_type = "ON_DEMAND"
}
}
tags = {
Environment = "production"
Application = "my-app"
}
}
output "cluster_endpoint" {
value = module.eks.cluster_endpoint
}
output "cluster_certificate_authority_data" {
value = module.eks.cluster_certificate_authority_data
}
output "configure_kubectl" {
value = "aws eks update-kubeconfig --region us-west-2 --name my-eks-cluster"
}
Advanced EKS Configuration
# Additional configuration for Fargate profiles
resource "aws_eks_fargate_profile" "example" {
cluster_name = module.eks.cluster_name
fargate_profile_name = "example-profile"
pod_execution_role_arn = aws_iam_role.fargate_pod_execution_role.arn
subnet_ids = module.vpc.private_subnets
selector {
namespace = "default"
labels = {
"fargate" = "true"
}
}
}
# Example of adding managed add-ons
resource "aws_eks_addon" "vpc_cni" {
cluster_name = module.eks.cluster_name
addon_name = "vpc-cni"
addon_version = "v1.16.0-eksbuild.1" # Check for the latest version
}
resource "aws_eks_addon" "coredns" {
cluster_name = module.eks.cluster_name
addon_name = "coredns"
addon_version = "v1.11.0-eksbuild.1" # Check for the latest version
}
resource "aws_eks_addon" "kube_proxy" {
cluster_name = module.eks.cluster_name
addon_name = "kube-proxy"
addon_version = "v1.30.0-eksbuild.1" # Check for the latest version
}
Deploying EKS with AWS CLI
Pre-requisites
Before you begin, ensure you have:
- AWS CLI (version 2.13.0 or higher) installed and configured
kubectlinstalled- IAM permissions to create EKS clusters
1. Create an IAM Role for EKS
# Create the policy document for EKS
cat > eks-cluster-role-trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "eks.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# Create the IAM role
aws iam create-role \
--role-name EKSClusterRole \
--assume-role-policy-document file://eks-cluster-role-trust-policy.json
# Attach required policies to the role
aws iam attach-role-policy \
--role-name EKSClusterRole \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy
2. Create a VPC for EKS
You can use AWS CloudFormation to deploy a VPC compatible with EKS:
aws cloudformation create-stack \
--stack-name eks-vpc \
--template-url https://amazon-eks.s3.us-west-2.amazonaws.com/cloudformation/2023-02-09/amazon-eks-vpc-sample.yaml
3. Create the EKS Cluster
aws eks create-cluster \
--name my-eks-cluster \
--role-arn arn:aws:iam::<ACCOUNT_ID>:role/EKSClusterRole \
--resources-vpc-config subnetIds=subnet-<ID1>,subnet-<ID2>,subnet-<ID3>,securityGroupIds=sg-<ID> \
--kubernetes-version 1.30
Wait for the cluster to be created (10-15 minutes):
aws eks describe-cluster \
--name my-eks-cluster \
--query "cluster.status"
4. Create Node IAM Role
# Create the policy document
cat > node-role-trust-policy.json << EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
EOF
# Create the IAM role
aws iam create-role \
--role-name EKSNodeRole \
--assume-role-policy-document file://node-role-trust-policy.json
# Attach required policies
aws iam attach-role-policy \
--role-name EKSNodeRole \
--policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy
aws iam attach-role-policy \
--role-name EKSNodeRole \
--policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly
aws iam attach-role-policy \
--role-name EKSNodeRole \
--policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy
5. Create a Node Group
aws eks create-nodegroup \
--cluster-name my-eks-cluster \
--nodegroup-name my-eks-nodegroup \
--node-role arn:aws:iam::<ACCOUNT_ID>:role/EKSNodeRole \
--subnets subnet-<ID1> subnet-<ID2> subnet-<ID3> \
--instance-types t3.medium \
--scaling-config minSize=2,maxSize=5,desiredSize=3
6. Configure kubectl to Work with Your EKS Cluster
aws eks update-kubeconfig \
--name my-eks-cluster \
--region us-west-2
7. Verify the Cluster and Nodes
kubectl get nodes
kubectl get pods --all-namespaces
Best Practices for EKS
- Security
- Use IAM roles for service accounts (IRSA) to provide fine-grained permissions
- Enable network policies for pod-to-pod traffic control
- Utilize Security Groups for Pods to apply AWS security groups to pods
- Implement Pod Security Standards
- Networking
- Plan your CIDR ranges carefully to avoid IP exhaustion
- Use VPC CNI custom networking when pod density is high
- Implement AWS Load Balancer Controller for advanced ingress features
- Consider AWS PrivateLink for private EKS API endpoint access
- Cost Optimization
- Use Fargate for infrequently used or burst workloads
- Implement Cluster Autoscaler for automatic scaling of node groups
- Consider Spot Instances for non-critical workloads
- Use Graviton (ARM) instances for better price-performance ratio
- Reliability
- Deploy across multiple availability zones
- Use managed add-ons for core components (CoreDNS, kube-proxy)
- Implement proper resource requests and limits
- Use Pod Disruption Budgets for critical workloads
- Operational Excellence
- Use EKS Blueprints for GitOps-based provisioning
- Implement AWS Observability solutions (CloudWatch, Container Insights)
- Regularly upgrade EKS versions to stay within support window
- Utilize EKS add-ons for streamlined management of common components