1. Karpenter란?

Karpenter는 쿠버네티스(Kubernetes) 클러스터의 노드 자동 확장을 위한 오픈소스 프로젝트로, AWS에서 개발하여 2021년에 공개되었습니다. Karpenter의 주요 목적은 워크로드 수요에 맞게 적절한 컴퓨팅 리소스를 신속하게 프로비저닝하고 제거하는 것입니다.

Karpenter라는 이름은 “Kubernetes”와 “Carpenter(목수)”의 합성어로, 클러스터 내 자원을 효율적으로 ‘구축’한다는 의미를 담고 있습니다.

2. Karpenter의 필요성

기존 자동 확장의 문제점

기존 쿠버네티스 환경에서는 Cluster Autoscaler(CA)가 노드 자동 확장을 담당해왔습니다. 그러나 CA는 다음과 같은 여러 제약이 있었습니다:

  • 노드 그룹 기반 작동: 미리 정의된 노드 그룹에 의존하기 때문에 유연성이 제한됨
  • 확장 속도 제한: 노드 추가 시간이 길어 급격한 트래픽 증가에 대응하기 어려움
  • 리소스 낭비: 사전 정의된 인스턴스 유형만 사용할 수 있어 최적의 리소스 활용이 어려움
  • 복잡한 설정: 다양한 워크로드에 맞춰 여러 노드 그룹을 구성해야 함

Karpenter의 해결책

Karpenter는 이런 문제들을 해결하기 위해 설계되었습니다:

  • 빠른 확장: 수십 초 내에 새 노드 프로비저닝
  • 워크로드 중심 접근: 노드 그룹이 아닌 워크로드 요구사항에 따라 최적의 인스턴스 선택
  • 자동 최적화: 리소스 활용도를 지속적으로 모니터링하고 최적화
  • 단순화된 관리: 복잡한 노드 그룹 구성 없이도 효율적인 확장 가능

3. 기존 솔루션과의 차이점

기능 Cluster Autoscaler Karpenter
확장 방식 노드 그룹 기반 워크로드 요구사항 기반
확장 속도 수 분 수십 초
인스턴스 유형 선택 노드 그룹별 고정 워크로드에 최적화하여 동적 선택
리소스 활용도 제한적 최적화 지속적인 최적화
관리 복잡성 높음 (여러 노드 그룹 관리) 낮음 (간단한 프로바이더 설정)
클라우드 통합 간접적 직접적 (클라우드 API 직접 호출)

4. Karpenter 작동 방식

Karpenter는 다음과 같은 핵심 구성요소로 작동합니다:

1. 프로비저너(Provisioner)

프로비저너는 Karpenter의 핵심 리소스로, 노드 프로비저닝에 대한 전반적인 정책을 정의합니다.

apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: "karpenter.k8s.aws/instance-category"
      operator: In
      values: ["c", "m", "r"]
  limits:
    resources:
      cpu: 1000
  providerRef:
    name: default
  ttlSecondsAfterEmpty: 30

2. 노드 템플릿(Node Template)

AWS 환경에서는 AWSNodeTemplate을 사용하여 노드의 세부 설정을 구성합니다.

apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:
  subnetSelector:
    karpenter.sh/discovery: my-cluster
  securityGroupSelector:
    karpenter.sh/discovery: my-cluster
  tags:
    environment: production

3. 워크플로우

  1. 모니터링: Karpenter는 스케줄링되지 않은 Pod를 지속적으로 모니터링
  2. 결정: Pod 요구사항에 맞는 최적의 노드 유형 결정
  3. 프로비저닝: 클라우드 제공자 API를 호출하여 노드 생성
  4. 통합: 노드를 쿠버네티스 클러스터에 등록
  5. 관리: 리소스 활용도를 지속적으로 모니터링하고 필요에 따라 노드 제거

5. 사용 예시

기본 설치 (AWS EKS)

AWS EKS 환경에서 Karpenter를 설치하고 구성하는 기본 예시입니다.

  1. 필요한 IAM 역할 및 정책 설정:
eksctl create iamserviceaccount \
  --cluster=my-cluster \
  --namespace=karpenter \
  --name=karpenter \
  --attach-policy-arn=arn:aws:iam::aws:policy/AmazonEKSClusterPolicy \
  --approve
  1. Helm을 통한 Karpenter 설치:
helm repo add karpenter https://charts.karpenter.sh
helm repo update
helm install karpenter karpenter/karpenter \
  --namespace karpenter \
  --create-namespace \
  --set serviceAccount.annotations."eks\\.amazonaws\\.com/role-arn"=${KARPENTER_IAM_ROLE_ARN} \
  --set clusterName=${CLUSTER_NAME} \
  --set clusterEndpoint=${CLUSTER_ENDPOINT}
  1. 프로비저너 및 노드 템플릿 생성:
# provisioner.yaml
apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: default
spec:
  requirements:
    - key: "karpenter.k8s.aws/instance-category"
      operator: In
      values: ["c", "m", "r"]
    - key: "karpenter.k8s.aws/instance-generation"
      operator: Gt
      values: ["4"]
  limits:
    resources:
      cpu: 100
      memory: 400Gi
  providerRef:
    name: default
  ttlSecondsUntilExpired: 604800  # 7일

---
# node-template.yaml
apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: default
spec:
  subnetSelector:
    karpenter.sh/discovery: my-cluster
  securityGroupSelector:
    karpenter.sh/discovery: my-cluster
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 100Gi
        volumeType: gp3
        deleteOnTermination: true
  tags:
    environment: production

실제 워크로드 예시

다양한 워크로드 요구사항에 맞는 Karpenter 구성 예시입니다.

