EKS Auto Mode와 Karpenter

노드 자동화 운영

EKS 1.37, Karpenter v1.15 기준 (2026-10-20 확인)

오늘 세션 구성

1
개념: 왜 노드 자동화인가
2
구조: NodePool, NodeClass, Auto Mode
3
스케일링과 disruption
4
Auto Mode 심화와 운영: 설정, 용량, 진단, 비용, 마이그레이션
5
데모 영상 4편
6
마무리

1부: Pending Pod가 노드를 부른다

고정된 노드 그룹 중심

  • 인스턴스 유형과 크기를 그룹마다 미리 정함
  • 워크로드 모양이 바뀌면 그룹을 새로 설계
  • 비어 가는 노드를 줄이는 판단은 사람이 함
  • AMI 교체와 노드 수명 관리도 별도 작업

Pending Pod 기반 프로비저닝

  • 스케줄되지 못한 Pod의 요구 사항이 수요 신호
  • requirements를 만족하는 인스턴스 유형 중에서 선택
  • 남는 노드는 consolidation으로 회수
  • 설정이나 AMI가 바뀌면 Drift, 오래되면 만료로 교체
핵심 질문이 바뀝니다: "몇 대를 띄울까"가 아니라 "어떤 조건의 노드를 허용하고, 언제 바꿔도 되는가"를 선언합니다.

제어 루프: 누가 무엇을 하나

1Pod가 Pending자리를 찾지 못한 Pod를 unschedulable로 표시kube-scheduler
2NodeClaim 생성NodePool 조건 안에서 인스턴스 후보를 계산하고 NodeClaim을 만듦Karpenter controller
3EC2 시작NodeClass의 subnet, SG, AMI로 인스턴스를 띄움Karpenter cloud provider, EC2
4노드 Readykubelet이 클러스터에 등록, NodeClaim이 Node와 연결kubelet
5Pod 바인딩새 노드에 Pod를 배치kube-scheduler
Karpenter는 Pod를 배치하지 않음
노드를 만들 뿐이고, 바인딩은 여전히 kube-scheduler가 합니다.
NodeClaim이 노드 한 대의 기록
교체, 만료, 중단 판단도 NodeClaim 단위로 이루어집니다.
Auto Mode도 같은 루프
2번과 3번을 AWS가 운영하는 관리형 Karpenter가 맡습니다.

2부: NodePool과 NodeClass의 분업

karpenter.sh/v1, kind: NodePool
  • template.spec.requirements: 허용할 인스턴스 조건
  • disruption: consolidation 정책, budget
  • template.spec.expireAfter, terminationGracePeriod
  • limits, weight, nodeClassRef
무엇을, 언제 바꿀지
어떤 노드를 허용하고 언제 회수, 교체할지를 정합니다. Auto Mode와 직접 운영이 같은 API를 씁니다.
라벨 접두사도 다름: 직접 운영은 karpenter.k8s.aws/instance-*, Auto Mode는 eks.amazonaws.com/instance-*. NodePool을 옮길 때 requirements 키를 바꿔야 합니다.

Auto Mode는 Karpenter를 AWS가 운영

항목EKS Auto ModeSelf-managed Karpenter v1.15
Karpenter controllerAWS 관리, 클러스터 Pod 아님, 버전 비공개사용자 노드의 Pod, Helm과 CRD chart로 업그레이드
AMI, OSAWS 결정, Bottlerocket 변형, 새 AMI는 Drift로 교체amiSelectorTerms, custom AMI, userData
VPC CNI, CoreDNS, kube-proxy, EBS CSI, Pod Identity Agent내장, CNI, CoreDNS, kube-proxy는 노드의 systemd serviceadd-on으로 설치, 관리
Spot 중단, 노드 healthAWS 자동 처리, 자동 repair 내장SQS, EventBridge 구성, NodeRepair는 alpha gate
그래도 사용자 몫
NodePool과 NodeClass 정의, PDB, 워크로드 설계, 비용 관리는 여전히 사용자가 정합니다.
둘 중 하나를 권장
AWS는 한쪽을 권장합니다. 마이그레이션 중 공존하면 NodePool로 워크로드를 분리합니다.

버전 지도: 2026-10-20 기준

