Skip to content
Published on

[AWS] Karpenter 완전 가이드: 쿠버네티스 노드 자동 프로비저닝

Authors

목차

1. Karpenter란 무엇인가

Karpenter는 AWS가 개발한 오픈소스 쿠버네티스 노드 프로비저너입니다. 기존 Cluster Autoscaler가 Auto Scaling Group(ASG)을 통해 간접적으로 노드를 관리하는 것과 달리, Karpenter는 EC2 API를 직접 호출하여 워크로드에 최적화된 노드를 수십 초 만에 프로비저닝합니다.

핵심 특징

  • 직접 EC2 프로비저닝: ASG 없이 EC2 Fleet API를 직접 호출
  • 빠른 스케일링: 약 4560초 내에 노드 온라인 (CA 대비 34분)
  • 지능형 인스턴스 선택: 워크로드 요구사항에 맞는 최적 인스턴스 타입 자동 선택
  • 빈 패킹 최적화: 고급 빈 패킹 알고리즘으로 클러스터 활용률 극대화
  • 자동 통합(Consolidation): 미사용 노드 자동 제거 및 저비용 노드로 교체
  • 드리프트 감지: 설정 변경 시 자동으로 노드를 최신 상태로 교체

2. 왜 Karpenter인가: Cluster Autoscaler의 한계

Cluster Autoscaler의 문제점

+------------------------------------------+
|           Cluster Autoscaler              |
|                                           |
|  Pod Pending                              |
|      |                                    |
|      v                                    |
|  CA가 ASG에 스케일 아웃 요청              |
|      |                                    |
|      v                                    |
|  ASG가 미리 정의된 Launch Template로      |
|  EC2 인스턴스 시작                        |
|      |                                    |
|      v                                    |
|  노드 등록까지 3~5분 소요                 |
+------------------------------------------+

Cluster Autoscaler는 다음과 같은 한계를 가집니다:

  1. ASG 의존성: 사전에 정의된 Node Group에 묶여 유연성이 떨어짐
  2. 느린 스케일링: ASG를 거치기 때문에 3~5분의 프로비저닝 시간 소요
  3. 인스턴스 타입 제한: Node Group별로 고정된 인스턴스 타입만 사용 가능
  4. 비효율적 빈 패킹: 노드 그룹 단위로만 스케일링하여 리소스 낭비 발생
  5. 수동 관리 부담: 다양한 워크로드를 위해 여러 Node Group을 수동으로 관리

Karpenter의 접근 방식

+------------------------------------------+
|              Karpenter                    |
|                                           |
|  Pod Pending                              |
|      |                                    |
|      v                                    |
|  Karpenter가 Pod 요구사항 분석            |
|  (CPU, Memory, GPU, Topology 등)          |
|      |                                    |
|      v                                    |
|  최적 인스턴스 타입 자동 선택             |
|  (200+ 인스턴스 타입에서 비용 최적화)     |
|      |                                    |
|      v                                    |
|  EC2 Fleet API 직접 호출                  |
|      |                                    |
|      v                                    |
|  45~60초 내 노드 Ready                    |
+------------------------------------------+

3. Karpenter 아키텍처

전체 구조

+----------------------------------------------------------------+
|                     EKS Cluster                                |
|                                                                |
|  +------------------+     +-----------------------------+      |
|  | Karpenter        |     | Kubernetes API Server       |      |
|  | Controller       |---->| (Pod Watch, Node Mgmt)      |      |
|  | (Deployment)     |     +-----------------------------+      |
|  +--------+---------+                                          |
|           |                                                    |
|           |  NodePool + EC2NodeClass 참조                      |
|           |                                                    |
|  +--------v---------+     +-----------------------------+      |
|  | 인스턴스 타입     |     | AWS Services                |      |
|  | 선택 엔진        |---->| - EC2 Fleet API             |      |
|  | (비용/용량 최적화)|     | - SSM (AMI Discovery)       |      |
|  +------------------+     | - Pricing API               |      |
|                           | - SQS (Interruption)        |      |
|                           | - EventBridge               |      |
|                           +-----------------------------+      |
+----------------------------------------------------------------+

핵심 컴포넌트

Karpenter는 세 가지 주요 CRD(Custom Resource Definition)를 사용합니다:

