새소식

AWS/EKS

[EKS Study 5주차] EKS AutoScaling - Karpenter

  • -

CloudNet@ 팀의 가시다님께서 Leading 하시는 AEWS Study 5주차 스터디 내용 정리

이번 포스팅에서는 EKS AutoScaling 중 Node 오토스케일링 기능인 Karpenter 에 대해 알아보겠습니다.

 

1. Karpenter

 

Karpenter 는 오픈소스 노드 수명 주기 관리 솔루션으로, 몇 초 만에 컴퓨팅 리소스를 제공할 수 있습니다.

기존 CA 의 단점인 느린 동작 시간과 비효율을 보완하는 솔루션이며 현재 AWS 에서 EKS 를 사용할 때 핵심 도구가 되어 가고 있습니다.

 

Karpenter 공식 문서

 

Karpenter

Just-in-time Nodes for Any Kubernetes Cluster

karpenter.sh

 

1.1. Karpenter 동작을 위한 AWS Resource 생성

 

Karpenter 설치는 공식 문서에 나와있는 방식으로 설치하겠습니다.

 

Getting Started with Karpenter

Set up a cluster and add Karpenter

karpenter.sh

 

해당 CloudFormation 배포시 IAM Role, SQS 등의 리소스가 배포됩니다.

curl -fsSL https://karpenter.sh/"${KARPENTER_VERSION}"/getting-started/getting-started-with-karpenter/cloudformation.yaml  > $TEMPOUT \
&& aws cloudformation deploy \
  --stack-name "Karpenter-${CLUSTER_NAME}" \
  --template-file "${TEMPOUT}" \
  --capabilities CAPABILITY_NAMED_IAM \
  --parameter-overrides "ClusterName=${CLUSTER_NAME}"

 

1.2. EKS 배포

eksctl create cluster -f - <<EOF
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
  name: ${CLUSTER_NAME}
  region: ${AWS_DEFAULT_REGION}
  version: "1.24"
  tags:
    karpenter.sh/discovery: ${CLUSTER_NAME}

iam:
  withOIDC: true
  serviceAccounts:
  - metadata:
      name: karpenter
      namespace: karpenter
    roleName: ${CLUSTER_NAME}-karpenter
    attachPolicyARNs:
    - arn:aws:iam::${AWS_ACCOUNT_ID}:policy/KarpenterControllerPolicy-${CLUSTER_NAME}
    roleOnly: true

iamIdentityMappings:
- arn: "arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterNodeRole-${CLUSTER_NAME}"
  username: system:node:{{EC2PrivateDNSName}}
  groups:
  - system:bootstrappers
  - system:nodes

managedNodeGroups:
- instanceType: m5.large
  amiFamily: AmazonLinux2
  name: ${CLUSTER_NAME}-ng
  desiredCapacity: 2
  minSize: 1
  maxSize: 10
  iam:
    withAddonPolicies:
      externalDNS: true
EOF

 

설치 후, IRSA 매핑을 확인해봅니다.

eksctl get iamidentitymapping --cluster $CLUSTER_NAME
eksctl get iamserviceaccount --cluster $CLUSTER_NAME

 

 

Karpenter 가 리소스를 사용하기 위한 auth 또한 적용이 되어 있습니다.

kubectl describe cm -n kube-system aws-auth

 

 

1.3. Karpenter 설치

 

Karpenter 설치를 위한 변수를 지정해줍니다.

export CLUSTER_ENDPOINT="$(aws eks describe-cluster --name ${CLUSTER_NAME} --query "cluster.endpoint" --output text)"
export KARPENTER_IAM_ROLE_ARN="arn:aws:iam::${AWS_ACCOUNT_ID}:role/${CLUSTER_NAME}-karpenter"

 

Karpenter 는 Helm 설치가 가능합니다.

 

karpenter 0.28.0-rc.1 · Devops/oci-karpenter

A Helm chart for Karpenter, an open-source node provisioning project built for Kubernetes.

artifacthub.io

 

helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter --version ${KARPENTER_VERSION} --namespace karpenter --create-namespace \
  --set serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=${KARPENTER_IAM_ROLE_ARN} \
  --set settings.aws.clusterName=${CLUSTER_NAME} \
  --set settings.aws.defaultInstanceProfile=KarpenterNodeInstanceProfile-${CLUSTER_NAME} \
  --set settings.aws.interruptionQueueName=${CLUSTER_NAME} \
  --set controller.resources.requests.cpu=1 \
  --set controller.resources.requests.memory=1Gi \
  --set controller.resources.limits.cpu=1 \
  --set controller.resources.limits.memory=1Gi \
  --wait

 

