Ssoon

[5주차] EKS Autoscaling - KARPENTER - INSTALL KARPENTER 본문

AWS EKS Workshop Study

[5주차] EKS Autoscaling - KARPENTER - INSTALL KARPENTER

구구달스 2023. 5. 25. 07:59
CloudNet@ 팀의 AWS EKS Workshop Study 5주차 정리입니다.
# Karpenter Workshop 의 내용입니다.

Karpenter는 Kubernetes용으로 구축된 오픈 소스 자동 확장 프로젝트입니다. Karpenter는 예약할 수 없는 포드의 총 리소스 요청을 관찰하고 클러스터 비용을 최적화하기 위해 노드를 시작 및 종료하도록 결정하여 몇 분이 아닌 몇 초 만에 애플리케이션의 요구 사항에 맞는 올바른 컴퓨팅 리소스를 제공하도록 설계되었습니다.


환경 설정

Karpenter에서 시작한 인스턴스는 컨테이너를 실행하고 네트워킹을 구성하는 데 필요한 권한을 부여하는 InstanceProfile로 실행해야 합니다. Karpenter는 이름 KarpenterNodeRole-${ClusterName}을 사용하여 InstanceProfile을 검색합니다. Karpenter는 또한 SQS 대기열 및 EventBridge 규칙을 활용하여 스팟 중단 알림 및 AWS 상태 이벤트를 처리합니다.

export KARPENTER_VERSION=v0.26.1
echo "export KARPENTER_VERSION=${KARPENTER_VERSION}" >> ~/.bash_profile
TEMPOUT=$(mktemp)
curl -fsSL https://karpenter.sh/"${KARPENTER_VERSION}"/getting-started/getting-started-with-eksctl/cloudformation.yaml > $TEMPOUT \
&& aws cloudformation deploy \
  --stack-name Karpenter-${CLUSTER_NAME} \
  --template-file ${TEMPOUT} \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides ClusterName=${CLUSTER_NAME}

둘째, 프로필을 사용하여 인스턴스에 대한 액세스 권한을 부여하여 클러스터에 연결합니다. 이 명령은 Karpenter 노드 역할을 aws-auth configmap에 추가하여 이 역할을 가진 노드가 클러스터에 연결할 수 있도록 합니다.

eksctl create iamidentitymapping \
  --username system:node:{{EC2PrivateDNSName}} \
  --cluster  ${CLUSTER_NAME} \
  --arn arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME} \
  --group system:bootstrappers \
  --group system:nodes

인증 맵(auth map)에 있는지 확인할 수 있습니다.

kubectl describe configmap -n kube-system aws-auth

KarpenterController IAM Role 생성

서비스 계정에 대한 IAM 역할을 추가하기 전에 클러스터에 대한 IAM OIDC 자격 증명 공급자를 생성해야 합니다.

eksctl utils associate-iam-oidc-provider --cluster ${CLUSTER_NAME} --approve

Karpenter에는 인스턴스 시작과 같은 권한이 필요합니다. 이렇게 하면 AWS IAM 역할, Kubernetes 서비스 계정이 생성되고 서비스 계정에 대한 IAM 역할(IRSA)을 사용하여 연결됩니다.

eksctl create iamserviceaccount \
  --cluster $CLUSTER_NAME --name karpenter --namespace karpenter \
  --role-name "${CLUSTER_NAME}-karpenter" \
  --attach-policy-arn arn:aws:iam::$AWS_ACCOUNT_ID:policy/KarpenterControllerPolicy-$CLUSTER_NAME \
  --role-only \
  --approve


[ Karpenter 설치 ]

Karpenter Helm 차트 설치

helm을 사용하여 Karpenter를 클러스터에 배포합니다

export KARPENTER_IAM_ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/${CLUSTER_NAME}-karpenter"
export CLUSTER_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text)"
echo "export KARPENTER_IAM_ROLE_ARN=${KARPENTER_IAM_ROLE_ARN}" >> ~/.bash_profile
echo "export CLUSTER_ENDPOINT=${CLUSTER_ENDPOINT}" >> ~/.bash_profile
helm upgrade --install --namespace karpenter --create-namespace \
  karpenter oci://public.ecr.aws/karpenter/karpenter \
  --version ${KARPENTER_VERSION}\
  --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=${KARPENTER_IAM_ROLE_ARN} \
  --set settings.aws.clusterName=${CLUSTER_NAME} \
  --set settings.aws.clusterEndpoint=${CLUSTER_ENDPOINT} \
  --set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \
  --set settings.aws.interruptionQueueName=${CLUSTER_NAME} \
  --set nodeSelector.intent=control-apps \
  --wait

Karpenter 구성은 CRD(Custom Resource Definition)를 통해 제공됩니다. 

Karpenter 컨트롤러가 클러스터 API 서버에 연결할 수 있도록 CLUSTER_NAME 및 CLUSTER_ENDPOINT를 모두 사용합니다.

--set nodeSelector.intent=control-apps

클러스터로 생성된 온디맨드 관리형 노드 그룹에 컨트롤러를 배포합니다.

--set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME}

