EKS Cluster Creation
There are several ways to create an Amazon EKS cluster. In this chapter, we will learn in detail how to create an EKS cluster using various tools and methods.
Table of Contents
- Prerequisites
- Creating a Cluster Using eksctl
- Creating a Cluster Using AWS Management Console
- Creating a Cluster Using AWS CLI
- Creating a Cluster Using Terraform
- Creating a Cluster Using AWS CDK
- Configuring Cluster Access
- Cluster Validation
- Cluster Upgrade
- Cluster Deletion
Prerequisites
Before creating an EKS cluster, the following prerequisites are required:
1. AWS Account
A valid AWS account is required. If you don't have an AWS account, you can sign up at the AWS website.
2. IAM Permissions
The following IAM permissions are required to create and manage an EKS cluster:
eks:*ec2:*iam:*cloudformation:*
If you have administrator permissions, no additional permission settings are required. Otherwise, you need to attach the following IAM policy to the user or role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:*",
"ec2:*",
"iam:*",
"cloudformation:*"
],
"Resource": "*"
}
]
}3. Tool Installation
The following tools must be installed to create and manage an EKS cluster:
AWS CLI
AWS CLI is a unified tool for controlling AWS services from the command line.
macOS:
curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /Linux:
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/installWindows:
https://awscli.amazonaws.com/AWSCLIV2.msiAfter installing AWS CLI, run the following command to configure credentials:
aws configurekubectl
kubectl is a command-line tool for communicating with Kubernetes clusters.
macOS:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectlLinux:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectlWindows:
curl -LO "https://dl.k8s.io/release/v1.26.0/bin/windows/amd64/kubectl.exe"eksctl
eksctl is a simple CLI tool for creating and managing EKS clusters.
macOS:
brew tap weaveworks/tap
brew install weaveworks/tap/eksctlOr:
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/binLinux:
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/binWindows:
# PowerShell
$version = (Invoke-WebRequest -Uri "https://api.github.com/repos/weaveworks/eksctl/releases/latest" | ConvertFrom-Json).tag_name
Invoke-WebRequest -Uri "https://github.com/weaveworks/eksctl/releases/download/$version/eksctl_Windows_amd64.zip" -OutFile eksctl.zip
Expand-Archive -Path eksctl.zip -DestinationPath $env:USERPROFILE\.eksctl\bin
$env:PATH += ";$env:USERPROFILE\.eksctl\bin"4. VPC and Subnets
An EKS cluster requires a VPC and subnets. You can use an existing VPC or create a new one. The VPC for an EKS cluster must meet the following requirements:
- At least 2 subnets must be in different availability zones.
- Subnets must have internet access (through a NAT gateway or internet gateway).
- Subnets must have sufficient IP addresses.
- Subnets must have appropriate tags.
VPC Tags for EKS Cluster
The following tags must be applied to enable the EKS cluster to use the VPC and subnets correctly:
VPC Tags:
kubernetes.io/cluster/<cluster-name>:sharedorowned
Public Subnet Tags:
kubernetes.io/cluster/<cluster-name>:sharedorownedkubernetes.io/role/elb:1
Private Subnet Tags:
kubernetes.io/cluster/<cluster-name>:sharedorownedkubernetes.io/role/internal-elb:1
Creating a Cluster Using eksctl
eksctl is the simplest way to create and manage EKS clusters. eksctl uses CloudFormation to create EKS clusters and related resources.
Basic Cluster Creation
To create the most basic form of an EKS cluster, run the following command:
eksctl create cluster --name my-cluster --region us-west-2This command creates a cluster with the following default settings:
- 2 m5.large nodes
- New VPC and subnets
- Default Amazon Linux 2 AMI
- Latest Kubernetes version
Creating a Cluster Using a Configuration File
For more complex configurations, you can define the cluster using a YAML file:
# cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-eks-cluster
region: us-west-2
version: "1.26"
vpc:
id: vpc-12345678
subnets:
private:
us-west-2a:
id: subnet-12345678
us-west-2b:
id: subnet-87654321
public:
us-west-2a:
id: subnet-23456789
us-west-2b:
id: subnet-98765432
managedNodeGroups:
- name: ng-1
instanceType: m5.large
desiredCapacity: 2
minSize: 1
maxSize: 3
privateNetworking: true
volumeSize: 80
volumeType: gp3
iam:
withAddonPolicies:
imageBuilder: true
autoScaler: true
externalDNS: true
certManager: true
appMesh: true
ebs: true
fsx: true
efs: true
albIngress: true
xRay: true
cloudWatch: true
- name: ng-2
instanceType: c5.xlarge
desiredCapacity: 2
privateNetworking: true
spot: true
autoModeConfig:
enabled: true
# Create default node pools (general-purpose, system)
# If nodePools is not specified, defaults are used
# nodePools: ["general-purpose", "system"]
# nodeRoleARN: arn:aws:iam::123456789012:role/AmazonEKSAutoNodeRole
fargate:
profiles:
- name: fp-default
selectors:
- namespace: default
labels:
env: fargate
- name: fp-kube-system
selectors:
- namespace: kube-system
labels:
k8s-app: kube-dns
cloudWatch:
clusterLogging:
enableTypes: ["api", "audit", "authenticator", "controllerManager", "scheduler"]To create a cluster using this configuration file, run the following command:
eksctl create cluster -f cluster.yamlCreating Managed Node Groups
To add a managed node group to an existing cluster, run the following command:
eksctl create nodegroup \
--cluster my-cluster \
--region us-west-2 \
--name my-nodegroup \
--node-type m5.large \
--nodes 3 \
--nodes-min 1 \
--nodes-max 5 \
--ssh-access \
--ssh-public-key my-keyOr you can use a configuration file:
# nodegroup.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: us-west-2
managedNodeGroups:
- name: my-nodegroup
instanceType: m5.large
desiredCapacity: 3
minSize: 1
maxSize: 5
volumeSize: 80
volumeType: gp3
ssh:
allow: true
publicKeyName: my-keyeksctl create nodegroup -f nodegroup.yamlCreating an EKS Auto Mode Cluster
EKS Auto Mode is a new feature released in 2024 that automates Kubernetes cluster infrastructure to significantly reduce operational overhead. Auto Mode automatically handles infrastructure management including compute, networking, and storage.
Key Features of EKS Auto Mode
- Automated Node Management: Automatically adds/removes nodes based on workload requirements
- Enhanced Security: Immutable AMI, SELinux enforcing mode, read-only root filesystem
- Automatic Upgrades: Regular security patches and updates with 21-day maximum node lifetime
- Integrated Components: Pod networking, DNS, storage, GPU support provided by default
- Cost Optimization: Automatic termination of unused instances and workload consolidation
Basic Auto Mode Cluster Creation
eksctl create cluster --name my-auto-cluster --enable-auto-mode --region us-west-2Creating an Auto Mode Cluster Using a Configuration File
# auto-cluster.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-auto-cluster
region: us-west-2
version: "1.31"
# EKS Auto Mode configuration
autoModeConfig:
enabled: true
# Create default node pools (general-purpose, system)
# If nodePools is not specified, defaults are used
# nodePools: ["general-purpose", "system"]
# nodeRoleARN: arn:aws:iam::123456789012:role/AmazonEKSAutoNodeRole
# VPC configuration (optional)
vpc:
cidr: "10.0.0.0/16"
nat:
gateway: Single # Or HighlyAvailable
clusterEndpoints:
privateAccess: true
publicAccess: true
# Cluster logging
cloudWatch:
clusterLogging:
enableTypes: ["api", "audit", "authenticator", "controllerManager", "scheduler"]
# Add-on configuration
addons:
- name: vpc-cni
version: latest
- name: coredns
version: latest
- name: kube-proxy
version: latest
- name: aws-ebs-csi-driver
version: latestCreate cluster:
eksctl create cluster -f auto-cluster.yamlAuto Mode vs Traditional Approach Comparison
| Feature | Traditional EKS | EKS Auto Mode |
|---|---|---|
| Node Management | Manual managed node groups | Automatic node management |
| Scaling | Cluster Autoscaler setup required | Built-in auto scaling |
| Upgrades | Manual upgrades | Automatic upgrades (21-day cycle) |
| Security | User configured | Enhanced security by default |
| Networking | CNI plugin setup | Automatic networking configuration |
| Storage | CSI driver installation required | EBS CSI automatically provided |
| GPU Support | Manual driver installation | Automatic GPU support |
Auto Mode Cluster Validation
After the cluster is created, you can check its status with the following commands:
# Check cluster status
kubectl get nodes
# Check Auto Mode node pools
kubectl get nodepools
# Check Auto Mode node classes
kubectl get nodeclasses
# Check system pod status
kubectl get pods -n kube-systemCreating Custom Node Pools
In Auto Mode, you can create custom node pools in addition to the default node pools:
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: gpu-nodepool
spec:
template:
metadata:
labels:
workload-type: gpu
spec:
requirements:
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand"]
- key: node.kubernetes.io/instance-type
operator: In
values: ["p3.2xlarge", "p3.8xlarge"]
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: gpu-nodeclass
limits:
cpu: 1000
disruption:
consolidationPolicy: WhenEmpty
consolidateAfter: 30s
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: gpu-nodeclass
spec:
amiFamily: AL2
instanceStorePolicy: RAID0
userData: |
#!/bin/bash
/etc/eks/bootstrap.sh my-auto-clusterAuto Mode Limitations
- No direct node access via SSH or SSM
- Maximum node lifetime of 21 days (automatic replacement)
- Cannot modify default node pools and node classes
- Certain instance type restrictions possible
Auto Mode Monitoring
Auto Mode clusters are integrated with CloudWatch and automatically collect metrics:
# Check CloudWatch metrics
aws cloudwatch get-metric-statistics \
--namespace AWS/EKS \
--metric-name cluster_node_count \
--dimensions Name=ClusterName,Value=my-auto-cluster \
--start-time 2024-01-01T00:00:00Z \
--end-time 2024-01-01T23:59:59Z \
--period 3600 \
--statistics AverageCreating Fargate Profiles
To create a Fargate profile, run the following command:
eksctl create fargateprofile \
--cluster my-cluster \
--region us-west-2 \
--name my-fargate-profile \
--namespace default \
--labels env=fargateOr you can use a configuration file:
# fargate.yaml
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: my-cluster
region: us-west-2
fargate:
profiles:
- name: my-fargate-profile
selectors:
- namespace: default
labels:
env: fargateeksctl create fargateprofile -f fargate.yamlUpdating a Cluster
You can update an existing cluster using eksctl:
# Upgrade cluster version
eksctl upgrade cluster --name=my-cluster --version=1.27
# Upgrade node group
eksctl upgrade nodegroup --cluster=my-cluster --name=my-nodegroupDeleting a Cluster
You can delete a cluster using eksctl:
eksctl delete cluster --name=my-cluster --region=us-west-2Creating a Cluster Using AWS Management Console
The steps to create an EKS cluster using the AWS Management Console are as follows:
- Log in to the AWS Management Console.
- Search for "EKS" or select "Elastic Kubernetes Service" from the services list.
- On the "Clusters" page, click the "Create cluster" button.
Creating an EKS Auto Mode Cluster (Quick Configuration)
Using EKS Auto Mode, you can create a production-ready cluster with minimal configuration.
1. Select Quick Configuration
- Ensure the "Quick configuration" option is selected.
- Enter the following information:
- Cluster name: Enter a unique name for the cluster.
- Kubernetes version: Select the Kubernetes version to use (latest version recommended).
2. Configure IAM Roles
Cluster IAM role selection:
- For your first Auto Mode cluster, use the "Create recommended role" option.
- If you have an existing role, you can reuse it.
- Recommended role name:
AmazonEKSAutoClusterRole
Node IAM role selection:
- For your first Auto Mode cluster, use the "Create recommended role" option.
- Recommended role name:
AmazonEKSAutoNodeRole
3. Configure Networking
Select VPC:
- Create new VPC: Select the "Create VPC" option to create a new VPC for EKS.
- Use existing VPC: Select a previously created EKS VPC.
Subnet configuration (optional):
- EKS Auto Mode automatically selects private subnets in the VPC.
- You can add or remove subnets as needed.
4. Review Configuration and Create
- Select View quick configuration defaults to review all configuration values.
- Click Create cluster. (Cluster creation takes approximately 15 minutes)
Creating a Cluster with Custom Configuration
If you need more granular control, you can use custom configuration.
Cluster Configuration
- On the "Configure cluster" page, enter the following information:
- Cluster name: Enter a unique name for the cluster.
- Kubernetes version: Select the Kubernetes version to use.
- Cluster service role: Create a new role or select an existing role.
- EKS Auto Mode: Check the checkbox to enable Auto Mode.
- Tags: Add tags if needed.
- Click the "Next" button.
Specify Networking
- On the "Specify networking" page, enter the following information:
- VPC: Create a new VPC or select an existing VPC.
- Subnets: Select the subnets to use for the cluster. At least 2 subnets must be in different availability zones.
- Security groups: Select the security groups to use for the cluster.
- Cluster endpoint access: Configure access to the cluster API server endpoint.
- Public: The API server can be accessed from the internet.
- Private: The API server can only be accessed from within the VPC.
- Public and Private: The API server can be accessed from both the internet and within the VPC.
- Click the "Next" button.
Configure Logging
- On the "Configure logging" page, enter the following information:
- Control plane logging: Select the log types to enable.
- API server logs
- Audit logs
- Authenticator logs
- Controller manager logs
- Scheduler logs
- Click the "Next" button.
- Control plane logging: Select the log types to enable.
Select Add-ons
- On the "Select add-ons" page, enter the following information:
- Amazon VPC CNI: CNI plugin for pod networking.
- CoreDNS: DNS service within the cluster.
- kube-proxy: Provides network proxy and load balancing.
- Amazon EBS CSI Driver: Automatically included in EKS Auto Mode.
- Click the "Next" button.
Review and Create
- On the "Review and create" page, review the configuration and click the "Create" button.
Adding Node Groups for Non-Auto Mode Clusters
If you are not using EKS Auto Mode, you need to manually add node groups after cluster creation.
Add Node Group
On the "Node group configuration" page, enter the following information:
- Node group name: Enter a unique name for the node group.
- Node IAM role: Create a new role or select an existing role.
- Click the "Next" button.
On the "Set compute and scaling configuration" page, enter the following information:
- AMI type: Select the AMI type to use for the nodes.
- Instance type: Select the EC2 instance type to use for the nodes.
- Disk size: Specify the disk size for the nodes.
- Node count: Specify the minimum, maximum, and desired number of nodes.
- Click the "Next" button.
On the "Specify networking" page, enter the following information:
- Subnets: Select the subnets to use for the node group.
- Remote access configuration: Configure SSH access.
- Click the "Next" button.
On the "Review and create" page, review the configuration and click the "Create" button.
Creating a Cluster Using AWS CLI
You can create an EKS cluster using AWS CLI. This method is useful for script automation or CI/CD pipelines.
Creating an EKS Auto Mode Cluster
1. Create Cluster
# Create Auto Mode cluster
aws eks create-cluster \
--name my-auto-cluster \
--version 1.31 \
--role-arn arn:aws:iam::123456789012:role/AmazonEKSAutoClusterRole \
--resources-vpc-config subnetIds=subnet-12345,subnet-67890 \
--access-config authenticationMode=API_AND_CONFIG_MAP \
--compute-config nodeRoleArn=arn:aws:iam::123456789012:role/AmazonEKSAutoNodeRole \
--storage-config blockStorage='{enabled=true}' \
--kubernetes-network-config ipFamily=ipv4 \
--region us-west-22. Check Cluster Status
# Check cluster status
aws eks describe-cluster --name my-auto-cluster --region us-west-2
# Wait until cluster is ACTIVE
aws eks wait cluster-active --name my-auto-cluster --region us-west-23. Update kubeconfig
# Update kubeconfig
aws eks update-kubeconfig --name my-auto-cluster --region us-west-2
# Verify cluster connection
kubectl get nodesCreating a Traditional Cluster
Here's how to create a cluster without using Auto Mode.
Basic Cluster Creation
aws eks create-cluster \
--name my-cluster \
--version 1.31 \
--role-arn arn:aws:iam::123456789012:role/eks-service-role \
--resources-vpc-config subnetIds=subnet-12345,subnet-67890,endpointConfigPrivateAccess=true,endpointConfigPublicAccess=true \
--region us-west-2Check Cluster Status
aws eks describe-cluster --name my-cluster --region us-west-2Once the cluster is created, the status changes to ACTIVE. This process takes approximately 10-15 minutes.
Update kubeconfig
aws eks update-kubeconfig --name my-cluster --region us-west-2Create Managed Node Group
aws eks create-nodegroup \
--cluster-name my-cluster \
--nodegroup-name my-nodegroup \
--subnets subnet-12345 subnet-67890 \
--instance-types m5.large \
--ami-type AL2_x86_64 \
--node-role arn:aws:iam::123456789012:role/NodeInstanceRole \
--scaling-config minSize=1,maxSize=3,desiredSize=2 \
--disk-size 20 \
--remote-access ec2SshKey=my-key \
--region us-west-2Check Node Group Status
aws eks describe-nodegroup \
--cluster-name my-cluster \
--nodegroup-name my-nodegroup \
--region us-west-2Creating a Cluster Using Terraform
Using Terraform to create an EKS cluster allows you to manage infrastructure as code.
EKS Auto Mode Cluster Terraform Configuration
# main.tf
terraform {
required_version = ">= 1.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
provider "aws" {
region = var.region
}
# VPC and subnet data sources
data "aws_vpc" "selected" {
id = var.vpc_id
}
data "aws_subnets" "private" {
filter {
name = "vpc-id"
values = [data.aws_vpc.selected.id]
}
tags = {
Type = "Private"
}
}
# EKS Auto Mode cluster
resource "aws_eks_cluster" "auto_mode" {
name = var.cluster_name
role_arn = aws_iam_role.cluster.arn
version = var.kubernetes_version
vpc_config {
subnet_ids = data.aws_subnets.private.ids
endpoint_private_access = true
endpoint_public_access = true
}
# EKS Auto Mode configuration
compute_config {
enabled = true
node_role_arn = aws_iam_role.node.arn
}
storage_config {
block_storage {
enabled = true
}
}
access_config {
authentication_mode = "API_AND_CONFIG_MAP"
}
enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
depends_on = [
aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy,
aws_iam_role_policy_attachment.node_AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.node_AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.node_AmazonEC2ContainerRegistryReadOnly,
]
tags = var.tags
}
# Cluster IAM role
resource "aws_iam_role" "cluster" {
name = "${var.cluster_name}-cluster-role"
assume_role_policy = jsonencode({
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "eks.amazonaws.com"
}
}]
Version = "2012-10-17"
})
}
resource "aws_iam_role_policy_attachment" "cluster_AmazonEKSClusterPolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
role = aws_iam_role.cluster.name
}
# Node IAM role
resource "aws_iam_role" "node" {
name = "${var.cluster_name}-node-role"
assume_role_policy = jsonencode({
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "ec2.amazonaws.com"
}
}]
Version = "2012-10-17"
})
}
resource "aws_iam_role_policy_attachment" "node_AmazonEKSWorkerNodePolicy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy"
role = aws_iam_role.node.name
}
resource "aws_iam_role_policy_attachment" "node_AmazonEKS_CNI_Policy" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"
role = aws_iam_role.node.name
}
resource "aws_iam_role_policy_attachment" "node_AmazonEC2ContainerRegistryReadOnly" {
policy_arn = "arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly"
role = aws_iam_role.node.name
}
# Variable definitions
variable "cluster_name" {
description = "EKS cluster name"
type = string
default = "my-auto-cluster"
}
variable "kubernetes_version" {
description = "Kubernetes version"
type = string
default = "1.31"
}
variable "region" {
description = "AWS region"
type = string
default = "us-west-2"
}
variable "vpc_id" {
description = "VPC ID"
type = string
}
variable "tags" {
description = "Resource tags"
type = map(string)
default = {
Environment = "dev"
Project = "eks-auto-mode"
}
}
# Outputs
output "cluster_endpoint" {
description = "EKS cluster endpoint"
value = aws_eks_cluster.auto_mode.endpoint
}
output "cluster_security_group_id" {
description = "EKS cluster security group ID"
value = aws_eks_cluster.auto_mode.vpc_config[0].cluster_security_group_id
}
output "cluster_arn" {
description = "EKS cluster ARN"
value = aws_eks_cluster.auto_mode.arn
}Running Terraform
# Initialize Terraform
terraform init
# Review plan
terraform plan -var="vpc_id=vpc-12345678"
# Apply
terraform apply -var="vpc_id=vpc-12345678"
# Update kubeconfig
aws eks update-kubeconfig --name my-auto-cluster --region us-west-2Traditional Terraform Configuration
Here's the Terraform configuration for not using Auto Mode:
# Traditional EKS cluster
resource "aws_eks_cluster" "main" {
name = var.cluster_name
role_arn = aws_iam_role.cluster.arn
version = var.kubernetes_version
vpc_config {
subnet_ids = data.aws_subnets.private.ids
endpoint_private_access = true
endpoint_public_access = true
}
enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
depends_on = [
aws_iam_role_policy_attachment.cluster_AmazonEKSClusterPolicy,
]
tags = var.tags
}
# Managed node group
resource "aws_eks_node_group" "main" {
cluster_name = aws_eks_cluster.main.name
node_group_name = "main-nodegroup"
node_role_arn = aws_iam_role.node.arn
subnet_ids = data.aws_subnets.private.ids
capacity_type = "ON_DEMAND"
instance_types = ["m5.large"]
scaling_config {
desired_size = 2
max_size = 3
min_size = 1
}
update_config {
max_unavailable = 1
}
depends_on = [
aws_iam_role_policy_attachment.node_AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.node_AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.node_AmazonEC2ContainerRegistryReadOnly,
]
tags = var.tags
}Creating a Cluster Using AWS CDK
You can create an EKS cluster using AWS CDK (Cloud Development Kit).
EKS Auto Mode Cluster Using TypeScript
// lib/eks-auto-mode-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as eks from 'aws-cdk-lib/aws-eks';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
export class EksAutoModeStack extends cdk.Stack {
constructor(scope: Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
// Import or create VPC
const vpc = ec2.Vpc.fromLookup(this, 'VPC', {
vpcId: 'vpc-12345678' // Existing VPC ID
});
// Or create new VPC
// const vpc = new ec2.Vpc(this, 'EksVpc', {
// maxAzs: 3,
// natGateways: 1,
// });
// Create EKS Auto Mode cluster
const cluster = new eks.Cluster(this, 'AutoModeCluster', {
clusterName: 'my-auto-cluster',
version: eks.KubernetesVersion.V1_31,
vpc: vpc,
vpcSubnets: [
{
subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
}
],
endpointAccess: eks.EndpointAccess.PUBLIC_AND_PRIVATE,
// Auto Mode configuration
defaultCapacity: 0, // Set default capacity to 0 for Auto Mode
// Enable logging
clusterLogging: [
eks.ClusterLoggingTypes.API,
eks.ClusterLoggingTypes.AUDIT,
eks.ClusterLoggingTypes.AUTHENTICATOR,
eks.ClusterLoggingTypes.CONTROLLER_MANAGER,
eks.ClusterLoggingTypes.SCHEDULER,
],
});
// Custom resource to enable Auto Mode
const autoModeConfig = new cdk.CustomResource(this, 'AutoModeConfig', {
serviceToken: this.createAutoModeProvider().serviceToken,
properties: {
ClusterName: cluster.clusterName,
NodeRoleArn: this.createNodeRole().roleArn,
},
});
// Outputs
new cdk.CfnOutput(this, 'ClusterName', {
value: cluster.clusterName,
description: 'EKS cluster name',
});
new cdk.CfnOutput(this, 'ClusterEndpoint', {
value: cluster.clusterEndpoint,
description: 'EKS cluster endpoint',
});
}
private createNodeRole(): iam.Role {
const nodeRole = new iam.Role(this, 'NodeRole', {
assumedBy: new iam.ServicePrincipal('ec2.amazonaws.com'),
managedPolicies: [
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKSWorkerNodePolicy'),
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEKS_CNI_Policy'),
iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonEC2ContainerRegistryReadOnly'),
],
});
return nodeRole;
}
private createAutoModeProvider(): cdk.Provider {
// Lambda function for enabling Auto Mode
const onEvent = new cdk.aws_lambda.Function(this, 'AutoModeHandler', {
runtime: cdk.aws_lambda.Runtime.PYTHON_3_9,
handler: 'index.on_event',
code: cdk.aws_lambda.Code.fromInline(`
import boto3
import json
def on_event(event, context):
print(json.dumps(event))
eks = boto3.client('eks')
cluster_name = event['ResourceProperties']['ClusterName']
node_role_arn = event['ResourceProperties']['NodeRoleArn']
if event['RequestType'] == 'Create' or event['RequestType'] == 'Update':
# Auto Mode enablement logic
try:
response = eks.update_cluster_config(
name=cluster_name,
computeConfig={
'enabled': True,
'nodeRoleArn': node_role_arn
}
)
return {'PhysicalResourceId': cluster_name}
except Exception as e:
print(f"Error: {e}")
raise e
return {'PhysicalResourceId': cluster_name}
`),
});
// Grant EKS permissions to Lambda function
onEvent.addToRolePolicy(new iam.PolicyStatement({
actions: [
'eks:UpdateClusterConfig',
'eks:DescribeCluster',
],
resources: ['*'],
}));
return new cdk.Provider(this, 'AutoModeProvider', {
onEventHandler: onEvent,
});
}
}CDK App Entry Point
// bin/eks-auto-mode.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { EksAutoModeStack } from '../lib/eks-auto-mode-stack';
const app = new cdk.App();
new EksAutoModeStack(app, 'EksAutoModeStack', {
env: {
account: process.env.CDK_DEFAULT_ACCOUNT,
region: process.env.CDK_DEFAULT_REGION,
},
});CDK Deployment
# Install CDK
npm install -g aws-cdk
# Initialize project
cdk init app --language typescript
# Install dependencies
npm install
# CDK bootstrap (only once)
cdk bootstrap
# Deploy
cdk deploy
# Update kubeconfig
aws eks update-kubeconfig --name my-auto-cluster --region us-west-2Configuring Cluster Access
Proper permissions and configuration are required to access an EKS cluster.
kubeconfig Configuration
# Update kubeconfig
aws eks update-kubeconfig --name my-cluster --region us-west-2
# Use specific profile
aws eks update-kubeconfig --name my-cluster --region us-west-2 --profile my-profile
# Use role ARN
aws eks update-kubeconfig --name my-cluster --region us-west-2 --role-arn arn:aws:iam::123456789012:role/EKSAccessRoleRBAC Configuration
# rbac.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
mapRoles: |
- rolearn: arn:aws:iam::123456789012:role/NodeInstanceRole
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
mapUsers: |
- userarn: arn:aws:iam::123456789012:user/admin
username: admin
groups:
- system:masterskubectl apply -f rbac.yamlCluster Validation
Here's how to verify that the cluster was created correctly.
Basic Validation
# Check cluster info
kubectl cluster-info
# Check node status
kubectl get nodes
# Check system pod status
kubectl get pods -n kube-system
# Check service accounts
kubectl get serviceaccounts -n kube-systemAuto Mode Specific Validation
# Check Auto Mode node pools
kubectl get nodepools
# Check Auto Mode node classes
kubectl get nodeclasses
# Check Karpenter status (used in Auto Mode)
kubectl get pods -n karpenterDeploy Sample Application
# sample-app.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: sample-app
spec:
replicas: 2
selector:
matchLabels:
app: sample-app
template:
metadata:
labels:
app: sample-app
spec:
containers:
- name: app
image: nginx:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: sample-app-service
spec:
selector:
app: sample-app
ports:
- port: 80
targetPort: 80
type: LoadBalancerkubectl apply -f sample-app.yaml
kubectl get pods
kubectl get servicesCluster Upgrade
Here's how to upgrade the Kubernetes version of an EKS cluster.
Auto Mode Cluster Upgrade
Auto Mode clusters are automatically upgraded, but manual upgrade is also possible:
# Upgrade using eksctl
eksctl upgrade cluster --name my-auto-cluster --version 1.32
# Upgrade using AWS CLI
aws eks update-cluster-version --name my-auto-cluster --kubernetes-version 1.32Traditional Cluster Upgrade
# Upgrade cluster
eksctl upgrade cluster --name my-cluster --version 1.32
# Upgrade node group
eksctl upgrade nodegroup --cluster my-cluster --name my-nodegroupCluster Deletion
Here's how to delete a cluster.
Delete Using eksctl
eksctl delete cluster --name my-cluster --region us-west-2Delete Using AWS CLI
# Delete node group (for non-Auto Mode)
aws eks delete-nodegroup --cluster-name my-cluster --nodegroup-name my-nodegroup
# Delete cluster
aws eks delete-cluster --name my-clusterDelete Using Terraform
terraform destroyDelete Using CDK
cdk destroyConclusion
There are several methods for creating an EKS cluster, each with its own advantages and disadvantages:
- EKS Auto Mode: Provides production-ready clusters with minimal operational overhead
- eksctl: Simple and fast cluster creation
- AWS Management Console: Intuitive creation through GUI
- AWS CLI: Suitable for script automation
- Terraform: Manage infrastructure as code
- AWS CDK: Define infrastructure using programming languages
For production environments, using EKS Auto Mode or Terraform/CDK is recommended to build consistent and repeatable infrastructure.