EKS 출시
-
표준 지원 종료
-
확장 지원 종료
-
Karpenter 최소
-
비고
-
버전을 누르면 ap-northeast-2 기준 지원 일정과 Karpenter 호환 버전이 바뀝니다.
Karpenter v1.15.0 (2026-10-10)
1.37에 필요. regular release라 다음 minor 출시 전까지만 지원
v1.14.x LTS (2027-07까지)
K8s 1.36까지. v1.14.2 패치 2026-10-19 출시
Auto Mode는 버전 선택 없음
관리형 Karpenter 버전은 비공개이고 AWS가 업그레이드합니다.

3부: 스케일링과 Disruption

노드를 고르고, 줄이고, 바꾸는 규칙

requirements는 넓게, 제약은 명확하게

requirements:
- key: karpenter.sh/capacity-type
  operator: In
  values: ["spot", "on-demand"]
- key: karpenter.k8s.aws/instance-category
  operator: In
  values: ["c", "m", "r"]
- key: kubernetes.io/arch
  operator: In
  values: ["amd64", "arm64"]
계열 단위로 넓게
특정 유형 몇 개보다 category, generation 같은 속성으로 후보를 넓힙니다.
Spot은 유연성이 조건
single-node spot-to-spot 교체는 instance type 15개 이상 유연성이 필요합니다.
capacity-type을 비워 두면: 두 방식 모두 reserved, spot, on-demand 순서로 고릅니다. Auto Mode 기본 풀은 On-Demand 고정이라 Spot은 커스텀 NodePool에서, self-managed는 비워 두면 Spot이 먼저 선택되니 의도를 명시하세요.

Consolidation: 절감이 중단보다 클 때

WhenEmpty
빈 노드만 회수합니다. DaemonSet만 남은 노드도 빈 노드입니다.
WhenEmptyOrUnderutilized
작은 절감이라도 있으면 교체합니다. upstream 기본값
Balanced
절감 비율이 유발하는 Pod disruption 비율보다 가치 있을 때만 실행
2026-07-11 Karpenter v1.14.0
upstream에 Balanced 추가, opt-in
2026-07-27 Auto Mode
NodePool에 Balanced 추가, 기존 NodePool 동작은 그대로
2026-10-01 EKS 1.37
새로 만든 NodePool 중 정책 미지정은 Balanced, built-in pool도 Balanced
GitOps라면 명시하세요: 기본값은 생성 시점에만 적용됩니다. 미지정 NodePool을 재생성하면 Git에는 값이 없고 live 객체는 Balanced인 drift가 생깁니다.

스케줄러 점수: 흩을까, 모을까

여유가 많은 노드에 새 Pod를 보냅니다. 노드마다 여유를 남기는 분산 배치입니다.
노드 A
노드 B
노드 C, 선택
기존 Pod requests새 Pod개념 그림, 사용률은 예시
consolidation과의 관계
MostAllocated는 적게 쓰인 노드에 새 Pod를 보내지 않아, 그 노드가 비면 Auto Mode나 Karpenter가 정리할 수 있습니다.
aws eks update-cluster-config \
  --name $CLUSTER \
  --kube-scheduler-config \
  '{"nodeResourcesFit":{"scoringStrategy":
    {"type":"MostAllocated"}}}'
EKS control plane configuration
2026-08-12 출시, Kubernetes 1.31 이상. 가중치 1 to 100: cpu, memory, nvidia.com/gpu, Neuron
노드 생성, 삭제 방식은 그대로
Pod 배치 점수만 바뀝니다. 클러스터 전체 적용, 실행 중 Pod는 옮기지 않고, 밀집할수록 노드 장애 영향이 커집니다.

In-place resize: 재시작 없이 requests를 줄인다

1.35 GA
컨테이너 in-place resize, resize subresource
1.36 Beta, 기본 켜짐
Pod 단위 .spec.resources도 Pod 재생성 없이 resize
1.37 Alpha
노드가 꽉 차 Deferred된 resize를 위해 scheduler가 낮은 priority Pod를 preempt
워크로드CPU req=limitGuaranteedrestartCountcontainerID
Deployment (Pod 2개)200m → 50m유지0 → 0동일
StatefulSet200m → 50m유지0 → 0동일
DaemonSet200m → 50m유지0 → 0동일
실측 2026-06, EKS 1.36.1, AL2023 arm64 노드(Auto Mode 아님): startup probe 통과 후 pods/resize로 축소, memory 고정
노드 자동화와 만나는 지점
Karpenter v1.14.0부터 Pod 크기를 requests와 allocatedResources 중 큰 값으로 계산합니다. requests가 줄면 consolidation 여지가 생깁니다.
주의
QoS class는 바뀌지 않고, memory 축소는 재시작될 수 있습니다. Auto Mode의 resize 동작은 AWS 문서에 따로 없습니다.

