[k8s] EKS에서 Karpenter 사용하기 (1)

2025. 1. 5. 23:31·Kubernetes
반응형

1. 유틸리티 설치

카펜터는 헬름 차트를 사용하여 클러스터로 설치된다.

  1. AWS CLI (v2.22.6)
  2. kubectl (v1.31.1)
  3. eksctl (v0.192.0)
  4. helm (v3.16.2)
  5. karpenter (v1.0.5)

사용한 버전은 다음과 같다.


2. 환경 변수 설정

카펜터, 쿠버네티스 버전 설정

export KARPENTER_NAMESPACE="kube-system"
export KARPENTER_VERSION="1.0.5"
export K8S_VERSION="1.31"

 

환경 변수 설정

export AWS_PARTITION="aws"
export CLUSTER_NAME="eks"
export AWS_REGION="ap-northeast-2"
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export NODEGROUP_NAME="karpenter-ng"

export POLICY_ARN="arn:aws:iam::<AWS_ACCOUNT_ID>:policy/KarpenterControllerPolicy-eks"
export ROLE_ARN="arn:aws:iam::<AWS_ACCOUNT_ID>:role/KarpenterControllerRole-eks"

# 임시 파일 지정
export TEMPOUT="$(mktemp)"

# EKS에 최적화된 AMI ID 가져오기 (Amazon Linux 2)
export ARM_AMI_ID="$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2-arm64/recommended/image_id --query Parameter.Value --output text)"
export AMD_AMI_ID="$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2/recommended/image_id --query Parameter.Value --output text)"
export GPU_AMI_ID="$(aws ssm get-parameter --name /aws/service/eks/optimized-ami/${K8S_VERSION}/amazon-linux-2-gpu/recommended/image_id --query Parameter.Value --output text)"

 

값을 기억하기

echo "${KARPENTER_NAMESPACE}" "${KARPENTER_VERSION}" "${K8S_VERSION}" "${CLUSTER_NAME}" "${AWS_REGION}" "${AWS_ACCOUNT_ID}" "${TEMPOUT}" "${ARM_AMI_ID}" "${AMD_AMI_ID}" "${GPU_AMI_ID}"

 


3. IAM 권한 준비

KarpenterControllerRole : Karpenter 컨트롤러에 필요한 역할

echo '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "ec2.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}' > karpenter-trust-policy.json

 

KarpenterNodeRole : Karpenter가 생성하는 노드에 할당할 역할

aws iam create-role --role-name KarpenterControllerRole \
    --assume-role-policy-document file://karpenter-trust-policy.json

 

KarpenterNodeRole에 EKS 노드에게 필수적으로 필요한 권한 4개

  • AmazonEKSWorkerNodePolicy
  • AmazonEKS_CNI_Policy
  • AmazonEC2ContainerRegistryReadOnly
  • AmazonSSMManagedInstanceCore
aws iam attach-role-policy \
    --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy

aws iam attach-role-policy \
    --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \
    --policy-arn arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy

aws iam attach-role-policy \
    --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \
    --policy-arn arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly

aws iam attach-role-policy \
    --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \
    --policy-arn arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore

 

Karpenter가 배포한 EC2에서 해당 Role을 사용할 수 있도록 EC2 Instance Profile을 생성한다.

aws iam create-instance-profile \
    --instance-profile-name "KarpenterNodeInstanceProfile-${CLUSTER_NAME}"

aws iam add-role-to-instance-profile \
    --instance-profile-name "KarpenterNodeInstanceProfile-${CLUSTER_NAME}" \
    --role-name "KarpenterNodeRole-${CLUSTER_NAME}"

 

1. Karpenter 컨트롤러용 IAM Role

이제 Karpenter 컨트롤러가 새 인스턴스를 프로비저닝 하는 데 사용할 IAM 역할을 생성해야 한다.

Karpenter 컨트롤러는 IRSAIAM Role for Service Account 방식으로 IAM 권한을 얻어 EC2 생성, 삭제를 수행한다.

 

 

IAM Role의 신뢰 관계 생성

cat << EOF > controller-trust-policy.json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_ENDPOINT#*//}"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "${OIDC_ENDPOINT#*//}:aud": "sts.amazonaws.com",
                    "${OIDC_ENDPOINT#*//}:sub": "system:serviceaccount:karpenter:karpenter"
                }
            }
        }
    ]
}
EOF

 

 

Karpenter 컨트롤러에서 사용할 IAM Role을 생성한다.

