EKS Pod 헬스체크 & 라이프사이클 관리
📌 기준 환경: EKS 1.33+, Kubernetes 1.30+, AWS Load Balancer Controller v2.7+
1. 개요
Pod의 헬스체크와 라이프사이클 관리는 서비스 안정성과 가용성의 핵심입니다. 적절한 Probe 설정과 Graceful Shutdown 구현은 다음을 보장합니다:
- 무중단 배포: 롤링 업데이트 시 트래픽 유실 방지
- 빠른 장애 감지: 비정상 Pod 자동 격리 및 재시작
- 리소스 최적화: 느린 시작 앱의 조기 재시작 방지
- 데이터 무결성: 종료 시 진행 중인 요청 안전하게 완료
본 문서는 Kubernetes Probe의 동작 원리부터 언어별 Graceful Shutdown 구현, Init Container 활용, 컨테이너 이미지 최적화까지 Pod 라이프사이클 전체를 다룹니다.
- Probe 디버깅: EKS 장애 진단 및 대응 가이드의 "Probe 디버깅 및 Best Practices" 섹션
- 고가용성 설계: EKS 고가용성 아키텍처 가이드의 "Graceful Shutdown", "PDB", "Pod Readiness Gates" 섹션
2. Kubernetes Probe 심층 가이드
2.1 세 가지 Probe 유형과 동작 원리
Kubernetes는 세 가지 유형의 Probe를 제공하여 Pod의 상태를 모니터링합니다.
| Probe 유형 | 목적 | 실패 시 동작 | 활성화 타이밍 |
|---|---|---|---|
| Startup Probe | 애플리케이션 초기화 완료 확인 | Pod 재시작 (failureThreshold 도달 시) | Pod 시작 직후 |
| Liveness Probe | 애플리케이션 데드락/교착 상태 감지 | 컨테이너 재시작 | Startup Probe 성공 후 |
| Readiness Probe | 트래픽 수신 준비 상태 확인 | Service Endpoint에서 제거 (재시작 없음) | Startup Probe 성공 후 |
Startup Probe: 느린 시작 앱 보호
Startup Probe는 애플리케이션이 완전히 시작될 때까지 Liveness/Readiness Probe의 실행을 지연시킵니다. Spring Boot, JVM 애플리케이션, ML 모델 로딩 등 시작이 느린 앱에 필수입니다.
동작 원리:
- Startup Probe가 실행 중일 때는 Liveness/Readiness Probe가 비활성화됨
- Startup Probe 성공 시 → Liveness/Readiness Probe 활성화
- Startup Probe 실패 (failureThreshold 도달) → 컨테이너 재시작
Liveness Probe: 데드락 감지
Liveness Probe는 애플리케이션이 살아있는지 확인합니다. 실패 시 kubelet이 컨테이너를 재시작합니다.
사용 사례:
- 무한 루프, 데드락 상태 감지
- 복구 불가능한 애플리케이션 에러
- 메모리 누수로 인한 응답 불가 상태
주의사항:
- Liveness Probe에 외부 의존성을 포함하지 마세요 (DB, Redis 등)
- 외부 서비스 장애 시 전체 Pod이 재시작되는 cascading failure 발생
Readiness Probe: 트래픽 수신 제어
Readiness Probe는 Pod이 트래픽을 받을 준비가 되었는지 확인합니다. 실패 시 Service의 Endpoints에서 Pod이 제거되지만, 컨테이너는 재시작되지 않습니다.
사용 사례:
- 의존 서비스 연결 확인 (DB, 캐시)
- 초기 데이터 로딩 완료 확인
- 배포 중 단계적 트래픽 수신
2.2 Probe 메커니즘
Kubernetes는 네 가지 Probe 메커니즘을 지원합니다.
| 메커니즘 | 설명 | 장점 | 단점 | 적합한 상황 |
|---|---|---|---|---|
| httpGet | HTTP GET 요청, 200-399 응답 코드 확인 | 표준적, 구현 간단 | HTTP 서버 필요 | REST API, 웹 서비스 |
| tcpSocket | TCP 포트 연결 가능 여부 확인 | 가볍고 빠름 | 애플리케이션 로직 검증 불가 | gRPC, 데이터베이스 |
| exec | 컨테이너 내 명령 실행, exit code 0 확인 | 유연함, 커스텀 로직 가능 | 오버헤드 높음 | 배치 워커, 파일 기반 확인 |
| grpc | gRPC Health Check Protocol 사용 (K8s 1.27+ GA) | 네이티브 gRPC 지원 | gRPC 앱만 사용 가능 | gRPC 마이크로서비스 |
httpGet 예시
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: HealthCheck
scheme: HTTP # 또는 HTTPS
initialDelaySeconds: 30
periodSeconds: 10
tcpSocket 예시
livenessProbe:
tcpSocket:
port: 5432 # PostgreSQL
initialDelaySeconds: 15
periodSeconds: 10
exec 예시
livenessProbe:
exec:
command:
- /bin/sh
- -c
- test -f /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
grpc 예시 (Kubernetes 1.27+)
livenessProbe:
grpc:
port: 9090
service: myservice # 선택 사항
initialDelaySeconds: 10
periodSeconds: 5
gRPC 서비스는 gRPC Health Checking Protocol을 구현해야 합니다. Go는 google.golang.org/grpc/health, Java는 grpc-health-check 라이브러리를 사용하세요.
2.3 Probe 타이밍 설계
Probe의 타이밍 파라미터는 장애 감지 속도와 안정성 간의 균형을 결정합니다.
| 파라미터 | 설명 | 기본값 | 권장 범위 |
|---|---|---|---|
initialDelaySeconds | 컨테이너 시작 후 첫 Probe까지 대기 시간 | 0 | 10-30s (Startup Probe 사용 시 0 가능) |
periodSeconds | Probe 실행 간격 | 10 | 5-15s |
timeoutSeconds | Probe 응답 대기 시간 | 1 | 3-10s |
failureThreshold | 실패 판정까지 연속 실패 횟수 | 3 | Liveness: 3, Readiness: 1-3, Startup: 30+ |
successThreshold | 성공 판정까지 연속 성공 횟수 (Readiness만 1 이상 가능) | 1 | 1-2 |
타이밍 설계 공식
최대 감지 시간 = failureThreshold × periodSeconds
최소 복구 시간 = successThreshold × periodSeconds
예시:
failureThreshold: 3, periodSeconds: 10→ 최대 30초 후 장애 감지successThreshold: 2, periodSeconds: 5→ 최소 10초 후 복구 판정 (Readiness만)
워크로드별 권장 타이밍
| 워크로드 유형 | initialDelaySeconds | periodSeconds | failureThreshold | 이유 |
|---|---|---|---|---|
| 웹 서비스 (Node.js, Python) | 10 | 5 | 3 | 빠른 시작, 빠른 감지 필요 |
| JVM 앱 (Spring Boot) | 0 (Startup Probe 사용) | 10 | 3 | 시작 느림, Startup으로 보호 |
| 데이터베이스 (PostgreSQL) | 30 | 10 | 5 | 초기화 시간 길음 |
| 배치 워커 | 5 | 15 | 2 | 주기적 작업, 느슨한 감지 |
| ML 추론 서비스 | 0 (Startup: 60) | 10 | 3 | 모델 로딩 시간 긺 |
2.4 워크로드별 Probe 패턴
패턴 1: 웹 서비스 (REST API)
apiVersion: apps/v1
kind: Deployment
metadata:
name: rest-api
spec:
replicas: 3
selector:
matchLabels:
app: rest-api
template:
metadata:
labels:
app: rest-api
spec:
containers:
- name: api
image: myapp/rest-api:v1.2.3
ports:
- containerPort: 8080
protocol: TCP
resources:
requests:
cpu: 200m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
# Startup Probe: 30초 이내 시작 완료 확인
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 6
periodSeconds: 5
# Liveness Probe: 내부 헬스체크만 (외부 의존성 제외)
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0 # Startup Probe 사용 시 0으로 설정
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# Readiness Probe: 외부 의존성 포함 가능
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
successThreshold: 1
lifecycle:
preStop:
exec:
command:
- /bin/sh
- -c
- sleep 5
terminationGracePeriodSeconds: 60
:::tip[preStop에서 kill -TERM 1이 불필요한 이유]
Kubernetes는 preStop Hook 완료 후 자동으로 컨테이너의 PID 1에 SIGTERM을 전송합니다. preStop에서 별도로 `kill -TERM 1`을 실행하면 SIGTERM이 중복 전송되며, PID 1이 init 프로세스(tini, dumb-init)인 경우 예상과 다르게 동작할 수 있습니다. 따라서 preStop에서는 `sleep 5`만으로 Endpoint 제거 시간을 확보하고, SIGTERM 전송은 kubelet에 맡기는 것이 안전합니다.
:::
헬스체크 엔드포인트 구현 (Node.js/Express):
// /healthz - Liveness: 애플리케이션 자체 상태만 확인
app.get('/healthz', (req, res) => {
// 내부 상태만 확인 (메모리, CPU 등)
const memUsage = process.memoryUsage();
if (memUsage.heapUsed / memUsage.heapTotal > 0.95) {
return res.status(500).json({ status: 'unhealthy', reason: 'memory_pressure' });
}
res.status(200).json({ status: 'ok' });
});
// /ready - Readiness: 외부 의존성 포함 확인
app.get('/ready', async (req, res) => {
try {
// DB 연결 확인
await db.ping();
// Redis 연결 확인
await redis.ping();
res.status(200).json({ status: 'ready' });
} catch (err) {
res.status(503).json({ status: 'not_ready', reason: err.message });
}
});
패턴 2: gRPC 서비스
apiVersion: apps/v1
kind: Deployment
metadata:
name: grpc-service
spec:
replicas: 3
selector:
matchLabels:
app: grpc-service
template:
metadata:
labels:
app: grpc-service
spec:
containers:
- name: grpc-server
image: myapp/grpc-service:v2.1.0
ports:
- containerPort: 9090
name: grpc
resources:
requests:
cpu: 300m
memory: 512Mi
limits:
cpu: 1
memory: 1Gi
# gRPC native probe (K8s 1.27+)
startupProbe:
grpc:
port: 9090
service: myapp.HealthService # 선택 사항
failureThreshold: 30
periodSeconds: 10
livenessProbe:
grpc:
port: 9090
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
grpc:
port: 9090
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
terminationGracePeriodSeconds: 45
gRPC Health Check 구현 (Go):
package main
import (
"context"
"google.golang.org/grpc"
"google.golang.org/grpc/health"
"google.golang.org/grpc/health/grpc_health_v1"
)
func main() {
server := grpc.NewServer()
// Health 서비스 등록
healthServer := health.NewServer()
grpc_health_v1.RegisterHealthServer(server, healthServer)
// 서비스를 SERVING 상태로 설정
healthServer.SetServingStatus("myapp.HealthService", grpc_health_v1.HealthCheckResponse_SERVING)
// 의존성 체크 후 NOT_SERVING으로 변경 가능
// healthServer.SetServingStatus("myapp.HealthService", grpc_health_v1.HealthCheckResponse_NOT_SERVING)
// gRPC 서버 시작
lis, _ := net.Listen("tcp", ":9090")
server.Serve(lis)
}
패턴 3: 워커/배치 처리
배치 워커는 HTTP 서버가 없으므로 exec Probe를 사용합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: batch-worker
spec:
replicas: 2
selector:
matchLabels:
app: batch-worker
template:
metadata:
labels:
app: batch-worker
spec:
containers:
- name: worker
image: myapp/batch-worker:v3.0.1
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: 2
memory: 4Gi
# Startup Probe: 워커 초기화 확인
startupProbe:
exec:
command:
- /bin/sh
- -c
- test -f /tmp/worker-ready
failureThreshold: 12
periodSeconds: 5
# Liveness Probe: 하트비트 파일 확인
livenessProbe:
exec:
command:
- /bin/sh
- -c
- find /tmp/heartbeat -mmin -2 | grep -q heartbeat
initialDelaySeconds: 10
periodSeconds: 30
failureThreshold: 3
# Readiness Probe: 작업 큐 연결 확인
readinessProbe:
exec:
command:
- /app/check-queue-connection.sh
periodSeconds: 10
failureThreshold: 3
terminationGracePeriodSeconds: 120
워커 애플리케이션 (Python):
import os
import time
from pathlib import Path
HEARTBEAT_FILE = Path("/tmp/heartbeat")
READY_FILE = Path("/tmp/worker-ready")
def worker_loop():
# 초기화 완료 시그널
READY_FILE.touch()
while True:
# 주기적으로 하트비트 업데이트
HEARTBEAT_FILE.touch()
# 작업 처리
process_jobs()
time.sleep(5)
def process_jobs():
# 실제 작업 로직
pass
if __name__ == "__main__":
worker_loop()
패턴 4: 느린 시작 앱 (Spring Boot, JVM)
JVM 애플리케이션은 시작 시간이 30초 이상 소요될 수 있습니다. Startup Probe로 보호합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-boot-app
spec:
replicas: 4
selector:
matchLabels:
app: spring-boot
template:
metadata:
labels:
app: spring-boot
spec:
containers:
- name: app
image: myapp/spring-boot:v2.7.0
ports:
- containerPort: 8080
resources:
requests:
cpu: 1
memory: 2Gi
limits:
cpu: 2
memory: 4Gi
env:
- name: JAVA_OPTS
value: "-Xms1g -Xmx3g"
# Startup Probe: 최대 5분(30 x 10s) 대기
startupProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
failureThreshold: 30
periodSeconds: 10
# Liveness Probe: Startup 성공 후 활성화
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: 8080
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# Readiness Probe: 외부 의존성 포함
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: 8080
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 2
terminationGracePeriodSeconds: 60
Spring Boot Actuator 설정:
# application.yml
management:
endpoints:
web:
exposure:
include: health
health:
livenessState:
enabled: true
readinessState:
enabled: true
endpoint:
health:
probes:
enabled: true
show-details: when-authorized
패턴 5: 사이드카 패턴 (Istio Proxy + 앱)
사이드카 패턴에서는 메인 컨테이너와 사이드카 모두에 Probe를 설정합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-sidecar
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
# 메인 애플리케이션 컨테이너
- name: app
image: myapp/app:v1.0.0
ports:
- containerPort: 8080
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
# Istio 사이드카 (자동 주입 시 Istio가 Probe 추가)
# 수동 설정 예시:
- name: istio-proxy
image: istio/proxyv2:1.22.0
ports:
- containerPort: 15090
name: http-envoy-prom
startupProbe:
httpGet:
path: /healthz/ready
port: 15021
failureThreshold: 30
periodSeconds: 1
livenessProbe:
httpGet:
path: /healthz/ready
port: 15021
periodSeconds: 10
readinessProbe:
httpGet:
path: /healthz/ready
port: 15021
periodSeconds: 2
terminationGracePeriodSeconds: 90
Istio가 자동 주입을 사용하는 경우 (istio-injection=enabled 레이블), Istio가 사이드카에 적절한 Probe를 자동으로 추가합니다. 수동 설정은 불필요합니다.
Native Sidecar Containers (K8s 1.28+ GA)
Kubernetes 1.28부터 GA된 Native Sidecar Container는 Init Container에 restartPolicy: Always를 설정하여 사이드카로 동작시키는 공식 기능입니다. 이를 통해 기존 사이드카 패턴의 종료 순서 문제를 해결합니다.
기존 문제: 일반 사이드카는 메인 컨테이너와 동시에 SIGTERM을 수신하므로, Istio proxy가 먼저 종료되면 메인 앱의 네트워크가 끊기는 문제가 발생합니다.
Native Sidecar 해결: Init Container로 정의된 사이드카는 모든 일반 컨테이너가 종료된 후에 종료됩니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: app-with-native-sidecar
spec:
template:
spec:
initContainers:
# Native Sidecar: 메인 컨테이너보다 먼저 시작, 나중에 종료
- name: log-collector
image: fluentbit:latest
restartPolicy: Always # 이 설정이 Native Sidecar로 동작하게 함
ports:
- containerPort: 2020
resources:
requests:
cpu: 50m
memory: 64Mi
containers:
- name: app
image: myapp:v1
ports:
- containerPort: 8080
종료 순서 보장:
- 일반 컨테이너(app)에 SIGTERM 전송
- 일반 컨테이너 종료 완료 대기
- Native Sidecar(log-collector)에 SIGTERM 전송
- Native Sidecar 종료
이 패턴은 Istio 사이드카, 로그 수집기, 모니터링 에이전트 등 메인 앱보다 오래 살아있어야 하는 보조 컨테이너에 적합합니다.
2.4.6 Windows 컨테이너 Probe 고려사항
EKS는 Windows Server 2019/2022 기반 Windows 노드를 지원하며, Windows 컨테이너는 Linux 컨테이너와 다른 Probe 동작 특성을 가집니다.
Windows vs Linux Probe 동작 차이
| 항목 | Linux 컨테이너 | Windows 컨테이너 | 영향 |
|---|---|---|---|
| 컨테이너 런타임 | containerd | containerd (1.6+) | 동일한 런타임, 다른 OS 레이어 |
| exec Probe 실행 | /bin/sh -c | cmd.exe /c 또는 powershell.exe | 스크립트 문법 차이 |
| httpGet Probe | 동일 | 동일 | 차이 없음 |
| tcpSocket Probe | 동일 | 동일 | 차이 없음 |
| 콜드 스타트 시간 | 빠름 (수초) | 느림 (10-30초) | Startup Probe failureThreshold 증가 필요 |
| 메모리 오버헤드 | 낮음 (50-100MB) | 높음 (200-500MB) | 리소스 요청 증가 필요 |
| Probe 타임아웃 | 일반적으로 1-5초 | 3-10초 권장 | Windows I/O 지연 고려 |
Windows 워크로드 Probe 설정 예시
IIS/.NET Framework 앱:
apiVersion: apps/v1
kind: Deployment
metadata:
name: iis-app
namespace: windows-workloads
spec:
replicas: 2
selector:
matchLabels:
app: iis-app
template:
metadata:
labels:
app: iis-app
spec:
nodeSelector:
kubernetes.io/os: windows
kubernetes.io/arch: amd64
containers:
- name: iis
image: mcr.microsoft.com/windows/servercore/iis:windowsservercore-ltsc2022
ports:
- containerPort: 80
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 2000m
memory: 2Gi
# Startup Probe: Windows 콜드 스타트 고려
startupProbe:
httpGet:
path: /
port: 80
scheme: HTTP
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 12 # Linux 대비 2배 (최대 60초)
successThreshold: 1
# Liveness Probe: IIS 프로세스 상태
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
# Readiness Probe: ASP.NET 앱 준비 상태
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 5
failureThreshold: 3
successThreshold: 1
terminationGracePeriodSeconds: 60
ASP.NET Core 헬스체크 엔드포인트 구현:
// Program.cs (ASP.NET Core 6+)
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
var builder = WebApplication.CreateBuilder(args);
// 헬스체크 추가
builder.Services.AddHealthChecks()
.AddCheck("self", () => HealthCheckResult.Healthy())
.AddSqlServer(
connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),
name: "sqlserver",
tags: new[] { "ready" }
);
var app = builder.Build();
// /healthz - Liveness: 애플리케이션 자체만
app.MapHealthChecks("/healthz", new HealthCheckOptions
{
Predicate = check => check.Tags.Contains("self") || check.Tags.Count == 0
});
// /ready - Readiness: 외부 의존성 포함
app.MapHealthChecks("/ready", new HealthCheckOptions
{
Predicate = _ => true // 모든 헬스체크
});
app.Run();
Windows 워크로드 Probe 타임아웃 주의사항
Windows 컨테이너는 다음 이유로 Probe 타임아웃이 길어질 수 있습니다:
- Windows 커널 오버헤드: Windows의 무거운 OS 레이어로 인한 시스템 콜 지연
- 디스크 I/O 성능: NTFS 파일시스템의 메타데이터 오버헤드
- .NET Framework 워밍업: CLR JIT 컴파일 및 어셈블리 로딩 시간
- Windows Defender: 실시간 스캔으로 인한 프로세스 시작 지연
권장 Probe 타이밍 (Windows):
startupProbe:
timeoutSeconds: 5-10 # Linux: 3-5초
periodSeconds: 5
failureThreshold: 12-20 # Linux: 6-10
livenessProbe:
timeoutSeconds: 5-10 # Linux: 3-5초
periodSeconds: 10-15 # Linux: 10초
failureThreshold: 3
readinessProbe:
timeoutSeconds: 5-10 # Linux: 3-5초
periodSeconds: 5-10 # Linux: 5초
failureThreshold: 3
CloudWatch Container Insights for Windows (2025-08)
AWS는 2025년 8월에 Windows 워크로드용 CloudWatch Container Insights 지원을 발표했습니다.
Windows 노드에 Container Insights 설치:
# CloudWatch Agent ConfigMap (Windows)
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: cwagentconfig-windows
namespace: amazon-cloudwatch
data:
cwagentconfig.json: |
{
"logs": {
"metrics_collected": {
"kubernetes": {
"cluster_name": "my-eks-cluster",
"metrics_collection_interval": 60
}
}
},
"metrics": {
"namespace": "ContainerInsights",
"metrics_collected": {
"statsd": {
"service_address": ":8125"
}
}
}
}
EOF
# Windows DaemonSet 배포
kubectl apply -f https://raw.githubusercontent.com/aws-samples/amazon-cloudwatch-container-insights/latest/k8s-deployment-manifest-templates/deployment-mode/daemonset/container-insights-monitoring/cwagent/cwagent-daemonset-windows.yaml
Container Insights 메트릭 확인:
# Windows 노드 메트릭
aws cloudwatch get-metric-statistics \
--namespace ContainerInsights \
--metric-name node_memory_utilization \
--dimensions Name=ClusterName,Value=my-eks-cluster Name=NodeName,Value=windows-node-1 \
--start-time 2026-02-12T00:00:00Z \
--end-time 2026-02-12T23:59:59Z \
--period 300 \
--statistics Average
# Windows Pod 메트릭
aws cloudwatch get-metric-statistics \
--namespace ContainerInsights \
--metric-name pod_cpu_utilization \
--dimensions Name=ClusterName,Value=my-eks-cluster Name=Namespace,Value=windows-workloads \
--start-time 2026-02-12T00:00:00Z \
--end-time 2026-02-12T23:59:59Z \
--period 60 \
--statistics Average
혼합 클러스터 (Linux + Windows) 통합 모니터링 전략
1. 노드 셀렉터 기반 분리:
apiVersion: v1
kind: Service
metadata:
name: unified-app
spec:
selector:
app: unified-app # OS 무관
ports:
- port: 80
targetPort: 8080
---
# Linux Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: unified-app-linux
spec:
replicas: 3
selector:
matchLabels:
app: unified-app
os: linux
template:
metadata:
labels:
app: unified-app
os: linux
spec:
nodeSelector:
kubernetes.io/os: linux
containers:
- name: app
image: myapp:linux-v1
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
timeoutSeconds: 3
---
# Windows Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: unified-app-windows
spec:
replicas: 2
selector:
matchLabels:
app: unified-app
os: windows
template:
metadata:
labels:
app: unified-app
os: windows
spec:
nodeSelector:
kubernetes.io/os: windows
containers:
- name: app
image: myapp:windows-v1
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 10 # Windows: 더 긴 간격
timeoutSeconds: 10 # Windows: 더 긴 타임아웃
2. CloudWatch Logs Insights 통합 쿼리:
-- Linux와 Windows Pod 로그를 동시에 검색
fields @timestamp, kubernetes.namespace_name, kubernetes.pod_name, kubernetes.host, @message
| filter kubernetes.labels.app = "unified-app"
| sort @timestamp desc
| limit 100
3. Grafana 대시보드 통합:
# Prometheus Query (혼합 클러스터)
# Linux + Windows Pod CPU 사용률
sum(rate(container_cpu_usage_seconds_total{namespace="default", pod=~"unified-app-.*"}[5m])) by (pod, node, os)
# OS별 집계
sum(rate(container_cpu_usage_seconds_total{namespace="default", pod=~"unified-app-.*"}[5m])) by (os)
- 이미지 크기: Windows 이미지는 수 GB (Linux는 수십 MB)
- 라이선스 비용: Windows Server 라이선스 비용 발생 (EC2 인스턴스 비용에 포함)
- 노드 부팅 시간: Windows 노드는 부팅이 느림 (5-10분)
- 특권 컨테이너: Windows는 Linux의
privileged모드 미지원 - HostProcess 컨테이너: Windows Server 2022 (1.22+)부터 지원
2.5 Probe 안티패턴과 함정
❌ 안티패턴 1: Liveness Probe에 외부 의존성 포함
문제:
livenessProbe:
httpGet:
path: /health # DB, Redis 연결 확인 포함
port: 8080
결과:
- DB 장애 시 모든 Pod이 동시 재시작 → Cascading Failure
- 일시적인 네트워크 지연으로도 Pod 재시작
올바른 설정:
# Liveness: 애플리케이션 자체 상태만
livenessProbe:
httpGet:
path: /healthz # 내부 상태만 확인
port: 8080
# Readiness: 외부 의존성 포함
readinessProbe:
httpGet:
path: /ready # DB, Redis 등 확인
port: 8080
❌ 안티패턴 2: Startup Probe 없이 높은 initialDelaySeconds
문제:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 120 # 2분 대기
periodSeconds: 10
결과:
- 앱이 30초에 시작 완료해도 90초 동안 헬스체크 없음
- 시작 중 크래시가 발생해도 2분까지 감지 불가
올바른 설정:
# Startup Probe로 시작 보호
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 12 # 최대 120초 대기
periodSeconds: 10
# Liveness는 Startup 성공 후 즉시 활성화
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 0 # Startup 성공 후 바로 시작
periodSeconds: 10
❌ 안티패턴 3: Liveness와 Readiness에 같은 엔드포인트
문제:
livenessProbe:
httpGet:
path: /health
port: 8080
readinessProbe:
httpGet:
path: /health # 동일한 엔드포인트
port: 8080
결과:
/health가 외부 의존성을 확인하면 Liveness가 실패하여 불필요한 재시작- 역할 구분이 모호하여 디버깅 어려움
올바른 설정:
livenessProbe:
httpGet:
path: /healthz # 내부 상태만
port: 8080
readinessProbe:
httpGet:
path: /ready # 외부 의존성 포함
port: 8080
❌ 안티패턴 4: 너무 공격적인 failureThreshold
문제:
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 5
failureThreshold: 1 # 단 1번 실패로 재시작
결과:
- 일시적인 네트워크 지연, GC pause 등으로 불필요한 재시작
- 재시작 루프 발생 가능
올바른 설정:
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3 # 30초(3 x 10s) 후 재시작
timeoutSeconds: 5
❌ 안티패턴 5: 과도하게 긴 timeoutSeconds
문제:
livenessProbe:
httpGet:
path: /healthz
port: 8080
timeoutSeconds: 30 # 30초 대기
periodSeconds: 10
결과:
- Probe가 30초 동안 blocking되어 다음 Probe 실행 지연
- 장애 감지가 느려짐
올바른 설정:
livenessProbe:
httpGet:
path: /healthz
port: 8080
timeoutSeconds: 5 # 5초 이내 응답 필요
periodSeconds: 10
failureThreshold: 3
2.6 ALB/NLB 헬스체크와 Probe 통합
AWS Load Balancer Controller를 사용하는 경우, ALB/NLB의 헬스체크와 Kubernetes Readiness Probe를 동기화해야 무중단 배포가 가능합니다.
ALB Target Group 헬스체크 vs Readiness Probe
| 구분 | ALB/NLB 헬스체크 | Kubernetes Readiness Probe |
|---|---|---|
| 실행 주체 | AWS Load Balancer | kubelet |
| 체크 대상 | Target Group의 IP:Port | Pod 컨테이너 |
| 실패 시 동작 | Target에서 제거 (트래픽 차단) | Service Endpoints에서 제거 |
| 기본 간격 | 30초 | 10초 |
| 타임아웃 | 5초 | 1초 |
헬스체크 타이밍 동기화 전략
롤링 업데이트 시 다음 순서로 동작합니다:
권장 설정:
apiVersion: v1
kind: Service
metadata:
name: myapp
annotations:
# ALB 헬스체크 설정
alb.ingress.kubernetes.io/healthcheck-path: /ready
alb.ingress.kubernetes.io/healthcheck-interval-seconds: "10"
alb.ingress.kubernetes.io/healthcheck-timeout-seconds: "5"
alb.ingress.kubernetes.io/healthy-threshold-count: "2"
alb.ingress.kubernetes.io/unhealthy-threshold-count: "2"
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
selector:
app: myapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
template:
spec:
containers:
- name: app
image: myapp:v1
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /ready # ALB와 동일한 경로
port: 8080
periodSeconds: 5 # ALB보다 짧은 간격
failureThreshold: 2
successThreshold: 1
terminationGracePeriodSeconds: 60
Pod Readiness Gates (무중단 배포 보장)
AWS Load Balancer Controller v2.5+는 Pod Readiness Gates를 지원하여, Pod이 ALB/NLB 타겟으로 등록되고 헬스체크를 통과할 때까지 Ready 상태 전환을 지연시킵니다.
활성화 방법:
# Namespace에 레이블 추가로 자동 주입 활성화
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
elbv2.k8s.aws/pod-readiness-gate-inject: enabled
동작 확인:
# Pod의 Readiness Gates 확인
kubectl get pod myapp-xyz -o yaml | grep -A 10 readinessGates
# 출력 예시:
# readinessGates:
# - conditionType: target-health.alb.ingress.k8s.aws/my-target-group-hash
# Pod Conditions 확인
kubectl get pod myapp-xyz -o jsonpath='{.status.conditions}' | jq
장점:
- 롤링 업데이트 시 Old Pod이 타겟에서 제거되기 전까지 유지됨
- New Pod이 ALB 헬스체크 통과 후에만 트래픽 수신
- 트래픽 유실 없는 완전한 무중단 배포
Pod Readiness Gates에 대한 자세한 내용은 EKS 고가용성 아키텍처 가이드의 "Pod Readiness Gates" 섹션을 참조하세요.
2.6.4 Gateway API 헬스체크 통합 (ALB Controller v2.14+)
AWS Load Balancer Controller v2.14+는 Kubernetes Gateway API v1.4와 네이티브 통합하여, Ingress보다 향상된 경로별 헬스체크 매핑을 제공합니다.
Gateway API vs Ingress 헬스체크 비교
| 구분 | Ingress | Gateway API |
|---|---|---|
| 헬스체크 설정 위치 | Service/Ingress annotation | HealthCheckPolicy CRD |
| 경로별 헬스체크 | 제한적 (annotation 기반) | 네이티브 지원 (HTTPRoute/GRPCRoute별) |
| L4/L7 프로토콜 지원 | HTTP/HTTPS만 | TCP/UDP/TLS/HTTP/GRPC 모두 지원 |
| 멀티 테넌트 역할 분리 | 단일 Ingress 오브젝트 | Gateway(인프라)/Route(앱) 분리 |
| 가중치 기반 카나리 | 어렵거나 불가능 | HTTPRoute 네이티브 지원 |
Gateway API 아키텍처와 헬스체크
L7 헬스체크: HTTPRoute/GRPCRoute with ALB
HealthCheckPolicy CRD 예시:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gateway
namespace: production
spec:
gatewayClassName: alb
listeners:
- name: http
protocol: HTTP
port: 80
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-v1-route
namespace: production
spec:
parentRefs:
- name: prod-gateway
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api/v1
backendRefs:
- name: api-v1-service
port: 8080
---
# HealthCheckPolicy (AWS Load Balancer Controller v2.14+)
apiVersion: elbv2.k8s.aws/v1beta1
kind: HealthCheckPolicy
metadata:
name: api-v1-healthcheck
namespace: production
spec:
targetGroupARN: arn:aws:elasticloadbalancing:region:account:targetgroup/name/id
healthCheckConfig:
protocol: HTTP
path: /api/v1/healthz # 경로별 헬스체크
port: 8080
intervalSeconds: 10
timeoutSeconds: 5
healthyThresholdCount: 2
unhealthyThresholdCount: 2
matcher:
httpCode: "200-299"
GRPCRoute 헬스체크 예시:
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GRPCRoute
metadata:
name: grpc-service-route
namespace: production
spec:
parentRefs:
- name: prod-gateway
hostnames:
- grpc.example.com
rules:
- matches:
- method:
service: myservice.v1.MyService
backendRefs:
- name: grpc-backend
port: 9090
---
apiVersion: elbv2.k8s.aws/v1beta1
kind: HealthCheckPolicy
metadata:
name: grpc-healthcheck
namespace: production
spec:
targetGroupARN: arn:aws:elasticloadbalancing:region:account:targetgroup/grpc/id
healthCheckConfig:
protocol: HTTP # gRPC 헬스체크는 HTTP/2 기반
path: /grpc.health.v1.Health/Check
port: 9090
intervalSeconds: 10
timeoutSeconds: 5
healthyThresholdCount: 2
unhealthyThresholdCount: 2
matcher:
grpcCode: "0" # gRPC OK status
L4 헬스체크: TCPRoute/UDPRoute with NLB
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: tcp-service-route
namespace: production
spec:
parentRefs:
- name: nlb-gateway
sectionName: tcp-listener
rules:
- backendRefs:
- name: tcp-backend
port: 5432
---
apiVersion: elbv2.k8s.aws/v1beta1
kind: HealthCheckPolicy
metadata:
name: tcp-healthcheck
namespace: production
spec:
targetGroupARN: arn:aws:elasticloadbalancing:region:account:targetgroup/tcp/id
healthCheckConfig:
protocol: TCP # TCP 연결만 확인
port: 5432
intervalSeconds: 30
timeoutSeconds: 10
healthyThresholdCount: 3
unhealthyThresholdCount: 3
Gateway API Pod Readiness Gates
Gateway API는 Ingress와 동일하게 Pod Readiness Gates를 지원합니다:
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
elbv2.k8s.aws/pod-readiness-gate-inject: enabled
동작 확인:
# Gateway 상태 확인
kubectl get gateway prod-gateway -n production
# HTTPRoute 상태 확인
kubectl get httproute api-v1-route -n production -o yaml
# Pod의 Readiness Gates 확인
kubectl get pod -n production -l app=api-v1 \
-o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[?(@.type=="target-health.gateway.networking.k8s.io")].status}{"\n"}{end}'
Ingress에서 Gateway API로 마이그레이션 시 헬스체크 전환 체크리스트
| 단계 | Ingress | Gateway API | 확인 항목 |
|---|---|---|---|
| 1. 헬스체크 경로 매핑 | Annotation 기반 | HealthCheckPolicy CRD | 경로별 정책 분리 |
| 2. 프로토콜 설정 | HTTP/HTTPS만 | HTTP/HTTPS/GRPC/TCP/UDP | 프로토콜 타입 확인 |
| 3. Pod Readiness Gates | Namespace 레이블 | Namespace 레이블 (동일) | 무중단 배포 보장 |
| 4. 헬스체크 타이밍 | Service annotation | HealthCheckPolicy | interval/timeout 검증 |
| 5. 멀티 경로 헬스체크 | 단일 경로만 | 경로별 독립 설정 | 각 경로 검증 |
마이그레이션 예시 (Ingress → Gateway API):
# Before (Ingress)
apiVersion: v1
kind: Service
metadata:
name: myapp
annotations:
alb.ingress.kubernetes.io/healthcheck-path: /healthz
alb.ingress.kubernetes.io/healthcheck-interval-seconds: "10"
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
spec:
rules:
- host: api.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp
port:
number: 8080
# After (Gateway API)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: myapp-route
spec:
parentRefs:
- name: prod-gateway
hostnames:
- api.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: myapp
port: 8080
---
apiVersion: elbv2.k8s.aws/v1beta1
kind: HealthCheckPolicy
metadata:
name: myapp-healthcheck
spec:
targetGroupARN: <auto-discovered-or-explicit>
healthCheckConfig:
protocol: HTTP
path: /healthz
port: 8080
intervalSeconds: 10
timeoutSeconds: 5
healthyThresholdCount: 2
unhealthyThresholdCount: 2
- 단계적 마이그레이션: 동일한 ALB에서 Ingress와 Gateway API를 동시에 사용 가능 (리스너 분리)
- 카나리 배포: HTTPRoute의 가중치 기반 트래픽 분할로 안전한 전환
- 롤백 계획: Ingress 오브젝트는 마이그레이션 완료 후 일정 기간 유지
2.7 2025-2026 EKS 신규 기능과 Probe 통합
AWS re:Invent 2025에서 발표된 EKS의 새로운 관찰성 및 제어 기능은 Probe 기반 헬스체크를 더욱 강화합니다. 이 섹션에서는 최신 EKS 기능과 Probe를 통합하여 더 정확하고 선제적인 헬스 모니터링을 구현하는 방법을 다룹니다.
2.7.1 Container Network Observability로 Probe 연결성 검증
개요:
Container Network Observability(2025년 11월 발표)는 Pod 간 네트워크 통신 패턴, 지연 시간, 패킷 손실 등 세밀한 네트워크 메트릭을 제공합니다. Probe 실패가 네트워크 문제로 인한 것인지, 애플리 케이션 자체 문제인지 명확히 구분할 수 있습니다.
주요 기능:
- Pod-to-Pod 통신 경로 시각화
- 네트워크 지연(latency), 패킷 손실(packet loss), 재전송률 모니터링
- 실시간 네트워크 트래픽 이상 탐지
- CloudWatch Container Insights와의 통합
활성화 방법:
# VPC CNI에서 네트워크 관찰성 활성화
kubectl set env daemonset aws-node \
-n kube-system \
ENABLE_NETWORK_OBSERVABILITY=true
# 또는 ConfigMap으로 설정
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: amazon-vpc-cni
namespace: kube-system
data:
enable-network-observability: "true"
EOF
Probe 연결성 검증 예시:
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-gateway
annotations:
# 네트워크 관찰성 메트릭 수집 활성화
network-observability.amazonaws.com/enabled: "true"
spec:
replicas: 3
template:
spec:
containers:
- name: gateway
image: myapp/gateway:v2
ports:
- containerPort: 8080
# Readiness Probe: 외부 DB 연결 확인
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 5
failureThreshold: 2
timeoutSeconds: 3
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
failureThreshold: 3
CloudWatch Insights 쿼리 - Probe 실패와 네트워크 지연 상관 분석:
-- Probe 실패 시점의 네트워크 지연 확인
fields @timestamp, pod_name, probe_type, network_latency_ms, packet_loss_percent
| filter namespace = "production"
| filter probe_result = "failed"
| filter network_latency_ms > 100 or packet_loss_percent > 1
| sort @timestamp desc
| limit 100
알림 설정 예시:
# CloudWatch Alarm: Probe 실패와 네트워크 이상 동시 발생
apiVersion: v1
kind: ConfigMap
metadata:
name: probe-network-alert
namespace: monitoring
data:
alarm-config: |
{
"AlarmName": "ProbeFailureWithNetworkIssue",
"MetricName": "ReadinessProbeFailure",
"Namespace": "ContainerInsights",
"Statistic": "Sum",
"Period": 60,
"EvaluationPeriods": 2,
"Threshold": 3,
"ComparisonOperator": "GreaterThanThreshold",
"Dimensions": [
{"Name": "ClusterName", "Value": "production-eks"},
{"Name": "Namespace", "Value": "production"}
],
"AlarmDescription": "Readiness Probe 실패 시 네트워크 지연 확인 필요"
}
진단 워크플로우:
Container Network Observability는 CloudWatch Logs Insights와 통합되어 Probe 요청의 전체 네트워크 경로를 추적할 수 있습니다. Readiness Probe가 외부 데이터베이스를 확인하는 경우, Pod → Service → Endpoint → DB Pod의 전체 경로에서 병목 구간을 식별할 수 있습니다.
2.7.2 CloudWatch Observability Operator + Control Plane 메트릭
개요:
CloudWatch Observability Operator(2025년 12월 발표)는 EKS Control Plane 메트릭을 자동으로 수집하여, API Server 성능 저하가 Probe 응답에 미치는 영향을 사전에 감지합니다.
설치:
# CloudWatch Observability Operator 설치
kubectl apply -f https://raw.githubusercontent.com/aws-observability/aws-cloudwatch-observability-operator/main/bundle.yaml
# EKS Control Plane 메트릭 수집 활성화
kubectl apply -f - <<EOF
apiVersion: cloudwatch.aws.amazon.com/v1alpha1
kind: EKSControlPlaneMetrics
metadata:
name: production-control-plane
namespace: amazon-cloudwatch
spec:
clusterName: production-eks
region: ap-northeast-2
metricsCollectionInterval: 60s
enabledMetrics:
- apiserver_request_duration_seconds
- apiserver_request_total
- apiserver_storage_objects
- etcd_request_duration_seconds
- rest_client_requests_total
EOF
주요 Control Plane 메트릭:
| 메트릭 | 설명 | Probe 연관성 | 임계값 예시 |
|---|---|---|---|
apiserver_request_duration_seconds | API Server 요청 지연 시간 | Probe 요청 처리 속도 | p99 < 1초 |
apiserver_request_total (code=5xx) | API Server 5xx 에러 수 | Probe 실패율 상승 | < 1% |
apiserver_storage_objects | etcd 저장 오브젝트 수 | 클러스터 규모 한계 | < 150,000 |
etcd_request_duration_seconds | etcd 읽기/쓰기 지연 | Pod 상태 업데이트 지연 | p99 < 100ms |
rest_client_requests_total (code=429) | API Rate Limiting 발생 | kubelet-apiserver 통신 제한 | < 10/min |
Probe 타임아웃 예측 알림:
apiVersion: cloudwatch.amazonaws.com/v1alpha1
kind: Alarm
metadata:
name: apiserver-slow-probe-risk
spec:
alarmName: "EKS-APIServer-SlowProbeRisk"
metrics:
- id: m1
metricStat:
metric:
namespace: AWS/EKS
metricName: apiserver_request_duration_seconds
dimensions:
- name: ClusterName
value: production-eks
- name: verb
value: GET
period: 60
stat: p99
- id: e1
expression: "IF(m1 > 0.5, 1, 0)"
label: "API Server 응답 지연 > 500ms"
evaluationPeriods: 2
threshold: 1
comparisonOperator: GreaterThanOrEqualToThreshold
alarmDescription: "API Server 성능 저하로 인한 Probe 타임아웃 위험"
alarmActions:
- arn:aws:sns:ap-northeast-2:123456789012:eks-ops-alerts
대규모 클러스터에서의 Probe 성능 보장:
# 1000+ 노드 클러스터의 Probe 설정 최적화
apiVersion: apps/v1
kind: Deployment
metadata:
name: large-scale-api
spec:
replicas: 100
template:
spec:
containers:
- name: api
image: myapp/api:v1
# Probe 타이밍 조정: API Server 부하 고려
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 5 # 초기 시작 시간 여유
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 15 # 대규모에서는 간격 증가
failureThreshold: 3
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /ready
port: 8080
periodSeconds: 10
failureThreshold: 2
timeoutSeconds: 3
CloudWatch Dashboard - Control Plane & Probe 상관 분석:
{
"widgets": [
{
"type": "metric",
"properties": {
"title": "API Server 지연 vs Probe 실패율",
"metrics": [
["AWS/EKS", "apiserver_request_duration_seconds", {"stat": "p99", "label": "API Server p99 지연"}],
["ContainerInsights", "ReadinessProbeFailure", {"stat": "Sum", "yAxis": "right"}]
],
"period": 60,
"region": "ap-northeast-2",
"yAxis": {
"left": {"label": "지연 시간 (초)", "min": 0},
"right": {"label": "Probe 실패 수", "min": 0}
}
}
}
]
}
1000개 이상의 노드를 가진 클러스터에서는 모든 kubelet의 Probe 요청이 API Server에 집중될 수 있습니다. periodSeconds를 10~15초로 늘리고, timeoutSeconds를 5초 이상으로 설정하여 API Server 부하를 분산시키세요. Provisioned Control Plane(Section 2.7.3)을 사용하면 이 문제를 근본적으로 해결할 수 있습니다.
2.7.3 Provisioned Control Plane에서 Probe 성능 보장
개요:
Provisioned Control Plane(2025년 11월 발표)은 사전 할당된 제어 플레인 용량으로 예측 가능한 고성능 Kubernetes 운영을 보장합니다. 대규모 클러스터에서 Probe 요청이 API Server 성능 저하의 영향을 받지 않도록 합니다.
티어별 성능 특성:
| 티어 | API 동시성 | Pod 스케줄링 속도 | 최대 노드 수 | Probe 처리 보장 | 적합 워크로드 |
|---|---|---|---|---|---|
| XL | 높음 | ~500 Pods/min | 1,000 | 99.9% < 100ms | AI Training, HPC |
| 2XL | 매우 높음 | ~1,000 Pods/min | 2,500 | 99.9% < 80ms | 대규모 배치 |
| 4XL | 초고속 | ~2,000 Pods/min | 5,000 | 99.9% < 50ms | 초대규모 ML |
Standard vs Provisioned Control Plane:
Provisioned Control Plane 생성:
# Provisioned Control Plane 클러스터 생성 (AWS CLI)
aws eks create-cluster \
--name production-provisioned \
--region ap-northeast-2 \
--kubernetes-version 1.32 \
--role-arn arn:aws:iam::123456789012:role/eks-cluster-role \
--resources-vpc-config subnetIds=subnet-xxx,subnet-yyy,securityGroupIds=sg-zzz \
--control-plane-type PROVISIONED \
--control-plane-tier XL
대규모 Probe 최적화 예시:
# AI/ML Training 클러스터 (1000+ GPU 노드)
apiVersion: apps/v1
kind: Deployment
metadata:
name: training-coordinator
annotations:
# Provisioned Control Plane에서 최적화된 Probe 설정
eks.amazonaws.com/control-plane-tier: "XL"
spec:
replicas: 50
template:
spec:
containers:
- name: coordinator
image: ml-training/coordinator:v3
resources:
requests:
cpu: 4
memory: 16Gi
# Provisioned Control Plane에서는 짧은 간격 설정 가능
startupProbe:
httpGet:
path: /healthz
port: 9090
failureThreshold: 30
periodSeconds: 3 # 빠른 감지
livenessProbe:
httpGet:
path: /healthz
port: 9090
periodSeconds: 5 # Standard보다 짧게
failureThreshold: 2
timeoutSeconds: 2
readinessProbe:
httpGet:
path: /ready
port: 9090
periodSeconds: 3
failureThreshold: 1
timeoutSeconds: 2
사용 사례: AI/ML Training 클러스터
- 문제: 1,000개의 GPU 노드에서 동시에 수백 개의 Training Pod 시작 시, Standard Control Plane에서 API Server 응답 지연 발생
- 해결: Provisioned Control Plane XL 티어 사용
- 결과:
- Pod 스케줄링 시간 70% 단축 (평균 45초 → 13초)
- Readiness Probe 타임아웃 99.8% 감소
- Training Job 시작 안정성 향상
Cost vs Performance 고려사항:
# Provisioned Control Plane 비용 최적화 전략
# 1. 평상시: Standard Control Plane
# 2. Training 기간: Provisioned Control Plane XL로 업그레이드
# (현재는 클러스터 생성 시 선택, 향후 동적 변경 지원 예정)
Provisioned Control Plane은 짧은 시간 내에 수천 개의 Pod을 동시에 시작하는 워크로드에 최적화되어 있습니다. AI/ML Training, 과학 시뮬레이션, 대규모 데이터 처리 등에서 Probe 성능을 보장하여 Job 시작 시간을 단축할 수 있습니다.