Disruption budget: 한 번에 몇 대까지

disruption:
  consolidationPolicy: Balanced
  budgets:
  - nodes: "10%"
  - nodes: "0"
    schedule: "0 0 * * 1-5"  # UTC
    duration: 9h
    reasons: ["Underutilized", "Drifted"]
40
10%
1
0
-
지금 허용되는 voluntary disruption 수
여러 budget은 최솟값
미지정 시 nodes: 10% 하나. Auto Mode 기본도 같습니다.
schedule은 UTC만
위 예시는 평일 KST 09시부터 9시간 동안 교체 금지입니다.
만료는 막지 못함
expireAfter에 의한 교체는 budget과 무관하게 진행됩니다.

Drift와 만료: 노드는 결국 교체된다

Drift를 일으킴
NodePool template과 NodeClass spec 변경. requirements, subnet, SG, AMI는 resolve 결과로 비교
Drift를 일으키지 않음
spec.weight, spec.limits, spec.disruption.*
AMI는 alias로 고정
al2023@v20261012처럼 pin. @latest는 새 AMI마다 전체 Drift라 프로덕션 비권장
Auto Mode는 AMI가 Drift 신호
새 AMI가 대략 주 1회 나오고 Drift로 롤링. advancedCompute 변경도 in-place 없이 Drift
만료는 강제입니다: NodePool budget을 무시하고 대체 노드 Ready를 기다리지 않습니다. expireAfter를 바꾸면 기존 NodeClaim은 Drift로 교체됩니다.

Spot 중단: 2분 경고는 누가 받나

Self-managed: SQS와 EventBridge를 직접

  • SQS interruption queue, Helm settings.interruptionQueue로 연결
  • EventBridge rule 5개: Spot Interruption Warning, Rebalance, State-change, AWS Health, Capacity Reservation Interruption
  • Spot 경고를 받으면 drain과 새 노드 생성을 병행
  • Rebalance Recommendation은 이벤트 기록만 함

Auto Mode: AWS가 처리

  • Spot 중단 알림, EC2 health 이벤트, 상태 검사 실패를 자동 처리
  • 사용자가 SQS나 EventBridge를 구성하지 않음
  • ARC zonal shift 시 해당 AZ의 노드 생성과 자발적 disruption 중지
queue를 안 붙이면 비활성
self-managed에서 interruptionQueue가 없으면 interruption 처리가 꺼집니다.
FIS EC2 action은 Auto Mode 미지원
SendSpotInstanceInterruptions 포함. Spot 중단 리허설은 self-managed 노드에서 합니다.

교체 중 앱을 지키는 장치들

PodDisruptionBudgetPod 그룹
drain 중 동시에 빠질 수 있는 Pod 수를 제한합니다. Karpenter와 Auto Mode 모두 존중
karpenter.sh/do-not-disruptPod 또는 Node
자발적 disruption 대상에서 뺍니다. 배치 작업처럼 끊으면 안 되는 Pod에 사용
karpenter.sh/disruption-costPod, v1.15
consolidation 비용 가중치. pod-deletion-cost로 조정하는 방식은 deprecated
karpenter.sh/do-not-repairNode, v1.15 신규
Node Auto Repair 대상에서 제외합니다.
보호에는 끝이 있습니다: terminationGracePeriod를 설정하면 blocking PDB나 do-not-disrupt가 있어도 Drift 교체가 진행됩니다. Auto Mode는 21일 최대 수명에서 blocking PDB가 있으면 개입이 필요할 수 있습니다.

4부: Auto Mode 심화와 운영

켜기, 노드 설정, 용량, 진단, 비용, 마이그레이션, 그리고 무엇을 고를까

Auto Mode 켜기: IAM과 세 스위치

