K8s Karpenter 노드 오토스케일링

Karpenter란?

Karpenter는 AWS에서 시작해 현재 CNCF Sandbox 프로젝트로 성장한 Kubernetes 노드 오토스케일러입니다. 기존 Cluster Autoscaler(HPA·VPA)가 Node Group 단위로 스케일링하는 반면, Karpenter는 Pod 요구사항을 직접 분석해 최적의 인스턴스 타입과 수량을 실시간으로 결정합니다.

Cluster Autoscaler vs Karpenter

항목 Cluster Autoscaler Karpenter
스케일링 단위 Node Group (ASG) 개별 Pod 요구사항
인스턴스 선택 미리 정의된 타입 실시간 최적 매칭
스케일 다운 10분+ 지연 즉시 (Consolidation)
Spot 관리 수동 MixedInstancePolicy 네이티브 Spot 전략
설정 복잡도 ASG + Launch Template NodePool + EC2NodeClass

핵심 아키텍처

Karpenter v1(GA)에서는 두 가지 핵심 CRD로 동작합니다:

1. NodePool — 스케줄링 정책

NodePool은 어떤 워크로드에 어떤 노드를 할당할지 정의합니다.

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    spec:
      requirements:
        - key: kubernetes.io/arch
          operator: In
          values: ["amd64", "arm64"]
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot", "on-demand"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m", "r"]
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ["5"]
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
  limits:
    cpu: "1000"
    memory: 2000Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s
  weight: 50

핵심 포인트:

  • requirements: 인스턴스 패밀리, 아키텍처, Spot/On-Demand를 유연하게 지정
  • limits: NodePool이 프로비저닝할 수 있는 총 리소스 상한
  • disruption: 노드 정리(Consolidation) 정책 — 비용 최적화의 핵심
  • weight: 여러 NodePool 간 우선순위 (높을수록 먼저 선택)

2. EC2NodeClass — 인프라 설정

apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  role: "KarpenterNodeRole-my-cluster"
  amiSelectorTerms:
    - alias: al2023@latest
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: "my-cluster"
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: "my-cluster"
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 100Gi
        volumeType: gp3
        iops: 5000
        throughput: 250
  metadataOptions:
    httpEndpoint: enabled
    httpTokens: required

amiSelectorTermsalias는 v1에서 추가된 기능으로, AL2023/Bottlerocket AMI를 자동 선택합니다.

Consolidation 심화 — 비용 절감의 핵심

Karpenter의 가장 강력한 기능은 노드 통합(Consolidation)입니다. 세 가지 전략이 동작합니다:

Empty 노드 제거

Pod가 없는 노드를 consolidateAfter 시간 후 즉시 제거합니다.

Replace — 더 작은 노드로 교체

m5.4xlarge에 Pod가 2개만 실행 중이면, m5.xlarge로 교체해 비용을 75% 절감합니다. Karpenter가 자동으로 cordon → drain → terminate → launch를 수행합니다.

Multi-Node Consolidation

여러 노드에 분산된 Pod를 더 적은 노드로 합칩니다. 예: 3 × m5.large → 1 × m5.2xlarge.

# Consolidation 동작 확인
kubectl get nodeclaims -o wide
kubectl logs -n kube-system deploy/karpenter -c controller 
  | grep -E "consolidat|disrupt"

Spot 인터럽션 대응

Karpenter는 AWS SQS를 통해 Spot 인터럽션 경고를 수신하고, 자동으로 대체 노드를 프로비저닝합니다.

# Terraform으로 SQS 이벤트 브릿지 설정
resource "aws_sqs_queue" "karpenter" {
  name                      = "karpenter-${var.cluster_name}"
  message_retention_seconds = 300
  sqs_managed_sse_enabled   = true
}

resource "aws_cloudwatch_event_rule" "spot_interruption" {
  name = "karpenter-spot-interruption"
  event_pattern = jsonencode({
    source      = ["aws.ec2"]
    detail-type = ["EC2 Spot Instance Interruption Warning"]
  })
}

resource "aws_cloudwatch_event_target" "spot_interruption" {
  rule = aws_cloudwatch_event_rule.spot_interruption.name
  arn  = aws_sqs_queue.karpenter.arn
}