1. 머신러닝 워크로드를 위한 GPU 노드 자동 프로비저닝

apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: gpu-provisioner
spec:
  requirements:
    - key: "node.kubernetes.io/instance-type"
      operator: In
      values: ["p3.2xlarge", "p3.8xlarge", "p3.16xlarge"]
    - key: "accelerator"
      operator: Exists
  labels:
    workload-type: gpu
  taints:
    - key: nvidia.com/gpu
      value: "true"
      effect: NoSchedule
  providerRef:
    name: gpu-template

2. 비용 최적화를 위한 스팟 인스턴스 활용

apiVersion: karpenter.k8s.aws/v1alpha1
kind: AWSNodeTemplate
metadata:
  name: spot-template
spec:
  subnetSelector:
    karpenter.sh/discovery: my-cluster
  securityGroupSelector:
    karpenter.sh/discovery: my-cluster
  instanceProfile: KarpenterNodeInstanceProfile
  capacityType: spot

3. 시간 기반 노드 관리 예시

특정 시간에만 노드를 유지하도록 구성:

apiVersion: karpenter.sh/v1alpha5
kind: Provisioner
metadata:
  name: batch-jobs
spec:
  requirements:
    - key: "karpenter.k8s.aws/instance-category"
      operator: In
      values: ["c", "m"]
  ttlSecondsAfterEmpty: 60  # 1분 후 노드 제거
  ttlSecondsUntilExpired: 14400  # 4시간 후 강제 교체

6. 결론

Karpenter는 쿠버네티스 클러스터의 자동 확장에 혁신적인 접근 방식을 제공합니다. 기존의 Cluster Autoscaler와 달리, Karpenter는 워크로드 요구사항을 기반으로 최적의 노드를 신속하게 프로비저닝하고 관리함으로써 다음과 같은 이점을 제공합니다:

  • 비용 최적화: 필요한 리소스만 정확히 프로비저닝
  • 빠른 확장: 수십 초 내에 워크로드 요구사항 충족
  • 운영 간소화: 복잡한 노드 그룹 구성 없이 자동화된 관리
  • 리소스 효율성: 워크로드에 맞춰 최적의 인스턴스 유형 자동 선택

특히 변동성이 큰 워크로드, 다양한 인스턴스 요구사항, 대규모 클러스터를 운영하는 환경에서 Karpenter의 가치가 극대화됩니다. 쿠버네티스 생태계의 발전과 함께 Karpenter는 클라우드 리소스 관리의 새로운 표준으로 자리잡아가고 있습니다.


참고 자료


7. Consolidation (통합) 기능

Consolidation은 Karpenter의 핵심 비용 최적화 기능으로, 유휴 노드를 자동으로 제거하거나 여러 노드의 파드를 더 적은 수의 노드에 통합합니다.

Consolidation 동작 방식

모드 설명
WhenEmpty 파드가 없는 빈 노드만 제거
WhenUnderutilized 파드를 다른 노드로 이동시켜 노드 수 감소
# NodePool에서 Consolidation 설정
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  disruption:
    consolidationPolicy: WhenUnderutilized   # 비용 최적화
    consolidateAfter: 30s                    # 30초 후 통합 시도
    budgets:
    - nodes: "20%"                           # 한 번에 최대 20% 노드만 교체
  template:
    spec:
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
      requirements:
      - key: karpenter.sh/capacity-type
        operator: In
        values: ["spot", "on-demand"]
      - key: karpenter.k8s.aws/instance-category
        operator: In
        values: ["c", "m", "r"]

Disruption Budget (중단 예산)

# 중요 워크로드 보호: PodDisruptionBudget과 함께 사용
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: web-pdb
spec:
  minAvailable: 2          # 최소 2개 파드 유지
  selector:
    matchLabels:
      app: web-server

주의: do-not-disrupt 어노테이션을 파드에 추가하면 Karpenter가 해당 파드의 노드를 교체하지 않습니다.

annotations:
  karpenter.sh/do-not-disrupt: "true"

8. 비용 모니터링

Karpenter + AWS Cost Explorer 연동

# 노드 비용 태그 자동 적용 (EC2NodeClass)
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  tags:
    Environment: production
    Team: platform
    CostCenter: engineering
    ManagedBy: karpenter

Prometheus + Grafana로 Karpenter 메트릭 모니터링

# Karpenter는 기본적으로 Prometheus 메트릭 제공 (포트 8080)
# 주요 메트릭
메트릭 설명
karpenter_nodes_total 프로비저닝된 노드 수
karpenter_pods_state 파드 스케줄링 상태
karpenter_provisioner_scheduling_duration_seconds 스케줄링 소요 시간
karpenter_interruption_received_messages_total Spot 인터럽션 수신 횟수
karpenter_nodes_termination_duration_seconds 노드 종료 소요 시간
# Prometheus ServiceMonitor 설정
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
  name: karpenter
  namespace: karpenter
spec:
  selector:
    matchLabels:
      app.kubernetes.io/name: karpenter
  endpoints:
  - port: http-metrics
    interval: 30s
    path: /metrics

Spot 인터럽션 처리

Karpenter는 EC2 Spot 인터럽션 알림을 자동으로 처리합니다.

# Spot 인터럽션 발생 시 Karpenter 동작:
# 1. AWS SQS로 인터럽션 알림 수신
# 2. 영향받는 노드의 파드를 다른 노드로 이동 (Cordon + Drain)
# 3. 새 노드 프로비저닝 (On-Demand 또는 다른 Spot 타입)

# SQS 큐 생성 (Spot 인터럽션 알림용)
aws cloudformation deploy \
  --template-file interruption-queue.yaml \
  --stack-name karpenter-interruption-queue

추가 참고 자료

댓글남기기