본문으로 건너뛰기

Karpenter와 Node Drain

2026-02-12 작성2026-09-17 수정6분 읽기
문서 도구
AI용 문서 안내

Pod 라이프사이클 개요 · 체크리스트와 참고 자료

Karpenter/Node Drain과의 상호작용

Karpenter가 노드를 통합(consolidation)하거나 Spot 인스턴스가 종료될 때, 노드의 모든 Pod이 안전하게 이동해야 합니다.

Karpenter Disruption과 Graceful Shutdown

글씨가 작으면 확대해서 확인할 수 있습니다.

Karpenter NodePool 설정:

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 5m
# Disruption budget: 동시 중단 노드 제한
budgets:
- nodes: "20%"
schedule: "0 9-17 * * MON-FRI" # 업무 시간 20%
- nodes: "50%"
schedule: "0 0-8,18-23 * * *" # 비업무 시간 50%
PDB와 Karpenter 상호작용

PodDisruptionBudget이 너무 엄격하면 (예: minAvailable이 replica 수와 같음) Karpenter가 노드를 drain할 수 없습니다. PDB는 minAvailable: replica - 1 또는 maxUnavailable: 1로 설정하여 최소 1개 Pod은 이동 가능하도록 하세요.

ARC + Karpenter 통합 AZ 대피 패턴

개요:

AWS Application Recovery Controller(ARC)와 Karpenter의 통합(2025년 발표)은 Availability Zone(AZ) 장애 시 자동으로 워크로드를 다른 AZ로 이동시키는 고가용성 패턴을 제공합니다. 이를 통해 AZ 장애 또는 Gray Failure 상황에서도 Graceful Shutdown을 보장하며 서비스 중단을 최소화할 수 있습니다.

ARC Zonal Shift란:

Zonal Shift는 특정 AZ에서 발생한 장애나 성능 저하를 감지했을 때, 해당 AZ의 트래픽을 자동으로 다른 정상 AZ로 전환하는 기능입니다. EKS와 통합 시 Pod의 안전한 이동까지 자동화됩니다.

아키텍처 구성 요소:

컴포넌트역할동작
ARC Zonal AutoshiftAZ 장애 자동 감지 및 트래픽 전환 결정CloudWatch Alarms 기반 자동 Shift
Karpenter새 AZ에 노드 프로비저닝NodePool 설정에 따라 정상 AZ에 노드 생성
AWS Load Balancer트래픽 라우팅 제어장애 AZ의 Target 제거
PodDisruptionBudgetPod 이동 시 가용성 보장최소 가용 Pod 수 유지

AZ 대피 시퀀스:

글씨가 작으면 확대해서 확인할 수 있습니다.

설정 예시:

1. ARC Zonal Autoshift 활성화:

# Load Balancer에 Zonal Autoshift 활성화
aws arc-zonal-shift create-autoshift-observer-notification-configuration \
--resource-identifier arn:aws:elasticloadbalancing:ap-northeast-2:123456789012:loadbalancer/app/production-alb/1234567890abcdef

# Zonal Autoshift 설정
aws arc-zonal-shift update-zonal-autoshift-configuration \
--resource-identifier arn:aws:elasticloadbalancing:ap-northeast-2:123456789012:loadbalancer/app/production-alb/1234567890abcdef \
--zonal-autoshift-status ENABLED

2. Karpenter NodePool - AZ 인식 설정:

apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: default
spec:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 30s
# AZ 장애 시 빠른 대응
budgets:
- nodes: "100%"
reasons:
- "Drifted" # AZ Cordon 시 즉시 교체
template:
spec:
requirements:
- key: "topology.kubernetes.io/zone"
operator: In
values:
- ap-northeast-2a
- ap-northeast-2b
- ap-northeast-2c
- key: karpenter.sh/capacity-type
operator: In
values:
- on-demand # AZ 장애 대응은 On-Demand 권장
nodeClassRef:
name: default
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: default
spec:
amiFamily: AL2023
role: "KarpenterNodeRole-production"
subnetSelectorTerms:
- tags:
karpenter.sh/discovery: "production-eks"
securityGroupSelectorTerms:
- tags:
karpenter.sh/discovery: "production-eks"
# AZ 장애 시 자동 감지
metadataOptions:
httpTokens: required
httpPutResponseHopLimit: 2

3. Deployment with PDB - AZ 분산:

apiVersion: apps/v1
kind: Deployment
metadata:
name: critical-api
spec:
replicas: 6
selector:
matchLabels:
app: critical-api
template:
metadata:
labels:
app: critical-api
spec:
# AZ 분산 보장
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: critical-api
# 동일 노드 배치 방지
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: critical-api
topologyKey: kubernetes.io/hostname
containers:
- name: api
image: myapp/critical-api:v3
ports:
- containerPort: 8080
resources:
requests:
cpu: 500m
memory: 1Gi
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
failureThreshold: 2
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- sleep 5
terminationGracePeriodSeconds: 60
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: critical-api-pdb
spec:
minAvailable: 4 # 6개 중 최소 4개 유지 (AZ 장애 시 2개 AZ에서 운영)
selector:
matchLabels:
app: critical-api

4. CloudWatch Alarm - AZ 성능 저하 감지:

apiVersion: v1
kind: ConfigMap
metadata:
name: az-health-monitoring
namespace: monitoring
data:
cloudwatch-alarm: |
{
"AlarmName": "AZ-A-NetworkLatency-High",
"MetricName": "NetworkLatency",
"Namespace": "AWS/EC2",
"Statistic": "Average",
"Period": 60,
"EvaluationPeriods": 3,
"Threshold": 100,
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [
{"Name": "AvailabilityZone", "Value": "ap-northeast-2a"}
],
"AlarmDescription": "AZ-A 네트워크 지연 증가 - Zonal Shift 트리거",
"AlarmActions": [
"arn:aws:arc-zonal-shift:ap-northeast-2:123456789012:autoshift-observer-notification"
]
}

