EKS 고가용성 아키텍처 가이드
📌 기준 환경: EKS 1.33+, Karpenter v1.x, Istio 1.22+
1. 개요
레질리언시(Resiliency)는 시스템이 장애에 직면했을 때 정상 상태로 복구하거나, 장애 영향을 최소화하면서 서비스를 유지하는 능력입니다. 클라우드 네이티브 환경에서 레질리언시의 핵심 원칙은 단순합니다: 장애는 반드시 발생한다 — 설계로 대비한다.
단일 Pod 장애부터 리전 전체 장애까지, 각 계층에서 발생할 수 있는 Failure Domain을 이해하고 그에 맞는 방어 전략을 수립하는 것이 EKS 운영의 핵심입니다.
Failure Domain 계층 구조
레질리언시 성숙도 모델
조직의 레질리언시 수준을 4단계로 분류하고, 현재 위치에서 점진적으로 발전시켜 나갈 수 있습니다.
| Level | 단계 | 핵심 역량 | 구현 항목 | 복잡성 | 비용 영향 |
|---|---|---|---|---|---|
| 1 | 기본 (Basic) | Pod 수준 복원력 | Probe 설정, PDB, Graceful Shutdown, 리소스 Limits | 낮음 | 최소 |
| 2 | Multi-AZ | AZ 장애 내성 | Topology Spread, Multi-AZ NodePool, ARC Zonal Shift | 중간 | Cross-AZ 트래픽 비용 |
| 3 | Cell-Based | Blast Radius 격리 | Cell Architecture, Shuffle Sharding, 독립 배포 | 높음 | Cell 별 오버헤드 |
| 4 | Multi-Region | 리전 장애 내성 | Active-Active 아키텍처, Global Accelerator, 데이터 복제 | 매우 높음 | 리전 별 인프라 비용 |
운영 중 장애 진단 및 해결은 EKS 장애 진단 및 대응 가이드를 참조하세요. 본 문서는 장애 예방과 설계에 초점을 맞추고 있으며, 실시간 트러블슈팅은 장애 진단 및 대응 가이드에서 다룹니다.
2. Multi-AZ 전략
Multi-AZ 배포는 EKS 레질리언시의 가장 기본적이면서도 강력한 전략입니다. 단일 AZ 장애가 서비스 전체를 중단시키지 않도록 워크로드를 여러 가용 영역에 분산합니다.
Pod Topology Spread Constraints
Topology Spread Constraints는 Pod를 AZ, 노드, 커스텀 토폴로지 도메인에 걸쳐 균등하게 분산시킵니다. minDomains 파라미터(K8s 1.24 alpha → 1.30 GA)를 통해 최소 분산 도메인 수를 지정할 수 있습니다.
| 파라미터 | 설명 | 권장값 |
|---|---|---|
maxSkew | 도메인 간 Pod 수 최대 차이 | AZ: 1, 노드: 2 |
topologyKey | 분산 기준 레이블 | topology.kubernetes.io/zone |
whenUnsatisfiable | 조건 불충족 시 동작 | DoNotSchedule (hard) 또는 ScheduleAnyway (soft) |
minDomains | 최소 분산 도메인 수 | AZ 수와 동일 (예: 3) |
labelSelector | 대상 Pod 선택 | Deployment의 matchLabels와 동일 |
Hard + Soft 조합 전략 (권장):
apiVersion: apps/v1
kind: Deployment
metadata:
name: critical-app
spec:
replicas: 6
selector:
matchLabels:
app: critical-app
template:
metadata:
labels:
app: critical-app
spec:
topologySpreadConstraints:
# Hard: AZ 간 균등 분산 (반드시 보장)
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: critical-app
minDomains: 3
# Soft: 노드 간 분산 (가능한 한 보장)
- maxSkew: 2
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
matchLabels:
app: critical-app
maxSkew: 1은 가장 엄격한 균등 분산을 보장합니다. 6개 replica를 3 AZ에 배포하면 각 AZ에 정확히 2개씩 배치됩니다. 스케일링 속도가 중요한 경우 maxSkew: 2로 느슨하게 설정하여 스케줄링 유연성을 확보할 수 있습니다.
AZ-aware Karpenter 설정
Karpenter v1 GA에서는 NodePool 단위로 Multi-AZ 분산, Disruption budget, Spot + On-Demand 혼합 전략을 선언적으로 구성합니다.
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: multi-az-pool
spec:
disruption:
consolidationPolicy: WhenEmptyOrUnderutilized
consolidateAfter: 5m
# Disruption budget: 동시에 20% 이상의 노드가 중단되지 않도록 제한
budgets:
- nodes: "20%"
# 업무 시간에는 더 보수적으로 운영 (선택 사항)
# - nodes: "10%"
# schedule: "0 9 * * MON-FRI" # 평일 09:00-17:00
# duration: 8h
template:
spec:
requirements:
# 3개 AZ에 걸쳐 노드 프로비저닝
- key: topology.kubernetes.io/zone
operator: In
values: ["us-east-1a", "us-east-1b", "us-east-1c"]
# Spot + On-Demand 혼합으로 비용 최적화 + 안정성 확보
- key: karpenter.sh/capacity-type
operator: In
values: ["on-demand", "spot"]
- key: node.kubernetes.io/instance-type
operator: In
values:
- c6i.xlarge
- c6i.2xlarge
- c6i.4xlarge
- c7i.xlarge
- c7i.2xlarge
- c7i.4xlarge
- m6i.xlarge
- m6i.2xlarge
nodeClassRef:
group: karpenter.k8s.aws
kind: EC2NodeClass
name: multi-az
limits:
cpu: "1000"
memory: 2000Gi
Spot 인스턴스는 AZ별로 가용 풀이 다릅니다. 15개 이상의 다양한 인스턴스 유형을 지정하면 Spot 용량 부족으로 인한 프로비저닝 실패를 최소화할 수 있습니다. 미션 크리티컬 워크로드의 base capacity는 반드시 On-Demand로 운영하세요.
Node Readiness 기반 안전한 워크로드 배치
Multi-AZ 환경에서 새 노드가 프로비저닝될 때, 노드가 Ready 상태가 되더라도 실제로 워크로드를 수용할 준비가 완료되지 않았을 수 있습니다. 이를 방지하기 위한 Kubernetes readiness 메커니즘들을 활용합니다.
Node Readiness Controller (2026년 2월 발표)
Node Readiness Controller는 노드 부트스트랩 과정에서 커스텀 taint를 선언적으로 관리하여, GPU 드라이버, CNI 플러그인, CSI 드라이버, 보안 에이전트 등 모든 인프라 요구사항이 충족될 때까지 워크로드 스케줄링을 지연시킵니다.
레질리언시 관점의 이점:
- AZ 장애 복구 시: Karpenter가 새 AZ에 노드를 프로비저닝할 때, 노드가 완전히 준비된 후에만 트래픽을 수용
- Scale-out 이벤트: 급격한 확장 시에도 미완성 노드에 워크로드가 배치되지 않음
- GPU/ML 워크로드: 드라이버 로딩 완료 전 스케줄링을 방지하여
CrashLoopBackOff방지
Pod Scheduling Readiness (K8s 1.30 GA)
schedulingGates를 사용하면 Pod 측에서 스케줄링 타이밍을 제어할 수 있습니다. 외부 시스템이 준비 상태를 확인한 후 gate를 제거하여 스케줄링을 허용합니다:
apiVersion: v1
kind: Pod
metadata:
name: validated-pod
spec:
schedulingGates:
- name: "example.com/capacity-validation"
- name: "example.com/security-clearance"
containers:
- name: app
image: app:latest
resources:
requests:
cpu: "4"
memory: "8Gi"
활용 사례:
- 리소스 쿼터 사전 검증 후 스케줄링 허용
- 보안 승인 완료 후 스케줄링 허용
- 커스텀 어드미션 체크 통과 후 스케줄링 허용