EKS Auto Mode

Node Lifecycle Management

Junseok Oh

Sr. Solutions Architect

Amazon Web Services

노드가 바뀌는 이유는 다릅니다

Block 2 · 같은 “노드 종료”라도 확인할 원인은 다릅니다

Consolidation · 노드 정리

Pod를 다른 곳에 배치할 수 있어
불필요한 노드를 줄이는 과정입니다.

Drift · 새 설정 반영

원하는 설정과 현재 노드가 달라
새 노드로 교체하는 과정입니다.

Expiration · 수명 만료

expireAfter에 도달해
노드 교체를 시작하는 경우입니다.

Spot interruption · 용량 회수

EC2가 Spot 인스턴스를 회수합니다.
PDB로 회수를 막을 수는 없습니다.

진단 순서: 앱이 영향을 받았나? → 노드가 준비됐나? → 이벤트에 어떤 이유가 남았나?

예약량과 실제 사용량을 구분합니다

Requests = 스케줄링 예약 · Usage = 실제 사용량 · 임계값은 교육용 예시

노드별 예약량과 사용량

노드상태유형RequestsUsage

최근 이벤트 · 교육용

    낮은 사용량만으로 노드를 삭제하지 않습니다. 아래 버튼은 개념을 설명하는 시뮬레이션입니다.

    Pod → 노드 → 이벤트 순서로 봅니다

    명령어를 외우기보다, 결과에서 확인할 질문을 기억하세요

    Pod가 어디서 멈췄나요?

    kubectl get pods -A --field-selector=status.phase=Pending kubectl describe pod <pod> -n <namespace>

    무엇을 읽어야 하나요?

    Events에 FailedScheduling이 있으면 CPU·메모리 요청량, taint, 배치 조건부터 확인합니다.

    이미 노드에 배치됐다면 이미지 다운로드·볼륨·앱 시작 문제도 확인합니다. Pending이 곧 노드 부족은 아닙니다.

    요청한 노드가 준비됐나요?

    kubectl get nodepools kubectl get nodeclaims -o wide kubectl describe nodeclaim <nodeclaim>

    무엇을 읽어야 하나요?

    NodeClaim의 Conditions·Events에서 생성, 등록, 준비 단계가 어디까지 진행됐는지 확인합니다.

    NodePool·NodeClass 조건이 맞는지, IAM·subnet·EC2 용량에 문제가 있는지 이벤트를 보고 좁힙니다.

    무슨 이유로 바뀌었나요?

    kubectl get events -A \ --field-selector involvedObject.kind=NodeClaim \ --sort-by='.lastTimestamp'

    무엇을 읽어야 하나요?

    같은 노드·같은 시간의 교체 이벤트를 앱 장애 시각과 비교합니다.

    NodeClaim 이벤트만으로 부족하면 관련 Node·Pod 이벤트도 확인합니다. 종료 원인은 메트릭 하나로 단정하지 않습니다.

    <pod>, <namespace>, <nodeclaim>은 실제 이름으로 바꿉니다. 명령은 조회용입니다.

    대시보드는 질문에 답하게 만듭니다

    노드 수·대기 Pod·Spot 비율·시작 지연 · 표시 수치는 예시

    count by (label_karpenter_sh_nodepool) (kube_node_labels{label_karpenter_sh_nodepool!=""})

    노드 수 변화는 “무슨 일이 생겼나”의 시작점입니다. 원인은 이벤트와 함께 봅니다. (node 라벨 allowlist 필요)

    workload
    8
    system
    2
    gpu-workload
    0
    sum(kube_pod_status_phase{phase="Pending"})

    전체 Pending Pod 수. 이미 스케줄된 시작 대기 Pod도 포함하며 Unschedulable과 구분합니다.

    Current
    3
    Alert 조건: sum(kube_pod_status_phase{phase="Pending"}) > 10 for 5m
    (count(kube_node_labels{label_karpenter_sh_capacity_type="spot"}) or vector(0)) / count(kube_node_labels{label_karpenter_sh_nodepool!=""}) * 100

    Spot 중단 시 영향을 가늠하는 보조 지표입니다. Pod 개수가 아닌 노드 수의 비율입니다. (라벨 allowlist 필요)

    Spot 비율
    40%
    60%
    On-Demand
    40%
    Spot
    max(karpenter_pods_startup_duration_seconds{quantile="0.99"})

    직접 설치한 Karpenter Controller 수집 필요, Summary 타입이라 quantile label로 조회 · Pod 시작 시간이며 Node Ready 시간과 다름

    P50
    45s
    P90
    72s
    P99
    98s
    📖 더 알아보기: PromQL 분석 패턴

    Spot 회수 통지가 오면?

    Pod 종료 처리와 대체 노드 준비를 함께 시작합니다

    기존 Spot 노드

    대체 용량과 앱

    단계 버튼 또는 ↑ ↓
    결과 비교:
    직접 설치한 Karpenter의 통지 경로와 주의점

    EC2 Spot interruption notice → EventBridge → SQS → Karpenter Controller. 직접 설치한 환경은 interruption queue 구성이 필요하고, Auto Mode는 AWS가 관리합니다.

    이 예시는 stop/terminate 회수 통지입니다. 통상 2분 전 알림이지만 새 노드와 앱의 준비 완료를 보장하지 않습니다. hibernate는 2분 유예 없이 시작됩니다. PDB는 EC2 회수 기한을 늘리지 못합니다.

    공식 근거와 적용 범위

    여유 자리를 미리 준비하면?

    버퍼 용량은 노드 대기를 줄이지만, 그만큼 비용이 듭니다

    Phase 1
    미리 자리 확보
    낮은 우선순위의 더미 Pod가 예약
    Phase 2
    실제 앱이 자리 사용
    조건이 맞으면 더미 Pod를 축출하고 배치
    Phase 3
    여유 자리 다시 확보
    대기 중인 더미 Pod를 위해 용량 보충
    Dummy Workload Pending Node

    이 예시: 더미 Pod로 예약

    빈자리를 낮은 우선순위 Pod가 차지합니다. 실제 앱이 더 높은 우선순위이고 배치 조건이 맞으면 자리를 내줍니다.

    Capacity Buffers API

    직접 설치한 Karpenter는 여유 용량을 선언하는 API도 제공합니다. v1.14에서 v1beta1로 승격됐고, v1.15.0에서도 CapacityBuffer feature gate(alpha, 기본 꺼짐)로 켭니다.

    CRD·적용 범위 확인 · Auto Mode의 지원을 의미하지 않습니다.

    apiVersion: scheduling.k8s.io/v1 kind: PriorityClass metadata: name: overprovisioning value: -1 # 기본값 0보다 낮은 우선순위 globalDefault: false description: "Overprovisioning placeholder pods"

    코드 안에서 스크롤해 전체 설정을 확인하세요.

    apiVersion: apps/v1 kind: Deployment metadata: name: overprovisioning spec: replicas: 2 # 노드당 1개씩 분산 배치 selector: matchLabels: app: overprovisioning template: metadata: labels: app: overprovisioning spec: priorityClassName: overprovisioning terminationGracePeriodSeconds: 0 affinity: # 같은 노드 배치 방지 podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchLabels: app: overprovisioning topologyKey: kubernetes.io/hostname containers: - name: pause image: registry.k8s.io/pause:3.9 resources: requests: cpu: "1" memory: "2Gi"
    기억할 점: 노드가 있어도 이미지 다운로드·앱 초기화는 필요합니다. 버퍼 자체가 Spot이면 함께 회수될 수도 있습니다.
    📖 더 알아보기: Spot 노드 활용 전략

    14일·24시간·21일은 서로 다릅니다

    노드 수명, 종료 유예, 서비스 상한을 구분하세요

    교체를 시작할 시점

    14일
    expireAfter: 336h

    Auto Mode 기본 노드 만료 설정.
    더 짧게 정할 수 있습니다.

    종료할 때 기다리는 시간

    24시간
    terminationGracePeriod

    미지정 시 NodeClaim에 적용되는 기본값.
    노드 종료가 시작된 뒤의 유예입니다.

    서비스가 정한 최대 수명

    21일
    Auto Mode 최대 노드 수명

    14일과 24시간을 더한 값이 아닙니다.
    노드를 유지하는 상한입니다.

    만료 정책 예시:
    전체 NodePool YAML 보기 — 선택한 만료 값이 반영됩니다

    기본 풀이 활성화되어 default NodeClass가 있는 환경의 커스텀 풀 예제입니다.

    apiVersion: karpenter.sh/v1 kind: NodePool metadata: name: workload spec: template: spec: nodeClassRef: group: eks.amazonaws.com kind: NodeClass name: default expireAfter: 336h terminationGracePeriod: 24h disruption: consolidationPolicy: Balanced consolidateAfter: 1m

    Drift·Spot 회수·노드 정리로 더 일찍 교체될 수 있습니다. PDB와 교체 예산이 모든 종료를 막는 것은 아닙니다.

    Drift: 새 설정을 새 노드에 반영합니다

    AMI rev A → AMI rev B · 각 단계 버튼으로 Pod 이동 과정 확인

    AWS가 관리형 AMI를 준비하고, 팀은 Pod 이동의 영향을 설계합니다.
    PDB = 동시에 중단할 Pod 제한 · NodePool 예산 = 동시에 교체할 노드 제한
    📖 더 알아보기: Consolidation & Drift 동작 이해

    AlertManager 알림 규칙

    kube-state-metrics 기반 공통 알림 · 임계값은 예시, Spot 원인은 이벤트로 확인

    PrometheusRule YAML

    apiVersion: monitoring.coreos.com/v1 kind: PrometheusRule metadata: name: karpenter-alerts spec: groups: - name: karpenter rules: # Selected alerts will appear here
    📖 더 알아보기: 관측성 알림 구성 가이드

    Day-2 운영 체크리스트

    EKS Auto Mode 운영 준비 상태 점검

    Disruption & 안정성

    • Disruption Budget 설정 완료
      # NodePool spec: disruption: budgets: - nodes: "10%"
    • PodDisruptionBudget 적용
      apiVersion: policy/v1 kind: PodDisruptionBudget spec: minAvailable: 1 selector: matchLabels: app: my-app
    • Spot 중단 관련 이벤트 확인
      # Spot 원인: NodeClaim 이벤트 확인 kubectl get events -A \ --field-selector involvedObject.kind=NodeClaim
    • expireAfter 정책 설정
      # NodePool spec: template: spec: expireAfter: 168h # 7일
    • 노드 모니터링 대시보드 구축
      # Grafana 대시보드 핵심 패널 count by (label_karpenter_sh_nodepool) (kube_node_labels{label_karpenter_sh_nodepool!=""}) sum(kube_pod_status_phase{phase="Pending"}) kube_node_status_allocatable

    최적화 & 비용

    • AWS 관리 AMI 교체 상태 확인
      # Auto Mode: AWS 관리 AMI 교체 상태 확인 kubectl get nodeclaims -o wide kubectl get nodes -o wide
    • 비용 태깅 (CostCenter, Team)
      # NodePool spec: template: metadata: labels: CostCenter: "engineering" Team: "platform"
    • Multi-AZ 배포 확인
      # NodePool requirements - key: topology.kubernetes.io/zone operator: In values: [ap-northeast-2a, 2b, 2c]
    • Topology Spread Constraints 적용
      # Pod spec topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: DoNotSchedule
    • 정기 비용 리뷰 스케줄
      # CronJob으로 비용 리포트 자동화 schedule: "0 9 * * MON" # 매주 월요일 image: kubecost/cost-analyzer
    Tip: 항목을 클릭하면 관련 YAML 설정을 확인할 수 있습니다. 모든 항목을 점검 후 프로덕션 배포를 진행하세요.
    📖 더 알아보기: Auto Mode Day-2 운영 가이드

    장애 상황에서 무엇부터 볼까요?

    한 상황씩 선택하고 진단 이유를 설명해 보세요

    Pending Pod가 보입니다. 가장 먼저 할 일은?
    expireAfter가 14일이면 그동안 노드가 유지될까요?
    Spot 회수 통지가 왔습니다. PDB가 해주는 일은?

    Thank You

    Block 2 — 노드 라이프사이클 & 모니터링 완료

    ← 목차로 돌아가기 다음: Block 3 →