CRDAPI 버전설명
NodePoolkarpenter.sh/v1노드 프로비저닝 제약 조건 정의
EC2NodeClasskarpenter.k8s.aws/v1AWS 고유 인스턴스 설정
NodeClaimkarpenter.sh/v1런타임에 생성되는 노드 요청 객체

프로비저닝 흐름

1. Pod가 Pending 상태로 감지됨
       |
2. Karpenter가 Pod의 리소스 요청, nodeSelector,
   affinity, tolerations 등을 분석
       |
3. 매칭되는 NodePool 결정 (weight 기반 우선순위)
       |
4. EC2NodeClass에서 AWS 설정 참조
   (서브넷, 보안 그룹, AMI 등)
       |
5. 최적 인스턴스 타입 선택
   (비용, 용량, 요구사항 기반)
       |
6. EC2 Fleet API로 인스턴스 시작
       |
7. NodeClaim 객체 생성 및 추적
       |
8. 노드 등록 완료 -> Pod 스케줄링

4. NodePool 상세 설정

NodePool은 Karpenter v1에서 기존 Provisioner를 대체하는 핵심 CRD입니다.

기본 NodePool 예제

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: default
spec:
  template:
    metadata:
      labels:
        team: platform
        environment: production
    spec:
      requirements:
        # 인스턴스 카테고리 제한
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ['c', 'm', 'r']

        # 인스턴스 세대 제한
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ['5']

        # 용량 타입 (on-demand 또는 spot)
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['on-demand', 'spot']

        # 가용 영역
        - key: topology.kubernetes.io/zone
          operator: In
          values: ['ap-northeast-2a', 'ap-northeast-2b', 'ap-northeast-2c']

        # 아키텍처
        - key: kubernetes.io/arch
          operator: In
          values: ['amd64', 'arm64']

      # EC2NodeClass 참조
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default

      # 노드 만료 시간 (72시간 후 자동 교체)
      expireAfter: 72h

  # 리소스 한도
  limits:
    cpu: '1000'
    memory: 1000Gi

  # 중단(Disruption) 정책
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 1m
    budgets:
      - nodes: '10%'
      - nodes: '0'
        schedule: '0 9 * * MON-FRI'
        duration: 1h

  # NodePool 가중치 (높을수록 우선)
  weight: 50

requirements 주요 키

+---------------------------------------------+--------------------------------+
| Key                                         | 설명                           |
+---------------------------------------------+--------------------------------+
| karpenter.sh/capacity-type                  | on-demand 또는 spot            |
| karpenter.k8s.aws/instance-category         | 인스턴스 패밀리 (c, m, r 등)   |
| karpenter.k8s.aws/instance-generation       | 인스턴스 세대 (5, 6, 7 등)     |
| karpenter.k8s.aws/instance-size             | 인스턴스 크기 (large, xlarge)  |
| karpenter.k8s.aws/instance-gpu-count        | GPU 수량                       |
| karpenter.k8s.aws/instance-gpu-name         | GPU 이름 (a10g, t4 등)         |
| topology.kubernetes.io/zone                 | 가용 영역                       |
| kubernetes.io/arch                          | CPU 아키텍처                    |
| kubernetes.io/os                            | 운영체제                        |
+---------------------------------------------+--------------------------------+

다중 NodePool 전략

# 프로덕션 워크로드용 (On-Demand 전용, 높은 우선순위)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: production
spec:
  template:
    metadata:
      labels:
        workload-type: production
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['on-demand']
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ['m', 'r']
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ['5']
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: production
      expireAfter: 168h
  limits:
    cpu: '500'
    memory: 500Gi
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 5m
  weight: 100
---
# 개발/테스트용 (Spot 허용, 낮은 우선순위)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: development
spec:
  template:
    metadata:
      labels:
        workload-type: development
      annotations:
        dev-team: 'true'
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['spot', 'on-demand']
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ['c', 'm']
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: development
      expireAfter: 24h
  limits:
    cpu: '200'
    memory: 200Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 30s
  weight: 10

5. EC2NodeClass 상세 설정

EC2NodeClass는 AWS 고유의 인스턴스 설정을 정의하는 CRD입니다.

완전한 EC2NodeClass 예제

apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: default
spec:
  # AMI 설정
  amiSelectorTerms:
    - alias: al2023@latest

  # IAM 역할
  role: KarpenterNodeRole-my-cluster

  # 서브넷 선택
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
        network-type: private

  # 보안 그룹 선택
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster

  # 블록 디바이스 매핑
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 100Gi
        volumeType: gp3
        iops: 3000
        throughput: 125
        encrypted: true
        deleteOnTermination: true

  # 메타데이터 옵션
  metadataOptions:
    httpEndpoint: enabled
    httpProtocolIPv6: disabled
    httpPutResponseHopLimit: 2
    httpTokens: required

  # 태그
  tags:
    Environment: production
    ManagedBy: karpenter
    Team: platform

  # 사용자 데이터 (부트스트랩 스크립트)
  userData: |
    #!/bin/bash
    echo "Karpenter managed node"
    # 추가 부트스트랩 로직

AMI 선택 옵션

# 옵션 1: 별칭(alias) 사용 (권장)
amiSelectorTerms:
  - alias: al2023@latest       # Amazon Linux 2023 최신
  # - alias: al2@latest        # Amazon Linux 2
  # - alias: bottlerocket@latest # Bottlerocket

# 옵션 2: 태그 기반 선택
amiSelectorTerms:
  - tags:
      environment: production
      ami-type: custom-al2023

# 옵션 3: AMI ID 직접 지정
amiSelectorTerms:
  - id: ami-0123456789abcdef0

지원하는 AMI 패밀리

+-----------------+------------------------------------------+
| AMI Family      | 설명                                     |
+-----------------+------------------------------------------+
| AL2023          | Amazon Linux 2023 (권장)                 |
| AL2             | Amazon Linux 2                           |
| Bottlerocket    | AWS Bottlerocket (컨테이너 전용 OS)      |
| Windows2019     | Windows Server 2019                      |
| Windows2022     | Windows Server 2022                      |
| Windows2025     | Windows Server 2025                      |
+-----------------+------------------------------------------+

6. 통합(Consolidation): 비용 최적화의 핵심

Karpenter의 Consolidation은 클러스터 비용을 자동으로 최적화하는 핵심 기능입니다.

Consolidation 동작 방식

Consolidation 유형:
+------------------------------------------------------------------+
|                                                                  |
|  1. 삭제(Delete) Consolidation                                   |
|     - 노드의 모든 Pod가 다른 노드에서 실행 가능한 경우           |
|     - 해당 노드를 안전하게 제거                                  |
|                                                                  |
|  2. 교체(Replace) Consolidation                                  |
|     - 현재 노드를 더 작고 저렴한 인스턴스로 교체 가능한 경우     |
|     - 새 노드 프로비저닝 -> Pod 마이그레이션 -> 구 노드 제거     |
|                                                                  |
+------------------------------------------------------------------+

Consolidation 정책 설정

# 정책 1: 빈 노드만 통합
disruption:
  consolidationPolicy: WhenEmpty
  consolidateAfter: 30s

# 정책 2: 빈 노드 + 미활용 노드 통합 (권장)
disruption:
  consolidationPolicy: WhenEmptyOrUnderutilized
  consolidateAfter: 1m

Disruption Budget으로 속도 제어

disruption:
  consolidationPolicy: WhenEmptyOrUnderutilized
  consolidateAfter: 1m
  budgets:
    # 전체 노드의 10%까지만 동시에 중단 허용
    - nodes: '10%'

    # 업무 시간에는 중단 차단
    - nodes: '0'
      schedule: '0 9 * * MON-FRI'
      duration: 8h

    # 특정 사유에 대해서만 예산 적용 (v1.0+)
    - nodes: '5%'
      reasons:
        - 'Underutilized'

Spot-to-Spot Consolidation

Spot 인스턴스 간 통합은 최소 15개 이상의 인스턴스 타입이 설정되어야 활성화됩니다.

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-optimized
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['spot']
        # 다양한 인스턴스 타입으로 Spot-to-Spot 통합 활성화
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ['c', 'm', 'r']
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ['4']
        - key: karpenter.k8s.aws/instance-size
          operator: In
          values: ['large', 'xlarge', '2xlarge', '4xlarge']

7. 드리프트 감지(Drift Detection)

드리프트 감지는 NodePool이나 EC2NodeClass의 설정이 변경되었을 때, 기존 노드가 최신 설정과 일치하지 않는 것을 탐지하고 자동으로 교체하는 기능입니다.