aws iam create-role \
    --role-name KarpenterControllerRole-${CLUSTER_NAME} \
    --assume-role-policy-document file://controller-trust-policy.json

 

 

Karpenter 컨트롤러용 IAM Policy를 생성한다.

cat << EOF > controller-policy.json
{
    "Statement": [
        {
            "Action": [
                "ssm:GetParameter",
                "ec2:DescribeImages",
                "ec2:RunInstances",
                "ec2:DescribeSubnets",
                "ec2:DescribeSecurityGroups",
                "ec2:DescribeLaunchTemplates",
                "ec2:DescribeInstances",
                "ec2:DescribeInstanceTypes",
                "ec2:DescribeInstanceTypeOfferings",
                "ec2:DescribeAvailabilityZones",
                "ec2:DeleteLaunchTemplate",
                "ec2:CreateTags",
                "ec2:CreateLaunchTemplate",
                "ec2:CreateFleet",
                "ec2:DescribeSpotPriceHistory",
                "pricing:GetProducts"
            ],
            "Effect": "Allow",
            "Resource": "*",
            "Sid": "Karpenter"
        },
        {
            "Action": "ec2:TerminateInstances",
            "Condition": {
                "StringLike": {
                    "ec2:ResourceTag/Name": "*karpenter*"
                }
            },
            "Effect": "Allow",
            "Resource": "*",
            "Sid": "ConditionalEC2Termination"
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": "arn:${AWS_PARTITION}:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}",
            "Sid": "PassNodeIAMRole"
        },
        {
            "Effect": "Allow",
            "Action": "eks:DescribeCluster",
            "Resource": "arn:${AWS_PARTITION}:eks:${AWS_REGION}:${AWS_ACCOUNT_ID}:cluster/${CLUSTER_NAME}",
            "Sid": "EKSClusterEndpointLookup"
        }
    ],
    "Version": "2012-10-17"
}
EOF

 

 

Inline Policy를 Karpenter Controller용 IAM Role에 연결한다.

aws iam put-role-policy \
    --role-name KarpenterControllerRole-${CLUSTER_NAME} \
    --policy-name KarpenterControllerPolicy-${CLUSTER_NAME} \
    --policy-document file://controller-policy.json

 

 

2. EKS 클러스터의 서브넷에 태그를 추가하는 AWS CLI 명령어

for 반복문 형태로 여러 서브넷에 한 번에 태그가 추가된다.

for NODEGROUP in $(aws eks list-nodegroups --cluster-name ${CLUSTER_NAME} \
    --query 'nodegroups' --output text); do aws ec2 create-tags \
        --tags "Key=karpenter.sh/discovery,Value=${CLUSTER_NAME}" \
        --resources $(aws eks describe-nodegroup --cluster-name ${CLUSTER_NAME} \
        --nodegroup-name ts-eks --query 'nodegroup.subnets' --output text )
done

 

 

3. 보안 그룹에 태그를 추가하는 CLI 명령어

이 명령은 클러스터의 첫 번째 노드 그룹에 대한 보안 그룹에만 karpenter.sh/discovery 태그를 지정한다.

노드 그룹 또는 보안 그룹이 여러 개인 경우 karpenter가 사용해야 하는 그룹을 결정해야 한다.

NODEGROUP=$(aws eks list-nodegroups --cluster-name ${CLUSTER_NAME} \
    --query 'nodegroups[0]' --output text)

LAUNCH_TEMPLATE=$(aws eks describe-nodegroup --cluster-name ${CLUSTER_NAME} \
    --nodegroup-name ${NODEGROUP} --query 'nodegroup.launchTemplate.{id:id,version:version}' \
    --output text | tr -s "\t" ",")