Spot 인터럽션 2분 전 경고 → Karpenter가 대체 노드 프로비저닝 → Pod graceful drain → 서비스 무중단.

워크로드별 NodePool 분리 패턴

실무에서는 워크로드 특성별로 NodePool을 분리합니다:

# GPU 워크로드 전용
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: gpu-workloads
spec:
  template:
    spec:
      requirements:
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["g", "p"]
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["on-demand"]
      taints:
        - key: nvidia.com/gpu
          value: "true"
          effect: NoSchedule
  limits:
    cpu: "200"
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 5m
---
# 배치/크론잡 전용 (Spot 공격적 활용)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: batch-jobs
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ["spot"]
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ["c", "m"]
      taints:
        - key: workload-type
          value: "batch"
          effect: NoSchedule
  limits:
    cpu: "500"
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 10s

Drift Detection — 자동 노드 갱신

Karpenter v1에서는 Drift Detection이 기본 활성화됩니다. EC2NodeClass의 AMI, 서브넷, 보안그룹이 변경되면 기존 노드를 자동으로 교체합니다.

# Drift 상태 확인
kubectl get nodeclaims -o jsonpath='{range .items[*]}{.metadata.name}{"t"}{.status.conditions[?(@.type=="Drifted")].status}{"n"}{end}'

# AMI 업데이트 후 자동 롤링 교체
# EC2NodeClass에서 alias: al2023@v20260301 → al2023@v20260308
# Karpenter가 자동으로 노드를 순차 교체

이를 통해 노드 패치 자동화가 가능합니다. AMI를 업데이트하면 Karpenter가 PDB를 존중하면서 롤링 교체를 수행합니다.

Helm 설치 및 IRSA 설정

# Karpenter v1 GA 설치
helm upgrade --install karpenter oci://public.ecr.aws/karpenter/karpenter 
  --version "1.1.0" 
  --namespace kube-system 
  --set "settings.clusterName=my-cluster" 
  --set "settings.interruptionQueue=karpenter-my-cluster" 
  --set controller.resources.requests.cpu=1 
  --set controller.resources.requests.memory=1Gi 
  --set controller.resources.limits.cpu=1 
  --set controller.resources.limits.memory=1Gi 
  --set replicas=2 
  --wait

프로덕션에서는 replicas=2로 고가용성을 확보하고, PriorityClasssystem-cluster-critical로 설정해 Karpenter 자체가 축출되지 않도록 합니다.

모니터링 — Prometheus 메트릭

Karpenter는 풍부한 Prometheus 메트릭을 노출합니다:

# 핵심 메트릭
karpenter_nodes_total                    # 관리 중인 노드 수
karpenter_nodeclaims_disrupted_total     # Consolidation/Drift로 교체된 노드
karpenter_pods_startup_duration_seconds  # Pod → 노드 프로비저닝 → Running 시간
karpenter_provisioner_scheduling_duration_seconds  # 스케줄링 결정 소요 시간
karpenter_cloudprovider_instance_type_price_estimate  # 인스턴스별 예상 비용

# Grafana 대시보드
# https://github.com/aws/karpenter/tree/main/website/content/en/docs/reference/metrics

운영 팁 — 실무에서 자주 만나는 이슈

  • Pod Topology Spread: topologySpreadConstraints와 Karpenter를 함께 쓰면 AZ별 균등 분배 + 비용 최적화 동시 달성
  • Do-Not-Disrupt 어노테이션: 장시간 실행 Pod에 karpenter.sh/do-not-disrupt: "true"를 설정해 Consolidation 제외
  • Budgets: spec.disruption.budgets로 동시 교체 노드 수를 제한 (예: nodes: "20%")
  • Instance 다양성: instance-category를 넓게 설정해야 Spot 가용성이 높아짐

정리

Karpenter는 Kubernetes 노드 관리를 선언적이고 자동화된 방식으로 전환합니다. Node Group을 미리 정의하는 대신, Pod가 원하는 것을 Karpenter가 실시간으로 해석하고 최적의 인프라를 프로비저닝합니다. Consolidation, Drift Detection, Spot 인터럽션 대응까지 — 노드 운영의 대부분을 자동화할 수 있습니다.

위로 스크롤
WordPress Appliance - Powered by TurnKey Linux