관리형 쿠버네티스 클러스터 시작하기
관리형 쿠버네티스 클러스터 시작하기
이 코드 예제에서는 AWS CLI로 Amazon EKS 클러스터와 관리형 노드 그룹을 만드는 방법을 보여드려요.
출처: 문서
본문
다음 작업을 다루어요.
- EKS 클러스터용 VPC 생성
- EKS 클러스터용 IAM 역할 생성
- EKS 클러스터 생성
- kubectl이 클러스터와 통신하도록 구성
- 관리형 노드 그룹 생성
- 리소스 정리
Bash (AWS CLI with Bash script)
Note GitHub에 더 많은 내용이 있어요. 전체 예제와 설정·실행 방법은 Sample developer tutorials 저장소에서 확인할 수 있어요.
이 스크립트는 CloudFormation으로 VPC를 만들고 IAM 역할(클러스터·노드 역할)을 생성한 뒤 EKS 클러스터와 관리형 노드 그룹을 만들어요.
#!/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 \
--tags Key=project,Value=doc-smith Key=tutorial,Value=eks-gs)
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"
aws iam tag-role --role-name "$CLUSTER_ROLE_NAME" \
--tags Key=project,Value=doc-smith Key=tutorial,Value=eks-gs
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"
aws iam tag-role --role-name "$NODE_ROLE_NAME" \
--tags Key=project,Value=doc-smith Key=tutorial,Value=eks-gs
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" \
--tags Key=project,Value=doc-smith,Key=tutorial,Value=eks-gs)
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[@]}" \
--tags Key=project,Value=doc-smith,Key=tutorial,Value=eks-gs)
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)"
API 상세는 AWS CLI Command Reference의 다음 항목을 참고해요.
AttachRolePolicy,CreateCluster,CreateNodegroup,CreateRole,CreateStack,DeleteCluster,DeleteNodegroup,DeleteRole,DeleteStack,DescribeCluster,DescribeNodegroup,DescribeStacks,DetachRolePolicy,GetCallerIdentity,GetRole,ListNodegroups,UpdateKubeconfig,Wait (CloudFormation),Wait (Amazon EKS)