설치가 정상적인지 배포 리소스를 확인합니다.

 

kubectl get all -n karpenter
kubectl get cm -n karpenter karpenter-global-settings -o jsonpath={.data} | jq
kubectl get crd | grep karpenter

 

 

2. Karpenter 사용

 

2.1. Karpenter Provisioner 배포

 

Karpenter 는 AWS AutoScaling Group 을 사용하지 않습니다.
즉, AWS ASG 를 위한 Launch Template (시작템플릿)을 필요로 하지 않습니다.

 

대신에, Node Scaling 을 위해 시작템플릿을 대체할 리소스가 필요한데 그것이 바로 Provisioner 입니다.

 

Provisioners

Learn about Karpenter Provisioners

karpenter.sh

 

아래 Yaml 설정은 Spot 인스턴스 구성으로 서브넷과 보안그룹에 태그가 적용된 곳에 노드를 배포하겠다는 설정입니다.
또한 30초간 노드에 리소스가 없으면 삭제하는 구성이 적용되어 있습니다.

cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values: ["spot"]
  limits:
    resources:
      cpu: 1000
  providerRef:
    name: default
  ttlSecondsAfterEmpty: 30
---
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:
  subnetSelector:
    karpenter.sh/discovery: ${CLUSTER_NAME}
  securityGroupSelector:
    karpenter.sh/discovery: ${CLUSTER_NAME}
EOF

 

2.2. Test Deployment 배포

 

Replica 가 0인 Deployment 를 배포합니다.

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate
spec:
  replicas: 0
  selector:
    matchLabels:
      app: inflate
  template:
    metadata:
      labels:
        app: inflate
    spec:
      terminationGracePeriodSeconds: 0
      containers:
        - name: inflate
          image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
          resources:
            requests:
              cpu: 1
EOF

 

이후, Replica 개수를 5로 늘립니다.

kubectl scale deployment inflate --replicas 5

 

kubectl get node --label-columns=eks.amazonaws.com/capacityType,karpenter.sh/capacity-type,node.kubernetes.io/instance-type

 

 

2.3. Consolidation

 

노드의 리소스 사용량을 확인하고 자동으로 노드 사용량을 최적화시켜 주는 설정입니다.

 

Deprovisioning

Understand different ways Karpenter deprovisions nodes

karpenter.sh

 

우선 기존 정책이 배포되어 있다면 삭제합니다.

kubectl delete provisioners default

 

On-demand 노드를 배포하는 카펜터 프로비저너입니다.

 

cat <<EOF | kubectl apply -f -
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  consolidation:
    enabled: true
  labels:
    type: karpenter
  limits:
    resources:
      cpu: 1000
      memory: 1000Gi
  providerRef:
    name: default
  requirements:
    - key: karpenter.sh/capacity-type
      operator: In
      values:
        - on-demand
    - key: node.kubernetes.io/instance-type
      operator: In
      values:
        - c5.large
        - m5.large
        - m5.xlarge
EOF

 

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate
spec:
  replicas: 0
  selector:
    matchLabels:
      app: inflate
  template:
    metadata:
      labels:
        app: inflate
    spec:
      terminationGracePeriodSeconds: 0
      containers:
        - name: inflate
          image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
          resources:
            requests:
              cpu: 1
EOF

 

Node Scaling 을 확인해봅니다.

kubectl scale deployment inflate --replicas 12

 

 

Node 병합을 확인해봅니다.

kubectl scale deployment inflate --replicas 5

 

 

 


Karpenter 를 사용하면 기존에 보수적으로 운영하던 EKS 노드를 굉장히 타이트하게 사용가능합니다.

다만, 너무 타이트하게 사용하다 보니 필요할 경우 오버 프로비저닝을 해야할 때도 있습니다.

 

또한 특정 시간에 트래픽이 몰릴 것으로 예상될 때, 이전 포스팅의 이벤트기반의 KEDA 와 Karpenter 를 같이 사용하는 경우도 존재합니다.

 

 

 

참고 문서

https://karpenter.sh/

 

https://karpenter.sh/v0.27.5/

 

https://aws.amazon.com/ko/blogs/aws/introducing-karpenter-an-open-source-high-performance-kubernetes-cluster-autoscaler/

 

https://www.eksworkshop.com/docs/autoscaling/compute/karpenter/consolidation/

 

https://aws.amazon.com/ko/blogs/containers/optimizing-your-kubernetes-compute-costs-with-karpenter-consolidation/

 

https://ec2spotworkshops.com/karpenter.html

Contents

포스팅 주소를 복사했습니다