SECURITY_GROUPS=$(aws eks describe-cluster \
    --name ${CLUSTER_NAME} --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" --output text)

SECURITY_GROUPS=$(aws ec2 describe-launch-template-versions \
    --launch-template-id ${LAUNCH_TEMPLATE%,*} --versions ${LAUNCH_TEMPLATE#*,} \
    --query 'LaunchTemplateVersions[0].LaunchTemplateData.[NetworkInterfaces[0].Groups||SecurityGroupIds]' \
    --output text)

aws ec2 create-tags \
    --tags "Key=karpenter.sh/discovery,Value=${CLUSTER_NAME}" \
    --resources ${SECURITY_GROUPS}

 

 

4. aws-auth configMap 업데이트

방금 생성한 노드 IAM 역할을 사용하는 EC2 노드가 EKS 클러스터에 가입하도록 허용해 준다.

관련 설정은 aws-auth ConfigMap에서 관리된다.

kubectl edit configmap aws-auth -n kube-system
# 변경 전
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/dev-global-eks-node-iam-role
      username: system:node:{{EC2PrivateDNSName}}    
kind: ConfigMap
metadata:
  ...
# 변경 후
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/dev-global-eks-node-iam-role
      username: system:node:{{EC2PrivateDNSName}}
+   - groups:
+     - system:bootstrappers
+     - system:nodes
+     rolearn: arn:aws:iam::<AWS_ACCOUNT_ID>:role/KarpenterNodeRole-eks
+     username: system:node:{{EC2PrivateDNSName}}
kind: ConfigMap
metadata:
  ...

참고로, ControllerRole이 아니라 NodeRole을 써야 한다.

 


4. Karpenter 설치

helm registry logout public.ecr.aws

Helm을 사용하여 Public ECR에서 Karpenter 이미지를 설치할 때 인증 없이(unauthenticated) 접근이 가능하도록 하기 위함이다.

Public ECR은 기본적으로 공개되어 있으므로 인증 없이 이미지를 받을 수 있다. 하지만 인증 세션이 활성화되어 있으면 인증 관련 문제가 발생할 가능성이 있으므로 이를 방지한다.

 

로그아웃되면 이후의 Helm 명령어는 인증 없이 Public ECR에서 이미지를 다운로드하게 된다.

 

helm 차트에서 Karpenter 배포 yaml을 생성할 수 있다.

helm template karpenter oci://public.ecr.aws/karpenter/karpenter \
    --version ${KARPENTER_VERSION} \
    --namespace karpenter \
    --set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \
    --set settings.aws.clusterName=${CLUSTER_NAME} \
    --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"="${ROLE_ARN}" \
    --set controller.resources.requests.cpu=0.5 \
    --set controller.resources.requests.memory=512Mi \
    --set controller.resources.limits.cpu=0.5 \
    --set controller.resources.limits.memory=512Mi \
    --set replicas=2 > karpenter.yaml

 

OCI Helm 차트는 릴리스 프로세스의 일부로 Cosign 에 의해 서명되었으므로 다음 명령을 실행하여 설치하기 전에 차트를 확인할 수 있다.

Sigstore의 Cosign 도구를 사용하여 컨테이너 이미지의 서명을 검증하는 과정이다.

이 예에서는 Karpenter 컨테이너 이미지의 서명을 검증하고, 이 이미지가 신뢰할 수 있는 소스에서 빌드되었음을 확인한다.

프로덕션 환경에서 신뢰할 수 없는 이미지를 사용하는 위험을 줄이기 위해 실행한다.

cosign verify public.ecr.aws/karpenter/karpenter:1.0.5 \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com \
  --certificate-identity-regexp='https://github\.com/aws/karpenter-provider-aws/\.github/workflows/release\.yaml@.+' \
  --certificate-github-workflow-repository=aws/karpenter-provider-aws \
  --certificate-github-workflow-name=Release \
  --certificate-github-workflow-ref=refs/tags/v1.0.5 \
  --annotations version=1.0.5

 


 

반응형

'Kubernetes' 카테고리의 다른 글

[k8s] EKS에서 Karpenter 사용하기 (2)  (1) 2025.01.05
[k8s] karpenter란?  (2) 2025.01.04
'Kubernetes' 카테고리의 다른 글
  • [k8s] EKS에서 Karpenter 사용하기 (2)
  • [k8s] karpenter란?
ssu_dev
ssu_dev
  • ssu_dev
    ssu
    ssu_dev
  • 전체
    오늘
    어제
    • 분류 전체보기 (71) N
      • Infra (10) N
      • Kubernetes (3)
      • Algorithm (42)
      • Computer Science (5)
      • Trouble Shooting (4)
      • System (5)
      • Work (1)
      • Git (1)
  • 블로그 메뉴

    • 홈
    • 태그
  • 링크

  • 인기 글

  • 태그

    자료구조
    BOJ
    priorityqueue
    Pod Scheduling
    Karpenter
    투포인터
    cs
    bfs
    구현
    Deque
    sort
    Stack
    EKS
    Java
    docker
    dfs
    OS
    K8s
    node scaling
    플로이드 워셜
  • 최근 글

  • hELLO· Designed By정상우.v4.10.1
ssu_dev
[k8s] EKS에서 Karpenter 사용하기 (1)
상단으로

티스토리툴바