EKS Cluster Setup
Creating an EKS cluster involves setting up the AWS infrastructure (VPC, IAM roles), creating the cluster control plane, configuring worker nodes, and connecting your local kubectl to the cluster. This guide covers the complete setup process from prerequisites to deploying your first application.
Prerequisites
Before creating an EKS cluster, ensure you have:
AWS Account Requirements
- AWS Account - Active AWS account with appropriate permissions
- IAM Permissions - Ability to create IAM roles, VPCs, and EKS clusters
- Service Quotas - Sufficient service quotas for EC2 instances, VPCs, and EKS clusters
- Region Selection - Choose an AWS region where EKS is available
Local Tools
Install these tools on your local machine:
kubectl:
# macOS
brew install kubectl
# Linux
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# Verify installation
kubectl version --client
AWS CLI:
# macOS
brew install awscli
# Linux
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
# Verify installation
aws --version
eksctl (Recommended):
# macOS/Linux
curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp
sudo mv /tmp/eksctl /usr/local/bin
# Verify installation
eksctl version
AWS CLI Authentication:
# Configure AWS credentials
aws configure
# Or use environment variables
export AWS_ACCESS_KEY_ID=your-access-key
export AWS_SECRET_ACCESS_KEY=your-secret-key
export AWS_DEFAULT_REGION=us-west-2
Understanding EKS Components
Before creating a cluster, understand what gets created:
EKS Cluster:
- Control plane managed by AWS
- API endpoint for cluster access
- Cluster configuration and version
VPC and Networking:
- VPC for cluster isolation
- Subnets across availability zones
- Internet gateway or NAT gateway for internet access
- Route tables for traffic routing
IAM Roles:
- Cluster Role - Permissions for EKS service to manage control plane
- Node Role - Permissions for worker nodes to access AWS services
OIDC Provider:
- Enables IAM Roles for Service Accounts (IRSA)
- Allows pods to assume IAM roles
Node Group:
- Auto Scaling Group for worker nodes
- Launch Template defining instance configuration
- EC2 instances running Kubernetes node components
Creating a Cluster
There are three main ways to create an EKS cluster:
Method 1: eksctl (Recommended for Beginners)
eksctl is the official CLI tool for EKS that simplifies cluster creation:
Simple Cluster Creation:
# Create cluster with default settings
eksctl create cluster \
--name my-cluster \
--region us-west-2 \
--nodegroup-name standard-workers \
--node-type t3.medium \
--nodes 3 \
--nodes-min 1 \
--nodes-max 4
This single command creates:
- EKS cluster
- VPC with subnets
- IAM roles
- Node group with 3 nodes
- kubeconfig configuration
Advanced Cluster Configuration:
# cluster-config.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: production-cluster
region: us-west-2
version: "1.28"
vpc:
cidr: 10.0.0.0/16
nat:
gateway: HighlyAvailable
iam:
withOIDC: true
serviceAccounts:
- metadata:
name: aws-load-balancer-controller
namespace: kube-system
wellKnownPolicies:
awsLoadBalancerController: true
managedNodeGroups:
- name: general-workers
instanceType: t3.large
minSize: 2
maxSize: 10
desiredCapacity: 3
volumeSize: 50
labels:
role: general
taints:
- key: dedicated
value: general
effect: NoSchedule
- name: compute-workers
instanceType: c5.xlarge
minSize: 0
maxSize: 20
desiredCapacity: 2
labels:
role: compute
spot: true
addons:
- name: vpc-cni
- name: coredns
- name: kube-proxy
- name: ebs-csi-driver
Create cluster from config:
eksctl create cluster -f cluster-config.yaml
Method 2: AWS Console
Creating via the AWS Console provides a visual interface:
Navigate to EKS:
- Go to AWS Console → EKS → Clusters → Create cluster
Configure Cluster:
- Cluster name
- Kubernetes version
- Cluster service role (IAM role for EKS service)
- VPC and subnets
- Security groups
- Cluster endpoint access (public, private, or both)
- Logging configuration
Create Node Group:
- After cluster creation, create a node group
- Select instance types
- Configure scaling
- Set IAM role for nodes
Configure kubectl:
- Update kubeconfig:
aws eks update-kubeconfig --name my-cluster --region us-west-2
- Update kubeconfig:
Method 3: Terraform
For infrastructure as code, use Terraform:
# main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = "us-west-2"
}
module "eks" {
source = "terraform-aws-modules/eks/aws"
version = "~> 19.0"
cluster_name = "my-cluster"
cluster_version = "1.28"
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 = {
general = {
min_size = 1
max_size = 10
desired_size = 3
instance_types = ["t3.medium"]
capacity_type = "ON_DEMAND"
}
compute = {
min_size = 0
max_size = 20
desired_size = 2
instance_types = ["c5.xlarge"]
capacity_type = "SPOT"
}
}
}
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.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 = false
tags = {
"kubernetes.io/cluster/my-cluster" = "shared"
}
}
Apply with:
terraform init
terraform plan
terraform apply
Cluster Configuration Options
Kubernetes Version
Choose a Kubernetes version supported by EKS:
# List available versions
aws eks describe-addon-versions --addon-name vpc-cni --region us-west-2
# Create cluster with specific version
eksctl create cluster --name my-cluster --version 1.28
Version Considerations:
- Use a recent stable version for new features
- Check EKS version support lifecycle
- Consider upgrade path when choosing version
- Test version compatibility with your applications
VPC Configuration
EKS requires a VPC with specific configuration:
Subnet Requirements:
- At least 2 subnets in different availability zones
- Sufficient IP addresses for pods (VPC CNI uses VPC IPs)
- Private subnets for nodes (recommended)
- Public subnets for load balancers (if needed)
CIDR Planning:
IP Address Planning:
- Reserve IPs for nodes (1 per node)
- Reserve IPs for pods (varies by instance type)
- Reserve IPs for AWS services (load balancers, etc.)
- Plan for growth and scaling
Cluster Endpoint Configuration
Control how the API server is accessed:
Public Endpoint:
- Accessible from internet
- Requires authentication
- Simpler for development
- Less secure for production
Private Endpoint:
- Only accessible from VPC
- More secure
- Requires VPN or bastion host
- Recommended for production
Both (Recommended):
- Public for kubectl access
- Private for pod-to-API communication
- Best of both worlds
# Configure endpoint access
aws eks update-cluster-config \
--name my-cluster \
--region us-west-2 \
--resources-vpc-config endpointPublicAccess=true,endpointPrivateAccess=true
Initial Node Group Setup
After creating the cluster, set up worker nodes:
Managed Node Groups
AWS manages the node lifecycle:
# Create managed node group
eksctl create nodegroup \
--cluster my-cluster \
--name general-workers \
--node-type t3.large \
--nodes 3 \
--nodes-min 1 \
--nodes-max 10 \
--ssh-access \
--ssh-public-key my-key
Benefits:
- Automatic node updates
- Automatic node replacement
- Integrated with Auto Scaling Groups
- Less operational overhead
Configuration Options:
- Instance types and sizes
- Minimum, maximum, and desired capacity
- Spot instances for cost savings
- Labels and taints
- User data for node initialization
Self-Managed Node Groups
You manage the node lifecycle:
# Create launch template
aws ec2 create-launch-template \
--launch-template-name eks-node-template \
--launch-template-data file://node-userdata.sh
# Create Auto Scaling Group
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name eks-nodes \
--launch-template LaunchTemplateName=eks-node-template \
--min-size 1 \
--max-size 10 \
--desired-capacity 3 \
--vpc-zone-identifier subnet-xxx,subnet-yyy
When to Use:
- Need custom AMIs
- Require specific node configurations
- Want full control over node lifecycle
- Have existing Auto Scaling Group patterns
Cluster Authentication
Configure kubectl to access your cluster:
Update kubeconfig
# Using AWS CLI
aws eks update-kubeconfig \
--name my-cluster \
--region us-west-2
# Using eksctl
eksctl utils write-kubeconfig \
--cluster my-cluster \
--region us-west-2
This updates ~/.kube/config with cluster credentials.
Verify Access
# Test cluster access
kubectl get nodes
# Should show your worker nodes
NAME STATUS ROLES AGE VERSION
ip-10-0-1-123.ec2.internal Ready <none> 5m v1.28.0-eks-xxxxx
ip-10-0-2-456.ec2.internal Ready <none> 5m v1.28.0-eks-xxxxx
ip-10-0-3-789.ec2.internal Ready <none> 5m v1.28.0-eks-xxxxx
aws-auth ConfigMap
The aws-auth ConfigMap maps AWS IAM users/roles to Kubernetes users:
# View current config
kubectl get configmap aws-auth -n kube-system -o yaml
# Add IAM user/role to cluster
eksctl create iamidentitymapping \
--cluster my-cluster \
--arn arn:aws:iam::123456789012:user/john \
--username john \
--group system:masters
Common Mappings:
- IAM users → Kubernetes users
- IAM roles → Kubernetes users
- Service accounts → IAM roles (IRSA)
Post-Setup Configuration
After cluster creation, configure essential components:
Install EKS Add-ons
# Install VPC CNI
aws eks create-addon \
--cluster-name my-cluster \
--addon-name vpc-cni \
--addon-version latest
# Install CoreDNS
aws eks create-addon \
--cluster-name my-cluster \
--addon-name coredns \
--addon-version latest
# Install kube-proxy
aws eks create-addon \
--cluster-name my-cluster \
--addon-name kube-proxy \
--addon-version latest
# Install EBS CSI driver
aws eks create-addon \
--cluster-name my-cluster \
--addon-name aws-ebs-csi-driver \
--addon-version latest
Configure OIDC Provider
Enable IAM Roles for Service Accounts:
# Create OIDC provider
eksctl utils associate-iam-oidc-provider \
--cluster my-cluster \
--approve
Set Up Monitoring
# Enable CloudWatch Container Insights
aws eks update-cluster-config \
--name my-cluster \
--logging '{"enable":[{"types":["api","audit","authenticator","controllerManager","scheduler"]}]}'
Tagging and Resource Management
Proper tagging helps with cost management and organization:
# Tag cluster
aws eks tag-resource \
--resource-arn arn:aws:eks:us-west-2:123456789012:cluster/my-cluster \
--tags Environment=Production,Team=Platform,CostCenter=Engineering
# Tag node group
aws eks update-nodegroup-config \
--cluster-name my-cluster \
--nodegroup-name general-workers \
--labels Environment=Production,Team=Platform
Recommended Tags:
- Environment (dev, staging, prod)
- Team/Department
- Cost Center
- Application
- Managed By (eksctl, terraform, etc.)
Best Practices
Use eksctl or Terraform - Avoid manual Console creation for reproducibility
Plan VPC CIDR Carefully - Ensure sufficient IP space for pods and growth
Use Private Subnets for Nodes - More secure, use NAT gateway for outbound access
Enable OIDC Provider - Required for IRSA and modern security patterns
Configure Cluster Logging - Enable audit logs for security and troubleshooting
Use Managed Node Groups - Less operational overhead unless you need custom configs
Set Appropriate Scaling Limits - Configure min/max to prevent cost overruns
Tag Everything - Helps with cost allocation and resource management
Test in Non-Production First - Validate configuration before production
Document Your Setup - Keep track of configuration decisions and rationale
Common Issues
Insufficient IP Addresses
Problem: Pods can’t get IP addresses
Solution:
- Increase subnet CIDR size
- Use secondary CIDR ranges
- Consider using custom networking mode
Node Group Creation Fails
Problem: Node group creation times out or fails
Solution:
- Check IAM role permissions
- Verify security group rules
- Check subnet configuration
- Review CloudWatch logs
kubectl Access Denied
Problem: Can’t access cluster with kubectl
Solution:
- Verify kubeconfig is updated
- Check IAM user/role permissions
- Verify aws-auth ConfigMap includes your user
- Check cluster endpoint access configuration
Next Steps
After cluster setup:
- Networking - Configure VPC CNI and networking
- Storage - Set up EBS and EFS storage
- Security - Configure IAM, IRSA, and security
- Node Management - Manage and optimize node groups
See Also
- EKS Overview - Understanding EKS architecture
- Cluster Operations - General Kubernetes cluster management
- Troubleshooting - Common issues and solutions