역할필요한 것
클러스터 역할신뢰: sts:AssumeRole + sts:TagSession
정책 (AmazonEKS 접두사): ClusterPolicy, ComputePolicy, BlockStoragePolicyV2, LoadBalancingPolicy, NetworkingPolicy
노드 역할AmazonEKSWorkerNodeMinimalPolicy, AmazonEC2ContainerRegistryPullOnly
워크로드Pod Identity로 따로 부여. OIDC provider 없이 활성화 가능
되돌릴 수 없는 것
CONFIG_MAP에서 API_AND_CONFIG_MAP 전환은 단방향. 기존 클러스터의 클러스터 역할 ARN은 교체 불가
# 기존 클러스터: 세 기능을 한 요청에서 함께
aws eks update-cluster-config --name $CLUSTER \
  --compute-config '{"enabled":true,
     "nodePools":["general-purpose","system"],
     "nodeRoleArn":"'$NODE_ROLE_ARN'"}' \
  --kubernetes-network-config \
     '{"elasticLoadBalancing":{"enabled":true}}' \
  --storage-config '{"blockStorage":{"enabled":true}}'
# eksctl: 새 클러스터 create cluster --enable-auto-mode
#         기존 클러스터 update auto-mode-config -f cluster.yaml
kubectl wait nodepool/general-purpose nodepool/system \
  --for=condition=Ready --timeout=300s
켠 직후 노드는 0대일 수 있음
Pending Pod가 생겨야 노드가 뜹니다. default NodeClass는 클러스터 subnet을 물려받으니 private subnet으로 클러스터를 만듭니다.

Built-in 풀과 default NodeClass

NodePool아키텍처용량, 인스턴스누가 올라가나
general-purposeamd64On-Demand, C/M/R, 5세대 이상일반 워크로드
systemamd64, arm64On-Demand, C/M/R, 5세대 이상CriticalAddonsOnly taint를 tolerate하는 Pod
수정하지 말고 추가
built-in 풀은 AWS 관리 객체입니다. Spot, Graviton 범용, GPU는 커스텀 NodePool로 만듭니다. 1.37에서 built-in 풀은 Balanced입니다.
default NodeClass 조건
built-in 풀이 하나 이상 켜져 있어야 생깁니다. 둘 다 끄면 NodeClass를 직접 만들고 참조를 바꿉니다.
목록에서 빼면 노드 종료
computeConfig.nodePools에서 이름을 지우면 그 풀의 노드가 drain, 종료됩니다. 새 Pod만 막는 설정이 아닙니다.
추측 말고 조회: kubectl get nodepool general-purpose system -o yaml, kubectl get nodeclass default -o yaml로 실제 disruption과 taint 값을 확인합니다.

커스텀 NodeClass: 필드 지도

apiVersion: eks.amazonaws.com/v1
kind: NodeClass
spec:
  role: AmazonEKSAutoNodeRole  # 또는 instanceProfile
  subnetSelectorTerms:
  - tags: {kubernetes.io/role/internal-elb: "1"}
  securityGroupSelectorTerms:
  - tags: {Type: worker-node}
  ephemeralStorage:
    size: 100Gi
    iops: 3000
    throughput: 125
  advancedNetworking:
    associatePublicIPAddress: false
  advancedCompute:
    kernel:
      sysctl: {vm.max_map_count: 262144}
  tags: {Environment: production}
role과 instanceProfile은 하나만
AmazonEKSComputePolicy가 eks* 이름의 instance profile에만 권한을 주므로 이름을 eks로 시작합니다. 새 역할에는 access entry가 필요합니다.
tags는 클러스터 역할 권한 필요
커스텀 태그 키로 리소스를 만들 권한이 없으면 launch가 실패합니다. 데모에서 CreateLaunchTemplate 권한 오류로 확인했습니다.
sysctl 변경은 Drift
부팅 시 적용되므로 기존 노드는 교체됩니다. 실행 중인 노드에 바로 적용되지 않습니다.

바꿀 수 없는 보안 기본값

IMDSv2, hop limit 1 고정
일반 Pod는 노드 메타데이터에 닿지 못합니다. hostNetwork Pod는 예외이니 앱 권한은 Pod Identity로 주고 리전 같은 값은 명시합니다.
SSH, SSM 접속 없음
관리형 Bottlerocket 변형, 읽기 전용 root 파일 시스템, SELinux enforcing. 노드에 들어가 고치는 운영은 불가
노드 역할은 최소 권한
WorkerNodeMinimalPolicy와 ContainerRegistryPullOnly. 앱 권한을 노드 역할에 넣지 않습니다.
최대 21일, 주간 AMI
패치는 새 AMI와 Drift로 들어옵니다. 오래된 노드가 남지 않는 대신 교체를 견디는 앱이 전제입니다.
taint와 label은 보안 경계가 아님: 배치를 나누는 도구입니다. 테넌트 격리가 필요하면 클러스터, 계정, 네트워크 정책 수준에서 나눕니다.