드리프트가 감지되는 경우

+---------------------------------------------------+
| 드리프트 감지 시나리오                             |
+---------------------------------------------------+
| - AMI가 업데이트된 경우                            |
| - NodePool의 requirements가 변경된 경우            |
| - EC2NodeClass의 보안 그룹이 변경된 경우           |
| - EC2NodeClass의 서브넷이 변경된 경우              |
| - 블록 디바이스 설정이 변경된 경우                 |
| - 메타데이터 옵션이 변경된 경우                    |
| - 태그가 변경된 경우                               |
+---------------------------------------------------+

드리프트 교체 프로세스

1. Karpenter가 NodeClaim과 현재 NodePool/EC2NodeClass 비교
       |
2. 차이 발견 시 NodeClaim에 Drifted 상태 표시
       |
3. Disruption Budget 확인
       |
4. 새 노드 프로비저닝 (최신 설정 적용)
       |
5. 기존 노드의 Pod를 안전하게 drain
       |
6. 기존 노드 종료

8. 인터럽션 처리(Interruption Handling)

Karpenter는 다양한 EC2 인터럽션 이벤트를 자동으로 처리합니다.

지원하는 인터럽션 유형

+-----------------------------+----------------------------------------+
| 인터럽션 유형               | 설명                                   |
+-----------------------------+----------------------------------------+
| Spot Interruption           | 2분 전 경고로 Spot 회수 알림           |
| Rebalance Recommendation    | 중단 위험 증가 시 사전 알림            |
| Scheduled Maintenance       | AWS 예정된 유지보수 이벤트             |
| Instance State Change       | 인스턴스 상태 변경 (stopping, stopped) |
+-----------------------------+----------------------------------------+

SQS 기반 인터럽션 처리 아키텍처

+-------------------+     +-------------------+     +------------------+
| EC2 Spot          |     | Amazon            |     | Amazon           |
| Interruption      |---->| EventBridge       |---->| SQS Queue        |
| Notice            |     | Rules             |     |                  |
+-------------------+     +-------------------+     +--------+---------+
                                                             |
+-------------------+     +-------------------+              |
| EC2 Rebalance     |---->| EventBridge       |----+         |
| Recommendation    |     |                   |    |         |
+-------------------+     +-------------------+    |         |
                                                   v         v
                                              +----+---------+----+
                                              | Karpenter         |
                                              | Controller        |
                                              |                   |
                                              | 1. 이벤트 수신    |
                                              | 2. 노드 Cordon    |
                                              | 3. Pod Drain      |
                                              | 4. 새 노드 시작   |
                                              | 5. 기존 노드 종료 |
                                              +-------------------+

인터럽션 처리 설정

Helm 설치 시 SQS 큐 이름을 지정합니다:

helm install karpenter oci://public.ecr.aws/karpenter/karpenter \
  --version "1.0.0" \
  --namespace karpenter \
  --create-namespace \
  --set "settings.clusterName=my-cluster" \
  --set "settings.interruptionQueue=my-cluster-karpenter" \
  --set controller.resources.requests.cpu=1 \
  --set controller.resources.requests.memory=1Gi \
  --set controller.resources.limits.cpu=1 \
  --set controller.resources.limits.memory=1Gi

9. Spot 인스턴스 베스트 프랙티스

다양한 인스턴스 타입 설정

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-diverse
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['spot']
        # 다양한 인스턴스 패밀리로 Spot 가용성 확보
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ['c', 'm', 'r', 'c', 'm']
        # 여러 세대 허용
        - key: karpenter.k8s.aws/instance-generation
          operator: In
          values: ['5', '6', '7']
        # 다양한 크기 허용
        - key: karpenter.k8s.aws/instance-size
          operator: In
          values: ['large', 'xlarge', '2xlarge', '4xlarge']
        # 여러 가용 영역
        - key: topology.kubernetes.io/zone
          operator: In
          values: ['ap-northeast-2a', 'ap-northeast-2b', 'ap-northeast-2c']
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default

Spot + On-Demand 혼합 전략

# Spot 우선 NodePool (높은 가중치)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: spot-first
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['spot']
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
  weight: 100
  limits:
    cpu: '500'
