There are more AWS SDK examples available in the AWS Doc SDK Examples
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)"-
For API details, see the following topics in AWS CLI Command Reference.
-
Scenarios
Elastic Beanstalk