Spot, 예약 용량, 정적 풀

커스텀 풀이 필요
built-in 풀은 On-Demand만. 한 풀 안의 우선순위는 reserved, spot, on-demand이고, 배열 순서와 weight는 Spot 비율을 정하지 않습니다.
selector가 reserved를 뺄 수 있음
Pod의 capacity-type: on-demand nodeSelector는 예약 용량을 제외합니다. preferred affinity는 비율을 보장하지 않습니다.
NTH는 필요 없음
중단 처리는 내장입니다. Node Termination Handler DaemonSet과 SQS를 Auto Mode 노드에 두면 처리가 중복됩니다.
2분은 best effort
감지, eviction, 종료 처리가 시간을 씁니다. preStop: sleep 90은 예산 대부분을 소비하는 안티패턴입니다.

GPU와 EFA: 드라이버는 AWS, 사양은 사용자

requirements:
- key: eks.amazonaws.com/instance-gpu-manufacturer
  operator: In
  values: ["nvidia"]
- key: node.kubernetes.io/instance-type
  operator: In
  values: ["g5.2xlarge", "g5.4xlarge"]
taints:
- key: nvidia.com/gpu
  effect: NoSchedule
limits:
  nvidia.com/gpu: "4"
disruption:
  consolidationPolicy: WhenEmpty
  consolidateAfter: 10m
드라이버와 device plugin은 관리형
NVIDIA, Neuron 드라이버와 NVIDIA device plugin이 내장입니다. plugin은 DaemonSet으로 보이지 않고, amiFamily 지정도 없습니다.
유형GPUvCPU / RAM
g5.xlargeA10G 1개4 / 16 GiB
g5.2xlargeA10G 1개8 / 32 GiB
g5.12xlargeA10G 4개48 / 192 GiB
노드 전체 사양을 보세요
4 CPU, 16Gi를 요청하는 Pod는 시스템 예약 때문에 g5.xlarge에 들어가지 않습니다. GPU는 request와 limit을 같게 둡니다.

AZ 장애: ARC zonal shift

장애 AZ (shift 대상)새 노드 프로비저닝 중단. 그 AZ 노드의 consolidation, Drift 같은 voluntary disruption 중단
정상 AZ대체 용량은 여기서 뜹니다. 단, 대체 Pod가 장애 AZ에 의존하면 정상 AZ의 voluntary disruption도 멈춥니다.
사용자 설정클러스터의 zonal-shift-config를 켜면 끝. 플래그, IAM 변경 없음. autoshift는 ARC에서 따로
2026-07-10부터 Auto Mode 지원
ARC zonal shift 자체는 추가 요금이 없고, 대체 용량은 일반 요금입니다.
옮겨 주지 않는 것
단일 AZ EBS 볼륨, DoNotSchedule 같은 엄격한 AZ 제약은 그대로입니다. replica와 topology spread가 먼저입니다.

1.37 업그레이드: Karpenter가 먼저

1Karpenter 1.15.xkarpenter-crd와 controller chart를 함께, 버전 문자열은 1.15.0
2상태 확인EC2NodeClass ValidationSucceeded, 대시보드 label 변경
3컨트롤 플레인 1.37리전 기본은 1.36이라 버전 명시
4노드 AMI 갱신alias pin을 1.37 AMI로 바꾸면 Drift로 롤링, budget 적용
왜 Karpenter가 먼저인가: 1.37 호환 버전은 1.15.x뿐입니다. v1.14 LTS로는 1.36까지만 갈 수 있습니다.

SSH 없이 진단: 로그와 NodeDiagnostic

log type무엇의 판단인가
AUTO_MODE_COMPUTE_LOGS관리형 Karpenter: 프로비저닝, disruption
AUTO_MODE_BLOCK_STORAGE_LOGSEBS CSI
AUTO_MODE_LOAD_BALANCING_LOGSLoad Balancer controller
AUTO_MODE_IPAM_LOGSIP 주소 관리
CloudWatch Vended Logs로 전달
PutDeliverySource, PutDeliveryDestination, CreateDelivery 순서. 목적지는 CloudWatch Logs, S3, Firehose
control plane logging과 별개
api, audit 로그를 켜도 이 로그는 오지 않습니다. 따로 연결하고 전송, 보관 요금을 확인합니다.