---
# On-Demand 대체 NodePool (낮은 가중치)
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: on-demand-fallback
spec:
  template:
    spec:
      requirements:
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['on-demand']
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: default
  weight: 1
  limits:
    cpu: '200'

Spot 사용 시 주의사항

  • 다양한 인스턴스 타입 허용: 최소 15개 이상의 인스턴스 타입을 허용하여 Spot 가용성을 극대화
  • 여러 가용 영역 사용: 단일 AZ에 의존하지 않고 여러 AZ에 걸쳐 Spot 용량 확보
  • PDB(Pod Disruption Budget) 설정: 중요 워크로드에 PDB를 설정하여 최소 가용성 보장
  • Graceful Shutdown 처리: terminationGracePeriodSeconds를 적절히 설정

10. Helm을 통한 Karpenter 설치

사전 준비

# 환경 변수 설정
export KARPENTER_NAMESPACE="karpenter"
export KARPENTER_VERSION="1.0.0"
export CLUSTER_NAME="my-eks-cluster"
export AWS_ACCOUNT_ID="$(aws sts get-caller-identity --query Account --output text)"
export TEMPOUT="$(mktemp)"

IAM 역할 생성

# Karpenter 컨트롤러 역할 생성
aws iam create-role \
  --role-name "KarpenterControllerRole-${CLUSTER_NAME}" \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::oidc-provider/oidc.eks.REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B71EXAMPLE"
      },
      "Action": "sts:AssumeRoleWithWebIdentity"
    }]
  }'

# Karpenter 노드 역할 생성
aws iam create-role \
  --role-name "KarpenterNodeRole-${CLUSTER_NAME}" \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }]
  }'

Helm 설치

# Helm 리포지토리 추가 (OCI)
helm install karpenter oci://public.ecr.aws/karpenter/karpenter \
  --version "${KARPENTER_VERSION}" \
  --namespace "${KARPENTER_NAMESPACE}" \
  --create-namespace \
  --set "settings.clusterName=${CLUSTER_NAME}" \
  --set "settings.interruptionQueue=${CLUSTER_NAME}-karpenter" \
  --set "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:role/KarpenterControllerRole-${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

설치 확인

# Karpenter Pod 상태 확인
kubectl get pods -n karpenter

# CRD 확인
kubectl get crd | grep karpenter

# 로그 확인
kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter -f

11. 완전한 배포 예제

전체 구성 (NodePool + EC2NodeClass)

apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
  name: production
spec:
  amiSelectorTerms:
    - alias: al2023@latest
  role: KarpenterNodeRole-my-cluster
  subnetSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
        network-type: private
  securityGroupSelectorTerms:
    - tags:
        karpenter.sh/discovery: my-cluster
  blockDeviceMappings:
    - deviceName: /dev/xvda
      ebs:
        volumeSize: 100Gi
        volumeType: gp3
        iops: 3000
        throughput: 125
        encrypted: true
        deleteOnTermination: true
  metadataOptions:
    httpEndpoint: enabled
    httpPutResponseHopLimit: 2
    httpTokens: required
  tags:
    Environment: production
    ManagedBy: karpenter
---
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
  name: production
spec:
  template:
    metadata:
      labels:
        environment: production
        managed-by: karpenter
    spec:
      requirements:
        - key: karpenter.k8s.aws/instance-category
          operator: In
          values: ['c', 'm', 'r']
        - key: karpenter.k8s.aws/instance-generation
          operator: Gt
          values: ['5']
        - key: karpenter.sh/capacity-type
          operator: In
          values: ['on-demand']
        - key: topology.kubernetes.io/zone
          operator: In
          values: ['ap-northeast-2a', 'ap-northeast-2b', 'ap-northeast-2c']
        - key: kubernetes.io/arch
          operator: In
          values: ['amd64']
      nodeClassRef:
        group: karpenter.k8s.aws
        kind: EC2NodeClass
        name: production
      expireAfter: 168h
  limits:
    cpu: '1000'
    memory: 2000Gi
  disruption:
    consolidationPolicy: WhenEmptyOrUnderutilized
    consolidateAfter: 2m
    budgets:
      - nodes: '10%'
      - nodes: '0'
        schedule: '0 2 * * *'
        duration: 1h
  weight: 100