Istio 서비스 메시 기반 End-to-End AZ 복구:

Istio 서비스 메시와 통합하면 AZ 대피 시 더욱 정교한 트래픽 제어가 가능합니다:

# Istio DestinationRule: AZ 기반 트래픽 라우팅
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: critical-api-az-routing
spec:
host: critical-api.production.svc.cluster.local
trafficPolicy:
loadBalancer:
localityLbSetting:
enabled: true
distribute:
- from: ap-northeast-2a/*
to:
"ap-northeast-2b/*": 50
"ap-northeast-2c/*": 50
- from: ap-northeast-2b/*
to:
"ap-northeast-2a/*": 50
"ap-northeast-2c/*": 50
- from: ap-northeast-2c/*
to:
"ap-northeast-2a/*": 50
"ap-northeast-2b/*": 50
outlierDetection:
consecutiveErrors: 3
interval: 10s
baseEjectionTime: 30s
maxEjectionPercent: 50
---
# VirtualService: AZ 장애 시 자동 재라우팅
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: critical-api-failover
spec:
hosts:
- critical-api.production.svc.cluster.local
http:
- match:
- sourceLabels:
topology.kubernetes.io/zone: ap-northeast-2a
route:
- destination:
host: critical-api.production.svc.cluster.local
subset: az-b
weight: 50
- destination:
host: critical-api.production.svc.cluster.local
subset: az-c
weight: 50
timeout: 3s
retries:
attempts: 3
perTryTimeout: 1s

Gray Failure 처리 전략:

Gray Failure는 완전한 장애가 아닌 성능 저하 상태로, 감지가 어렵습니다. ARC + Karpenter + Istio 조합으로 대응:

Gray Failure 증상감지 방법자동 대응
네트워크 지연 증가 (50-200ms)Container Network ObservabilityIstio Outlier Detection → 트래픽 우회
간헐적 패킷 손실 (1-5%)CloudWatch Network MetricsARC Zonal Shift 트리거
디스크 I/O 저하EBS CloudWatch MetricsKarpenter 노드 교체
API Server 응답 지연Control Plane MetricsProvisioned Control Plane 자동 스케일링

테스트 및 검증:

# AZ 장애 시뮬레이션 (Chaos Engineering)
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: az-failure-test
namespace: chaos
data:
experiment: |
# 1. AZ-A의 모든 노드에 Taint 추가 (AZ 장애 시뮬레이션)
kubectl taint nodes -l topology.kubernetes.io/zone=ap-northeast-2a \
az-failure=true:NoSchedule

# 2. Karpenter가 AZ-B, AZ-C에 새 노드 생성 확인
kubectl get nodes -l topology.kubernetes.io/zone=ap-northeast-2b,ap-northeast-2c

# 3. Pod 이동 모니터링
kubectl get pods -o wide --watch

# 4. PDB 준수 확인 (minAvailable 유지)
kubectl get pdb critical-api-pdb

# 5. Graceful Shutdown 로그 확인
kubectl logs <pod-name> --previous

# 6. 복구 (Taint 제거)
kubectl taint nodes -l topology.kubernetes.io/zone=ap-northeast-2a \
az-failure-
EOF

모니터링 대시보드:

# Grafana Dashboard: AZ 헬스 및 대피 상태
apiVersion: v1
kind: ConfigMap
metadata:
name: az-failover-dashboard
namespace: monitoring
data:
dashboard.json: |
{
"panels": [
{
"title": "AZ별 Pod 분포",
"targets": [
{
"expr": "count(kube_pod_info) by (node, zone)"
}
]
},
{
"title": "AZ별 네트워크 지연",
"targets": [
{
"expr": "avg(container_network_latency_ms) by (availability_zone)"
}
]
},
{
"title": "Karpenter 노드 프로비저닝 속도",
"targets": [
{
"expr": "rate(karpenter_nodes_created_total[5m])"
}
]
},
{
"title": "Graceful Shutdown 성공률",
"targets": [
{
"expr": "rate(pod_termination_graceful_total[5m]) / rate(pod_termination_total[5m])"
}
]
}
]
}

관련 자료:

운영 Best Practice

AZ 대피는 자동화되지만, 정기적인 Chaos Engineering 테스트로 검증하세요. 매 분기 1회 이상 AZ 장애 시뮬레이션을 수행하여 PDB, Karpenter, Graceful Shutdown이 예상대로 동작하는지 확인합니다. 특히 terminationGracePeriodSeconds가 실제 Shutdown 시간보다 충분히 긴지 프로덕션 환경에서 측정하세요.

Spot 인스턴스 2분 경고 처리

AWS Spot 인스턴스는 종료 2분 전에 경고를 보냅니다. 이를 처리하여 Graceful Shutdown을 보장합니다.

AWS Node Termination Handler 설치:

helm repo add eks https://aws.github.io/eks-charts
helm repo update

helm install aws-node-termination-handler \
--namespace kube-system \
eks/aws-node-termination-handler \
--set enableSpotInterruptionDraining=true \
--set enableScheduledEventDraining=true

동작 방식:

  1. Spot 종료 2분 경고 감지
  2. 노드를 즉시 Cordon (새 Pod 스케줄링 차단)
  3. 노드의 모든 Pod을 Drain
  4. Pod의 terminationGracePeriodSeconds 내에 Graceful Shutdown 완료

권장 terminationGracePeriodSeconds:

  • 일반 웹 서비스: 30-60초
  • 장기 실행 작업 (배치, ML 추론): 90-120초
  • 최대 2분 이내로 설정 (Spot 경고 시간 고려)