무엇을 볼까: 이벤트와 메트릭

얼마나 흔들렸나
disruption이 Pod에 준 영향
karpenter_pods_disrupted_total
label: consolidation_policy, termination_mode
Balanced는 왜 승인했나
점수와 실행된 이동
karpenter_consolidation_score
karpenter_consolidation_moves_total
event: ConsolidationApproved
무엇이 막혔나
budget 여유와 실패
karpenter_nodepool_allowed_disruptions
karpenter_voluntary_disruption_queue_failures_total
karpenter_cloudprovider_errors_total
Auto Mode는 앞 장의 도구로
위 메트릭은 self-managed 기준입니다. Auto Mode는 COMPUTE 로그, NodeClaim, event로 봅니다. event source는 eks-auto-mode/compute
EC2 목록에서 기본 숨김
2026-04-22 이후 Auto Mode 인스턴스는 EC2 콘솔과 describe 목록에서 숨겨집니다. include-managed-resources로 조회

비용: 관리비는 할인되지 않는다

20
-
월 Auto Mode 관리비
-
월 On-Demand EC2
서울 리전 Price List API 단가, 월 730시간 가정의 계산 모델입니다.
인스턴스 유형과 시간 기준
EC2 요금과 별도로 부과, 초 단위 과금, 최소 1분
구매 옵션과 독립
Spot, RI, Savings Plans 할인이 관리비를 줄이지 않습니다. Spot일수록 비율이 커집니다.
GPU 계열 인하 (2026-07-01)
G 계열 35%, P 계열과 Trainium 60% 인하. 조직 150노드 초과는 별도 문의

비용 귀속: 태그, 약정, 무엇이 할인되나

할인 수단EC2 요금Auto Mode 관리비
Compute Savings Plans적용 (최대 66%)미적용
EC2 Instance Savings Plans적용 (최대 72%)미적용
Reserved Instances적용미적용
SpotSpot 가격 (SP 대상 아님)미적용
클러스터별 귀속: aws:eks:cluster-name
AWS가 EC2 인스턴스에 붙이는 태그입니다. Billing에서 cost allocation tag로 활성화해야 보이고, control plane 요금은 포함하지 않습니다.
관리비만 보려면
Cost Explorer에서 usage type이 *EKS-Auto:*-management-hours인 항목으로 거릅니다.
NodePool, 팀 단위는 직접
NodeClass tags로 팀 태그를 붙이거나 Kubecost 같은 도구로 Pod requests 기준 배분합니다.

마이그레이션 1: 바뀌는 driver 이름

리소스직접 설치한 controllerAuto Mode
StorageClass provisionerebs.csi.aws.comebs.csi.eks.amazonaws.com
Service loadBalancerClass (NLB)service.k8s.aws/nlbeks.amazonaws.com/nlb
IngressClass controller (ALB)ingress.k8s.aws/albeks.amazonaws.com/alb
TargetGroupBinding, IngressClassParamselbv2.k8s.aws/v1beta1eks.amazonaws.com/v1
NodeClasskarpenter.k8s.aws/v1 EC2NodeClasseks.amazonaws.com/v1 NodeClass
PVC는 넘어오지 않음
다른 provisioner의 볼륨은 마운트할 수 없습니다. snapshot 복원이나 Retain 후 static PV 재생성, AWS의 migration tool을 씁니다.
LB도 인수하지 않음
새 LB를 만들고 DNS로 blue/green 전환합니다. 기존 LB controller는 자기 리소스가 남아 있는 동안 유지합니다.
CoreDNS Deployment 유지
Auto Mode 노드는 node-local DNS를 씁니다. Auto가 아닌 노드가 남아 있는 동안 기존 CoreDNS를 지우지 않습니다.

마이그레이션 2: 노드를 옮기는 순서