컨테이너를 실행하고 네트워킹을 구성하기 위해 인스턴스에 필요한 권한을 부여하기 위해 이전에 생성한 인스턴스 프로파일을 사용합니다.

--set settings.aws.interruptionQueueName=${CLUSTER_NAME}

이전 CloudFormation 스택에서 생성된 SQS 대기열을 사용하여 스팟 중단 알림 및 AWS 상태 이벤트를 처리합니다.

--wait

제공자 컨트롤러가 배포될 때까지 대기하도록 webhook 컨트롤러에 알립니다.

설치정보를 확인합니다.

Karpenter는 2개의 복제본을 배포합니다. 
복제본 중 하나는 리더로 선출되고 다른 하나는 대기 모드를 유지합니다. 
karpenter 배포는 또한 topologySpreadConstraints를 사용하여 각 복제본을 다른 AZ에 분산시킵니다.

 

[ SET UP THE PROVISIONER ]

기본 CRD 제공자 설정

Karpenter 구성은 프로비저너 CRD(Custom Resource Definition)의 형태로 제공됩니다.

단일 Karpenter 프로비저너는 다양한 포드 모양을 처리할 수 있습니다. Karpenter는 labels  affinity 와 같은 Pod 속성을 기반으로 스케줄링 및 프로비저닝 결정을 내립니다.

클러스터에는 프로비저너가 두 개 이상 있을 수 있지만 지금은 기본 프로비저너 하나만 선언합니다.

cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  labels:
    intent: apps
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot"]
    - key: karpenter.k8s.aws/instance-size
      operator: NotIn
      values: [nano, micro, small, medium, large]
  limits:
    resources:
      cpu: 1000
      memory: 1000Gi
  ttlSecondsAfterEmpty: 30
  ttlSecondsUntilExpired: 2592000
  providerRef:
    name: default
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:
  subnetSelector:
    alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
  securityGroupSelector:
    alpha.eksctl.io/cluster-name: ${CLUSTER_NAME}
  tags:
    KarpenerProvisionerName: "default"
    NodeType: "karpenter-workshop"
    IntentLabel: "apps"
EOF

provider 에 대한 구성은 두 부분으로 나뉩니다.

첫 번째는 제공자 관련 사양을 정의합니다.

두 번째 부분은 provider 구현(이 경우 AWSNodeTemplate)에 의해 정의되며 해당 클라우드 공급자에 적용되는 특정 구성을 정의합니다. 

Requirements Section

프로비저너 CRD는 인스턴스 유형 및 영역과 같은 노드 속성 정의를 지원합니다. 예를 들어 topology.kubernetes.io/zone=us-east-1c 레이블에 대한 응답으로 Karpenter는 해당 가용성 영역에 노드를 프로비저닝합니다. 이 예에서는 karpenter.sh/capacity-type을 설정하여 EC2 스팟 인스턴스를 조달하고 karpenter.k8s.aws/instance-size를 설정하여 더 작은 인스턴스를 방지합니다.

Limits section

프로비저너는 특정 프로비저너와 클러스터의 일부에 할당된 CPU 및 메모리 수의 제한을 정의할 수 있습니다.

ttlSecondsAfterEmpty

값은 빈 노드를 종료하도록 Karpenter를 구성합니다. 값을 정의되지 않은 상태로 두면 이 동작을 비활성화할 수 있습니다. 이 경우 빠른 데모를 위해 30초 값으로 설정했습니다.

ttlSecondsUntilExpired

선택적 매개변수. 설정되면 노드가 삭제되는 시기를 정의합니다. 이는 최신 AMI로 새 노드를 강제 실행하는 데 유용합니다. 이 예에서는 값을 30일로 설정했습니다.

Provider section

이 프로비저너는 securityGroupSelector 및 subnetSelector를 사용하여 노드를 시작하는 데 사용되는 리소스를 검색합니다. Karpenter가 서브넷에 첨부한 태그를 사용합니다.

Tags

프로비저너는 EC2 인스턴스가 생성 시 갖게 될 태그 세트를 정의할 수도 있습니다. 이는 EC2 수준에서 accounting 및 거버넌스를 활성화하는 데 도움이 됩니다. provider 섹션의 일부로 수행됩니다.


Karpenter 로그 표시

karpenter 로그를 읽으려면 먼저 선출된 리더 역할을 하는 포드를 찾고 여기에서 로그를 가져와야 합니다. 다음 줄은 이를 자동화하는 데 사용할 수 있는 별칭을 설정합니다. 별칭은 모든 Karpenter 컨트롤러 로그의 헤더를 찾고, 선출된 리더 메시지가 있는 포드를 검색하고 라인 스트리밍을 시작합니다.

alias kl='kubectl logs deploy/karpenter -n karpenter -f --tail=20'

Karpenter 로그 구성은 Kubernetes ConfigMap으로 저장됩니다.

kubectl describe configmap config-logging -n karpenter 명령을 실행하여 구성을 읽을 수 있습니다. 다음 명령을 사용하여 Karpenter Helm 릴리스를 업그레이드하여 디버깅할 로깅 수준을 높일 수 있습니다.

helm upgrade --namespace karpenter karpenter karpenter/karpenter --set logLevel=debug --reuse-values

 

Comments