View a markdown version of this page

Getting started with Amazon EKS - AWS SDK Code Examples

There are more AWS SDK examples available in the AWS Doc SDK Examples GitHub repo.

Getting started with Amazon EKS

The following code example shows how to:

  • Create a VPC for your EKS cluster

  • Create IAM roles for your EKS cluster

  • Create your EKS cluster

  • Configure kubectl to communicate with your cluster

  • Create a managed node group

  • Clean up resources

Bash
AWS CLI with Bash script
Note

There's more on GitHub. Find the complete example and learn how to set up and run in the Sample developer tutorials repository.

#!/bin/bash # Amazon EKS Cluster Creation Script (v2) # This script creates an Amazon EKS cluster with a managed node group using the AWS CLI # Set up logging LOG_FILE="eks-cluster-creation-v2.log" exec > >(tee -a "$LOG_FILE") 2>&1 echo "Starting Amazon EKS cluster creation script at $(date)" echo "All commands and outputs will be logged to $LOG_FILE" # Error handling function handle_error() { echo "ERROR: $1" echo "Attempting to clean up resources..." cleanup_resources exit 1 } # Function to check command success check_command() { if [ $? -ne 0 ] || echo "$1" | grep -i "error" > /dev/null; then handle_error "$1" fi } # Function to check if kubectl is installed check_kubectl() { if ! command -v kubectl &> /dev/null; then echo "WARNING: kubectl is not installed or not in your PATH." echo "" echo "To install kubectl, follow these instructions based on your operating system:" echo "" echo "For Linux:" echo " 1. Download the latest release:" echo " curl -LO \"https://dl.k8s.io/release/\$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl\"" echo "" echo " 2. Make the kubectl binary executable:" echo " chmod +x ./kubectl" echo "" echo " 3. Move the binary to your PATH:" echo " sudo mv ./kubectl /usr/local/bin/kubectl" echo "" echo "For macOS:" echo " 1. Using Homebrew:" echo " brew install kubectl" echo " or" echo " 2. Using curl:" echo " curl -LO \"https://dl.k8s.io/release/\$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl\"" echo " chmod +x ./kubectl" echo " sudo mv ./kubectl /usr/local/bin/kubectl" echo "" echo "For Windows:" echo " 1. Using curl:" echo " curl -LO \"https://dl.k8s.io/release/v1.28.0/bin/windows/amd64/kubectl.exe\"" echo " Add the binary to your PATH" echo " or" echo " 2. Using Chocolatey:" echo " choco install kubernetes-cli" echo "" echo "After installation, verify with: kubectl version --client" echo "" return 1 fi return 0 } # Generate a random identifier for resource names RANDOM_ID=$(LC_ALL=C tr -dc 'a-z0-9' < /dev/urandom | fold -w 6 | head -n 1) STACK_NAME="eks-vpc-stack-${RANDOM_ID}" CLUSTER_NAME="eks-cluster-${RANDOM_ID}" NODEGROUP_NAME="eks-nodegroup-${RANDOM_ID}" CLUSTER_ROLE_NAME="EKSClusterRole-${RANDOM_ID}" NODE_ROLE_NAME="EKSNodeRole-${RANDOM_ID}" echo "Using the following resource names:" echo "- VPC Stack: $STACK_NAME" echo "- EKS Cluster: $CLUSTER_NAME" echo "- Node Group: $NODEGROUP_NAME" echo "- Cluster IAM Role: $CLUSTER_ROLE_NAME" echo "- Node IAM Role: $NODE_ROLE_NAME" # Array to track created resources for cleanup declare -a CREATED_RESOURCES # Function to clean up resources cleanup_resources() { echo "Cleaning up resources in reverse order..." # Check if node group exists and delete it if aws eks list-nodegroups --cluster-name "$CLUSTER_NAME" --query "nodegroups[?contains(@,'$NODEGROUP_NAME')]" --output text 2>/dev/null | grep -q "$NODEGROUP_NAME"; then echo "Deleting node group: $NODEGROUP_NAME" aws eks delete-nodegroup --cluster-name "$CLUSTER_NAME" --nodegroup-name "$NODEGROUP_NAME" echo "Waiting for node group deletion to complete..." aws eks wait nodegroup-deleted --cluster-name "$CLUSTER_NAME" --nodegroup-name "$NODEGROUP_NAME" echo "Node group deleted successfully." fi # Check if cluster exists and delete it if aws eks describe-cluster --name "$CLUSTER_NAME" 2>/dev/null; then echo "Deleting cluster: $CLUSTER_NAME" aws eks delete-cluster --name "$CLUSTER_NAME" echo "Waiting for cluster deletion to complete (this may take several minutes)..." aws eks wait cluster-deleted --name "$CLUSTER_NAME" echo "Cluster deleted successfully." fi # Check if CloudFormation stack exists and delete it if aws cloudformation describe-stacks --stack-name "$STACK_NAME" 2>/dev/null; then echo "Deleting CloudFormation stack: $STACK_NAME" aws cloudformation delete-stack --stack-name "$STACK_NAME" echo "Waiting for CloudFormation stack deletion to complete..." aws cloudformation wait stack-delete-complete --stack-name "$STACK_NAME" echo "CloudFormation stack deleted successfully." fi # Clean up IAM roles if aws iam get-role --role-name "$NODE_ROLE_NAME" 2>/dev/null; then echo "Detaching policies from node role: $NODE_ROLE_NAME" aws iam detach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy --role-name "$NODE_ROLE_NAME" aws iam detach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly --role-name "$NODE_ROLE_NAME" aws iam detach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy --role-name "$NODE_ROLE_NAME" echo "Deleting node role: $NODE_ROLE_NAME" aws iam delete-role --role-name "$NODE_ROLE_NAME" echo "Node role deleted successfully." fi if aws iam get-role --role-name "$CLUSTER_ROLE_NAME" 2>/dev/null; then echo "Detaching policies from cluster role: $CLUSTER_ROLE_NAME" aws iam detach-role-policy --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy --role-name "$CLUSTER_ROLE_NAME" echo "Deleting cluster role: $CLUSTER_ROLE_NAME" aws iam delete-role --role-name "$CLUSTER_ROLE_NAME" echo "Cluster role deleted successfully." fi echo "Cleanup complete." } # Trap to ensure cleanup on script exit trap 'echo "Script interrupted. Cleaning up resources..."; cleanup_resources; exit 1' SIGINT SIGTERM # Verify AWS CLI configuration echo "Verifying AWS CLI configuration..." AWS_ACCOUNT_INFO=$(aws sts get-caller-identity) check_command "$AWS_ACCOUNT_INFO" echo "AWS CLI is properly configured." # Step 1: Create VPC using CloudFormation echo "Step 1: Creating VPC with CloudFormation..." echo "Creating CloudFormation stack: $STACK_NAME" # Create the CloudFormation stack CF_CREATE_OUTPUT=$(aws cloudformation create-stack \ --stack-name "$STACK_NAME" \ --template-url https://s3.us-west-2.amazonaws.com/amazon-eks/cloudformation/2020-10-29/amazon-eks-vpc-private-subnets.yaml) check_command "$CF_CREATE_OUTPUT" CREATED_RESOURCES+=("CloudFormation Stack: $STACK_NAME") echo "Waiting for CloudFormation stack to complete (this may take a few minutes)..." aws cloudformation wait stack-create-complete --stack-name "$STACK_NAME" if [ $? -ne 0 ]; then handle_error "CloudFormation stack creation failed" fi echo "CloudFormation stack created successfully." # Step 2: Create IAM roles for EKS echo "Step 2: Creating IAM roles for EKS..." # Create cluster role trust policy echo "Creating cluster role trust policy..." 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 cluster role echo "Creating cluster IAM role: $CLUSTER_ROLE_NAME" CLUSTER_ROLE_OUTPUT=$(aws iam create-role \ --role-name "$CLUSTER_ROLE_NAME" \ --assume-role-policy-document file://"eks-cluster-role-trust-policy.json") check_command "$CLUSTER_ROLE_OUTPUT" CREATED_RESOURCES+=("IAM Role: $CLUSTER_ROLE_NAME") # Attach policy to cluster role echo "Attaching EKS cluster policy to role..." ATTACH_CLUSTER_POLICY_OUTPUT=$(aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEKSClusterPolicy \ --role-name "$CLUSTER_ROLE_NAME") check_command "$ATTACH_CLUSTER_POLICY_OUTPUT" # Create node role trust policy echo "Creating node role trust policy..." cat > node-role-trust-policy.json << EOF { "Version":"2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "ec2.amazonaws.com" }, "Action": "sts:AssumeRole" } ] } EOF # Create node role echo "Creating node IAM role: $NODE_ROLE_NAME" NODE_ROLE_OUTPUT=$(aws iam create-role \ --role-name "$NODE_ROLE_NAME" \ --assume-role-policy-document file://"node-role-trust-policy.json") check_command "$NODE_ROLE_OUTPUT" CREATED_RESOURCES+=("IAM Role: $NODE_ROLE_NAME") # Attach policies to node role echo "Attaching EKS node policies to role..." ATTACH_NODE_POLICY1_OUTPUT=$(aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy \ --role-name "$NODE_ROLE_NAME") check_command "$ATTACH_NODE_POLICY1_OUTPUT" ATTACH_NODE_POLICY2_OUTPUT=$(aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly \ --role-name "$NODE_ROLE_NAME") check_command "$ATTACH_NODE_POLICY2_OUTPUT" ATTACH_NODE_POLICY3_OUTPUT=$(aws iam attach-role-policy \ --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy \ --role-name "$NODE_ROLE_NAME") check_command "$ATTACH_NODE_POLICY3_OUTPUT" # Step 3: Get VPC and subnet information echo "Step 3: Getting VPC and subnet information..." VPC_ID=$(aws cloudformation describe-stacks \ --stack-name "$STACK_NAME" \ --query "Stacks[0].Outputs[?OutputKey=='VpcId'].OutputValue" \ --output text) if [ -z "$VPC_ID" ]; then handle_error "Failed to get VPC ID from CloudFormation stack" fi echo "VPC ID: $VPC_ID" SUBNET_IDS=$(aws cloudformation describe-stacks \ --stack-name "$STACK_NAME" \ --query "Stacks[0].Outputs[?OutputKey=='SubnetIds'].OutputValue" \ --output text) if [ -z "$SUBNET_IDS" ]; then handle_error "Failed to get Subnet IDs from CloudFormation stack" fi echo "Subnet IDs: $SUBNET_IDS" SECURITY_GROUP_ID=$(aws cloudformation describe-stacks \ --stack-name "$STACK_NAME" \ --query "Stacks[0].Outputs[?OutputKey=='SecurityGroups'].OutputValue" \ --output text) if [ -z "$SECURITY_GROUP_ID" ]; then handle_error "Failed to get Security Group ID from CloudFormation stack" fi echo "Security Group ID: $SECURITY_GROUP_ID" # Step 4: Create EKS cluster echo "Step 4: Creating EKS cluster: $CLUSTER_NAME" CLUSTER_ROLE_ARN=$(aws iam get-role --role-name "$CLUSTER_ROLE_NAME" --query "Role.Arn" --output text) if [ -z "$CLUSTER_ROLE_ARN" ]; then handle_error "Failed to get Cluster Role ARN" fi echo "Creating EKS cluster (this will take 10-15 minutes)..." CREATE_CLUSTER_OUTPUT=$(aws eks create-cluster \ --name "$CLUSTER_NAME" \ --role-arn "$CLUSTER_ROLE_ARN" \ --resources-vpc-config subnetIds="$SUBNET_IDS",securityGroupIds="$SECURITY_GROUP_ID") check_command "$CREATE_CLUSTER_OUTPUT" CREATED_RESOURCES+=("EKS Cluster: $CLUSTER_NAME") echo "Waiting for EKS cluster to become active (this may take 10-15 minutes)..." aws eks wait cluster-active --name "$CLUSTER_NAME" if [ $? -ne 0 ]; then handle_error "Cluster creation failed or timed out" fi echo "EKS cluster is now active." # Step 5: Configure kubectl echo "Step 5: Configuring kubectl to communicate with the cluster..." # Check if kubectl is installed if ! check_kubectl; then echo "Will skip kubectl configuration steps but continue with the script." echo "You can manually configure kubectl later with: aws eks update-kubeconfig --name \"$CLUSTER_NAME\"" else UPDATE_KUBECONFIG_OUTPUT=$(aws eks update-kubeconfig --name "$CLUSTER_NAME") check_command "$UPDATE_KUBECONFIG_OUTPUT" echo "kubectl configured successfully." # Test kubectl configuration echo "Testing kubectl configuration..." KUBECTL_TEST_OUTPUT=$(kubectl get svc 2>&1) if [ $? -ne 0 ]; then echo "Warning: kubectl configuration test failed. This might be due to permissions or network issues." echo "Error details: $KUBECTL_TEST_OUTPUT" echo "Continuing with script execution..." else echo "$KUBECTL_TEST_OUTPUT" echo "kubectl configuration test successful." fi fi # Step 6: Create managed node group echo "Step 6: Creating managed node group: $NODEGROUP_NAME" NODE_ROLE_ARN=$(aws iam get-role --role-name "$NODE_ROLE_NAME" --query "Role.Arn" --output text) if [ -z "$NODE_ROLE_ARN" ]; then handle_error "Failed to get Node Role ARN" fi # Convert comma-separated subnet IDs to space-separated for the create-nodegroup command SUBNET_IDS_ARRAY=(${SUBNET_IDS//,/ }) echo "Creating managed node group (this will take 5-10 minutes)..." CREATE_NODEGROUP_OUTPUT=$(aws eks create-nodegroup \ --cluster-name "$CLUSTER_NAME" \ --nodegroup-name "$NODEGROUP_NAME" \ --node-role "$NODE_ROLE_ARN" \ --subnets "${SUBNET_IDS_ARRAY[@]}") check_command "$CREATE_NODEGROUP_OUTPUT" CREATED_RESOURCES+=("EKS Node Group: $NODEGROUP_NAME") echo "Waiting for node group to become active (this may take 5-10 minutes)..." aws eks wait nodegroup-active --cluster-name "$CLUSTER_NAME" --nodegroup-name "$NODEGROUP_NAME" if [ $? -ne 0 ]; then handle_error "Node group creation failed or timed out" fi echo "Node group is now active." # Step 7: Verify nodes echo "Step 7: Verifying nodes..." echo "Waiting for nodes to register with the cluster (this may take a few minutes)..." sleep 60 # Give nodes more time to register # Check if kubectl is installed before attempting to use it if ! check_kubectl; then echo "Cannot verify nodes without kubectl. Skipping this step." echo "You can manually verify nodes after installing kubectl with: kubectl get nodes" else NODES_OUTPUT=$(kubectl get nodes 2>&1) if [ $? -ne 0 ]; then echo "Warning: Unable to get nodes. This might be due to permissions or the nodes are still registering." echo "Error details: $NODES_OUTPUT" echo "Continuing with script execution..." else echo "$NODES_OUTPUT" echo "Nodes verified successfully." fi fi # Step 8: View resources echo "Step 8: Viewing cluster resources..." echo "Cluster information:" CLUSTER_INFO=$(aws eks describe-cluster --name "$CLUSTER_NAME") echo "$CLUSTER_INFO" echo "Node group information:" NODEGROUP_INFO=$(aws eks describe-nodegroup --cluster-name "$CLUSTER_NAME" --nodegroup-name "$NODEGROUP_NAME") echo "$NODEGROUP_INFO" echo "Kubernetes resources:" if ! check_kubectl; then echo "Cannot list Kubernetes resources without kubectl. Skipping this step." echo "You can manually list resources after installing kubectl with: kubectl get all --all-namespaces" else KUBE_RESOURCES=$(kubectl get all --all-namespaces 2>&1) if [ $? -ne 0 ]; then echo "Warning: Unable to get Kubernetes resources. This might be due to permissions." echo "Error details: $KUBE_RESOURCES" echo "Continuing with script execution..." else echo "$KUBE_RESOURCES" fi fi # Display summary of created resources echo "" echo "===========================================" echo "RESOURCES CREATED" echo "===========================================" for resource in "${CREATED_RESOURCES[@]}"; do echo "- $resource" done echo "===========================================" # Prompt for cleanup echo "" echo "===========================================" echo "CLEANUP CONFIRMATION" echo "===========================================" echo "Do you want to clean up all created resources? (y/n): " read -r CLEANUP_CHOICE if [[ "${CLEANUP_CHOICE,,}" == "y" ]]; then cleanup_resources else echo "Resources will not be cleaned up. You can manually clean them up later." echo "To clean up resources, run the following commands:" echo "1. Delete node group: aws eks delete-nodegroup --cluster-name $CLUSTER_NAME --nodegroup-name $NODEGROUP_NAME" echo "2. Wait for node group deletion: aws eks wait nodegroup-deleted --cluster-name $CLUSTER_NAME --nodegroup-name $NODEGROUP_NAME" echo "3. Delete cluster: aws eks delete-cluster --name $CLUSTER_NAME" echo "4. Wait for cluster deletion: aws eks wait cluster-deleted --name $CLUSTER_NAME" echo "5. Delete CloudFormation stack: aws cloudformation delete-stack --stack-name $STACK_NAME" echo "6. Detach and delete IAM roles for the node group and cluster" fi echo "Script completed at $(date)"