1built-in 풀 없이 켜기nodePools: []. 무제한 general-purpose가 Pending Pod를 먼저 가져가지 않게
2NodeClass, 선택적 풀default NodeClass가 없으니 직접 만들고 EC2 access entry 추가. taint 건 풀
3wave별 이전Deployment, GitOps 원본에 toleration과 compute-type: auto selector. 저위험부터
4한 대씩 drain앱 검증 후 다음 노드. --force, --delete-emptydir-data로 오류를 덮지 않기
5비운 뒤 축소, 삭제기존 노드가 빈 것을 확인하고 desired 0, 삭제는 원래 IaC로
desired size 축소는 drain 단계가 아닙니다: 어떤 노드를 지울지 ASG가 고릅니다. 노드 그룹 전체를 지울 때는 AWS 기본 경로인 eksctl delete nodegroup이 노드를 drain한 뒤 삭제합니다.

Auto Mode인가, 직접 운영인가

직접 운영 쪽 신호

  • custom AMI, userData, launch template, SSH나 SSM 접속이 필요
  • kubelet, sysctl 요구가 advancedCompute 지원 필드를 벗어남
  • Windows 노드, DRA, 대체 CNI 필요 (Security Groups per Pod는 podSecurityGroupSelectorTerms로 대체)
  • feature gate 기능이나 FIS EC2 장애 주입 테스트가 필요

Auto Mode 쪽 신호

  • Karpenter minor마다 CRD와 breaking change를 따라갈 인력이 부족
  • CNI, CoreDNS, EBS CSI, LB controller 운영을 줄이고 싶음
  • 주간 AMI 교체와 21일 수명 상한을 보안 기준으로 받아들일 수 있음
  • 인스턴스당 관리비가 운영 시간 절감보다 작다고 판단
0
직접 운영 신호
0
Auto Mode 신호
왼쪽이 하나라도 필수라면: 그 워크로드는 self-managed가 맞습니다. 클러스터를 나누거나, 마이그레이션 중에만 NodePool로 분리해 공존합니다.

5부: 데모 영상

같은 조건, 두 클러스터: 스케일 아웃, Consolidation, Drift, Spot 중단

데모 환경: 같은 VPC, 같은 NodePool 조건

akd-auto: EKS Auto Mode
  • 노드 OS: Bottlerocket (EKS Auto, Standard) 2026.10.9
  • NodeClass demo (eks.amazonaws.com/v1)
  • 정책 미지정 시 라이브 값: Balanced, expireAfter 336h
akd-karp: 직접 설치 Karpenter 1.15.0
  • 노드 OS: Amazon Linux 2023 (AMI v20261003으로 시작)
  • EC2NodeClass default + interruption queue (SQS)
  • 정책 미지정 시 라이브 값: WhenEmptyOrUnderutilized, expireAfter 720h
공통 조건: EKS 1.37, ap-northeast-2, 데모 VPC의 private 서브넷 2개(2a, 2b). NodePool demo: on-demand, c/m/r 계열, generation 5 초과, amd64, consolidateAfter 30s, budget nodes: "1". 워크로드: pause 컨테이너, replica당 1 vCPU / 1.5Gi
노드에 공인 IP 없음. API endpoint는 작업 PC의 출구 IP 하나만 허용했습니다.

V1: 같은 Pending Pod 10개

실제 터미널 녹화(2026-10-20)와 실측 결과 재구성, 무음

V1 결과: 고른 인스턴스는 같고, 준비 시간은 달랐다

클러스터선택한 노드NodeClaim 생성 (UTC)노드 ReadyPod 10개 Ready
akd-auto (Auto Mode)c7i-flex.4xlarge 1대13:54:15+15초+28초
akd-karp (Karpenter 1.15.0)c7i-flex.4xlarge 1대13:54:15+40초+47초
결정 로직은 같다
같은 requirements와 같은 Pod 요청에 같은 인스턴스 유형, 같은 대수를 골랐습니다. Auto Mode 안에서도 Karpenter가 판단합니다.
시간 차이는 1회 측정
노드 OS(Bottlerocket과 AL2023)와 부팅 구성이 다릅니다. 직접 운영 시 AMI와 userData를 줄이는 만큼 달라질 수 있습니다.

V2: 정책을 비워 두면 무엇이 들어갈까

실제 터미널 녹화(2026-10-20)와 실측 결과 재구성, 무음

V2 결과: 같은 교체, Balanced는 점수로 승인했다

두 클러스터 모두 같은 순서
  1. DisruptionLaunching: 대체 NodeClaim(c7i-flex.2xlarge) 먼저 생성
  2. 새 노드 Ready 확인
  3. DisruptionTerminating: 기존 c7i-flex.4xlarge
  4. Evicted: Pod 4개가 새 노드로 이동