테스트 워크로드 배포

apiVersion: apps/v1
kind: Deployment
metadata:
  name: inflate
  namespace: default
spec:
  replicas: 0
  selector:
    matchLabels:
      app: inflate
  template:
    metadata:
      labels:
        app: inflate
    spec:
      containers:
        - name: inflate
          image: public.ecr.aws/eks-distro/kubernetes/pause:3.7
          resources:
            requests:
              cpu: '1'
              memory: 1Gi
# 스케일 업하여 Karpenter 프로비저닝 트리거
kubectl scale deployment inflate --replicas=10

# 노드 프로비저닝 확인
kubectl get nodes -w

# NodeClaim 상태 확인
kubectl get nodeclaims

# 스케일 다운하여 Consolidation 확인
kubectl scale deployment inflate --replicas=0

12. Karpenter vs Cluster Autoscaler 비교표

+-----------------------------+----------------------------+----------------------------+
| 항목                        | Karpenter                  | Cluster Autoscaler         |
+-----------------------------+----------------------------+----------------------------+
| 프로비저닝 방식             | EC2 API 직접 호출          | ASG 통한 간접 호출         |
| 프로비저닝 속도             | 45~60초                    | 3~5분                      |
| 인스턴스 선택               | 자동 최적화 (200+ 타입)    | Node Group 고정 타입       |
| 빈 패킹                     | Pod 단위 최적화            | Node Group 단위            |
| Consolidation               | 내장 (자동)                | 제한적 (scale-down)        |
| 드리프트 감지               | 자동                       | 미지원                     |
| Spot 인스턴스               | 네이티브 지원, 자동 다각화 | ASG Mixed Instances        |
| Spot 인터럽션 처리          | SQS 기반 자동 처리         | 별도 도구 필요             |
| 멀티 아키텍처               | AMD64 + ARM64 자동 선택    | 별도 Node Group 필요       |
| 설정 복잡도                 | NodePool + EC2NodeClass    | ASG + Launch Template      |
| 멀티 클라우드               | AWS 전용 (커뮤니티 확장)   | 공식 멀티 클라우드         |
| 비용 절감 효과              | 25~40% (빈패킹 + Spot)    | 10~20%                     |
| 쿠버네티스 공식 프로젝트    | 아니오 (AWS 주도)          | 예 (SIG Autoscaling)       |
+-----------------------------+----------------------------+----------------------------+

13. 자주 발생하는 문제와 해결

Pod가 Pending 상태로 남는 경우

# NodePool 요구사항 확인
kubectl describe nodepool default

# Karpenter 로그에서 프로비저닝 실패 원인 확인
kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter | grep -i "error\|failed"

# Pod 이벤트 확인
kubectl describe pod [pod-name]

일반적인 원인과 해결 방법

  1. 서브넷 또는 보안 그룹 태그 미설정: EC2NodeClass의 selector 태그가 실제 AWS 리소스에 적용되어 있는지 확인
  2. IAM 권한 부족: Karpenter 컨트롤러 역할에 필요한 EC2, IAM, SSM 권한 확인
  3. 리소스 한도 초과: NodePool의 limits 설정이 현재 사용량을 초과하지 않는지 확인
  4. 인스턴스 타입 가용성: 특정 AZ에서 해당 인스턴스 타입의 용량이 부족한 경우

14. 마무리

Karpenter는 쿠버네티스 노드 프로비저닝의 패러다임을 바꾸고 있습니다. ASG 기반의 정적인 노드 관리에서 벗어나, 워크로드 중심의 동적 인프라 프로비저닝이 가능해졌습니다.

도입 권장 시나리오

  • 다양한 인스턴스 타입이 필요한 워크로드
  • Spot 인스턴스를 적극 활용하고 싶은 경우
  • 빠른 스케일링이 중요한 이벤트성 워크로드
  • 비용 최적화가 핵심 목표인 클러스터
  • GPU/ML 워크로드가 포함된 환경

주의사항

  • AWS EKS 전용이므로 멀티 클라우드 환경에서는 Cluster Autoscaler 병행 고려
  • v1.0+ 안정 버전 사용을 권장
  • SQS 큐 설정으로 Spot 인터럽션 처리 반드시 활성화
  • NodePool의 limits를 적절히 설정하여 비용 폭주 방지