Auto Mode 이벤트 (ConsolidationApproved)
score 0.50 >= threshold 0.50
(k: 2, savings 50.0%, disruption 100.0%)
절감 비율을 disruption 비율로 나눈 점수가 임계값 이상일 때만 실행합니다. 노드 한 대뿐이라 disruption 100%였고, 절감 50%로 겨우 통과했습니다.
시점은 비교하지 않는다
녹화 회차는 Auto Mode +67초, Karpenter +75초에 첫 이동. 앞선 회차는 Karpenter 약 1분, Auto Mode 약 5분 30초 뒤였습니다. 정책의 속도 차이로 해석하지 않습니다.

V3: NodeClass를 바꾸면 노드는 한 대씩

실제 터미널 녹화(2026-10-20)와 실측 결과 재구성, 무음

V3 결과: 새 노드를 먼저, 한 번에 한 대

클러스터바꾼 값Launch, Terminate, Launch, Terminate (UTC)완료
akd-autoadvancedCompute.kubelet.maxPods: 6414:20:12, 14:20:30, 14:20:45, 14:21:00+98초
akd-karpal2023@v20261003 → al2023@v2026101214:20:10, 14:20:46, 14:20:57, 14:21:27+127초
maxPods 64, 실제는 56
새 Auto Mode 노드의 capacity.pods는 56이었습니다. 실제값은 설정값, 인스턴스 IP 수, 110 중 가장 작은 값입니다.
같은 EC2NodeClass는 함께 교체
AMI를 바꾸자 같은 EC2NodeClass를 쓰는 spot NodePool 노드도 Drift로 교체됐습니다. 영향 범위는 NodeClass 단위로 봅니다.

V4: Spot 중단 경고를 받으면

실제 터미널 녹화(2026-10-20)와 실측 결과 재구성, akd-karp만, 무음

V4 결과: Karpenter는 2분을 기다리지 않는다

14:23:15 UTCFIS 실험 시작 (Spot 인스턴스 1대, 2분 전 알림) 14:23:29 UTCSpotInterrupted: Pod 3개 Evicted, 대체 NodeClaim 지명 14:23:35 UTCKarpenter가 기존 인스턴스 종료 시작 14:24:00 UTC대체 노드(c7i-flex.xlarge spot) Ready, Pod 다시 Running
약 30초 동안 Running 0개
replica 3개가 모두 중단된 노드 한 대에 있었습니다. 대체 노드가 Ready가 될 때까지 서비스가 비었습니다.
대책: 분산과 여유
topology spread로 replica를 여러 노드와 zone에 나누고, 여러 인스턴스 유형을 허용해 대체 용량을 넓힙니다. PDB는 중단 drain에도 적용되지만 2분 뒤 회수는 막지 못합니다(이번 시험에는 PDB 없음).

6부: 오늘 가져갈 다섯 가지

1. 판단은 같은 Karpenter
Auto Mode도 같은 조건에 같은 노드를 골랐습니다. 차이는 누가 운영하느냐입니다.
2. 1.37 기본값을 명시
비워 두면 Auto Mode는 Balanced, Karpenter는 WhenEmptyOrUnderutilized입니다.
3. 버전 순서
직접 운영은 Karpenter 1.15.x와 CRD를 먼저, 그다음 Kubernetes 1.37입니다.
4. 교체는 budget으로
AMI는 버전을 고정하고, budget과 PDB로 교체 속도를 정합니다.
5. 배치가 가용성
Spot 중단에 견디는 힘은 replica 분산에서 나옵니다.

참고 자료와 Q&A

다음 단계
관측성과 리소스 최적화까지
EKS Auto Mode & Karpenter 운영: 노드 라이프사이클 모니터링, Grafana 상관분석, VPA와 KEDA
Auto Mode 운영 가이드
kubernetes-docs: EKS Auto Mode 운영 가이드: 시작하기, NodePool, 스케일링, Spot, 운영, 비용, 수명, 워크로드, 마이그레이션 9개 장
데모 스크립트
오늘 영상의 클러스터 구성, NodePool, 녹화 driver, 정리 스크립트는 요청 시 공유합니다.
Q&A
버전과 기본값은 2026-10-20 기준입니다. 적용 전에 최신 문서를 확인하세요.

Thank You

EKS Auto Mode와 Karpenter, 감사합니다

수고하셨습니다!

← 목차로 돌아가기