예측 스케일링 및 자동 복구 패턴
📅 작성일: 2026-02-12 | 수정일: 2026-02-14 | ⏱️ 읽는 시간: 약 29분
1. 개요
1.1 반응형에서 자율형으로
EKS 운영의 진화는 반응형 → 예측형 → 자율형의 3단계로 이루어집니다.
이 문서의 범위
반응형 스케일링의 한계를 넘어, ML 기반 예측 스케일링과 AI Agent를 통한 자율 복구 패턴을 다룹니다. 특히 Kiro+MCP 기반 프로그래머틱 디버깅과 Kagent/Strands 기반 자동 인시던트 대응을 중심으로 설명합니다.
1.2 왜 예측 운영이 필요한가
- HPA의 한계: 메트릭 임계값 초과 후 반응 → 이미 사용자 영향 발생
- Cold Start 문제: 새 Pod 시작까지 30초-2분 → 트래픽 급증 시 대응 불가
- 노드 프로비저닝 지연: Karpenter도 노드 시작에 1-3분 소요
- 복합 장애: 단일 메트릭으로는 감지 불가한 복합 원인 장애 증가
- 비용 비효율: 과도한 여유 리소스 확보 → 비용 낭비
2. ML 기반 예측 스케일링
2.1 HPA의 한계
HPA(Horizontal Pod Autoscaler)는 현재 메트릭에 반응하므로 구조적 한계가 있습니다.
[HPA의 반응형 스케일링]
트래픽 ████████████████████████░░░░░░░░░
↑ 임계값 초과
|
Pod 수 ██████████░░░░████████████████████
↑ 스케일아웃 시작
| (지연 발생)
사용자 ✓✓✓✓✓✓✓✓✗✗✗✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓
경험 ↑ 성능 저하 구간
[ML 예측 스케일링]
트래픽 ████████████████████████░░░░░░░░░
↑ 예측 시점 (30분 전)
|
Pod 수 ██████████████████████████████████
↑ 사전 스케일아웃
|
사용자 ✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓✓
경험 (성능 저하 없음)
2.2 시계열 예측 모델
EKS 워크로드의 트래픽 패턴을 예측하는 대표적 ML 모델:
2.3 Prophet 기반 예측 스케일링 구현
# Prophet 기반 EKS 트래픽 예측
import boto3
from prophet import Prophet
import pandas as pd
from datetime import datetime, timedelta
def fetch_metrics_from_amp(workspace_id, query, hours=168):
"""AMP에서 지난 7일간 메트릭 조회"""
client = boto3.client('amp', region_name='ap-northeast-2')
end_time = datetime.utcnow()
start_time = end_time - timedelta(hours=hours)
response = client.query_range(
workspaceId=workspace_id,
query=query,
startTime=start_time,
endTime=end_time,
step='5m'
)
return response
def predict_scaling(metrics_df, forecast_hours=2):
"""Prophet으로 향후 트래픽 예측"""
# Prophet 형식으로 변환
df = metrics_df.rename(columns={
'timestamp': 'ds',
'value': 'y'
})
model = Prophet(
changepoint_prior_scale=0.05,
seasonality_mode='multiplicative',
daily_seasonality=True,
weekly_seasonality=True,
)
model.fit(df)
# 향후 forecast_hours 예측
future = model.make_future_dataframe(
periods=forecast_hours * 12, # 5분 간격
freq='5min'
)
forecast = model.predict(future)
return forecast[['ds', 'yhat', 'yhat_upper', 'yhat_lower']]
def calculate_required_pods(predicted_rps, pod_capacity_rps=100):
"""예측 RPS 기반 필요 Pod 수 계산"""
# 상한값(yhat_upper) 사용으로 안전 마진 확보
required = int(predicted_rps / pod_capacity_rps) + 1
return max(required, 2) # 최소 2개 유지
def apply_scaling(namespace, deployment, target_replicas):
"""kubectl을 통해 스케일링 적용"""
import subprocess
cmd = f"kubectl scale deployment/{deployment} -n {namespace} --replicas={target_replicas}"
subprocess.run(cmd.split(), check=True)
print(f"Scaled {deployment} to {target_replicas} replicas")
2.4 CronJob 기반 예측 스케일링 자동화
# 예측 스케일링을 주기적으로 실행하는 CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: predictive-scaler
namespace: scaling
spec:
schedule: "*/15 * * * *" # 15분마다 실행
jobTemplate:
spec:
template:
spec:
serviceAccountName: predictive-scaler
containers:
- name: scaler
image: my-registry/predictive-scaler:latest
env:
- name: AMP_WORKSPACE_ID
value: "ws-xxxxx"
- name: TARGET_NAMESPACE
value: "payment"
- name: TARGET_DEPLOYMENT
value: "payment-service"
- name: FORECAST_HOURS
value: "2"
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: "1"
memory: 2Gi
restartPolicy: OnFailure
2.5 네트워크 성능 예측 및 ML 추론 워크로드 최적화
EKS의 Container Network Observability는 Pod-to-Pod 통신 패턴을 세밀하게 모니터링하여, 네트워크 병목을 사전에 예측하고 ML 추론 워크로드의 성능을 최적화할 수 있습니다.
Container Network Observability 데이터 활용
1. Pod-to-Pod 통신 패턴 → 네트워크 병목 예측
# Container Network Observability 메트릭 기반 병목 예측
import boto3
from prophet import Prophet
import pandas as pd
def predict_network_bottleneck(cluster_name, namespace):
"""
Pod-to-Pod 네트워크 지연을 예측하여 병목 가능성을 판단합니다.
"""
cloudwatch = boto3.client('cloudwatch')
# Container Network Observability 메트릭 조회
metrics = cloudwatch.get_metric_data(
MetricDataQueries=[
{
'Id': 'rx_latency',
'MetricStat': {
'Metric': {
'Namespace': 'ContainerInsights',
'MetricName': 'pod_network_rx_latency_ms',
'Dimensions': [
{'Name': 'ClusterName', 'Value': cluster_name},
{'Name': 'Namespace', 'Value': namespace}
]
},
'Period': 300,
'Stat': 'Average'
}
},
{
'Id': 'tx_bytes',
'MetricStat': {
'Metric': {
'Namespace': 'ContainerInsights',
'MetricName': 'pod_network_tx_bytes',
'Dimensions': [
{'Name': 'ClusterName', 'Value': cluster_name},
{'Name': 'Namespace', 'Value': namespace}
]
},
'Period': 300,
'Stat': 'Sum'
}
}
],
StartTime=datetime.utcnow() - timedelta(days=7),
EndTime=datetime.utcnow()
)
# Prophet 모델로 향후 2시간 예측
df = pd.DataFrame({
'ds': [d['Timestamp'] for d in metrics['MetricDataResults'][0]['Timestamps']],
'y': [d for d in metrics['MetricDataResults'][0]['Values']]
})
model = Prophet(changepoint_prior_scale=0.05)
model.fit(df)
future = model.make_future_dataframe(periods=24, freq='5min')
forecast = model.predict(future)
# 병목 예측: 레이턴시가 평소 대비 2배 이상 증가 예상
baseline = df['y'].mean()
predicted_peak = forecast['yhat'].iloc[-1]
if predicted_peak > baseline * 2:
return {
'bottleneck_risk': 'HIGH',
'predicted_latency_ms': predicted_peak,
'baseline_latency_ms': baseline,
'action': 'consider_network_policy_optimization'
}
return {'bottleneck_risk': 'LOW'}
2. Cross-AZ 트래픽 추이 → 비용 최적화 예측
# Cross-AZ 네트워크 트래픽 비용 추적
sum(rate(pod_network_tx_bytes{
source_az!="", dest_az!="",
source_az!=dest_az
}[5m])) by (source_az, dest_az)
* 0.01 / 1024 / 1024 / 1024 # $0.01/GB
비용 최적화 전략:
- 토폴로지 인식 스케줄링: Kubernetes Topology Aware Hints를 활용하여 동일 AZ 내 통신 선호
- 서비스 메시 최적화: Istio locality load balancing으로 Cross-AZ 트래픽 최소화
- 예측 기반 배치: ML 모델이 통신 패턴을 학습하여 최적 AZ 배치 제안
# Topology Aware Hints 활성화
apiVersion: v1
kind: Service
metadata:
name: ml-inference-service
annotations:
service.kubernetes.io/topology-mode: Auto
spec:
selector:
app: ml-inference
ports:
- port: 8080
type: ClusterIP
ML 추론 워크로 드 성능 예측
1. Ray, vLLM, Triton, PyTorch 워크로드 네트워크 성능 모니터링
# vLLM 추론 서비스 네트워크 모니터링
apiVersion: v1
kind: ConfigMap
metadata:
name: vllm-network-monitoring
data:
metrics.yaml: |
# Container Network Observability 메트릭
metrics:
- pod_network_rx_bytes
- pod_network_tx_bytes
- pod_network_rx_latency_ms
- pod_network_rx_errors_total
# 추가 커스텀 메트릭
custom_metrics:
- name: vllm_inference_network_throughput_mbps
query: |
sum(rate(pod_network_rx_bytes{app="vllm-inference"}[1m]))
/ 1024 / 1024
- name: vllm_model_load_network_time_ms
query: |
histogram_quantile(0.99,
rate(pod_network_rx_latency_bucket{
app="vllm-inference",
operation="model_load"
}[5m])
)
Ray 분산 추론 네트워크 패턴:
# Ray 클러스터의 네트워크 병목 감지
import ray
from ray import serve
@serve.deployment
class LLMInferenceDeployment:
def __init__(self):
self.model = load_model()
self.network_monitor = NetworkMonitor()
async def __call__(self, request):
# 네트워크 지연 추적
start_time = time.time()
# Ray의 분산 추론 호출
result = await self.model.generate(request.prompt)
network_latency = time.time() - start_time
# CloudWatch에 커스텀 메트릭 전송
self.network_monitor.record_latency(network_latency)
# 네트워크 병목 감지 시 스케일 아웃 트리거
if network_latency > 200: # 200ms 이상
trigger_scale_out()
return result
2. 추론 레이턴시 → 스케일 아웃 트리거 예측
# ML 추론 레이턴시 기반 예측 스케일링
def predict_inference_scaling(service_name, forecast_hours=2):
"""
추론 레이턴시 패턴을 학습하여 스케일 아웃 필요 시점을 예측합니 다.
"""
# 지난 7일간 추론 레이턴시 데이터 수집
latency_data = fetch_inference_latency_from_cloudwatch(
service_name=service_name,
days=7
)
# 추론 요청 수 데이터 수집
request_volume = fetch_request_volume(service_name, days=7)
# 레이턴시와 요청 수의 상관관계 분석
df = pd.DataFrame({
'timestamp': latency_data['timestamps'],
'latency_p99': latency_data['p99'],
'request_rate': request_volume['rate']
})
# 임계값 계산: P99 레이턴시 > 500ms 시점의 요청 수
threshold_requests = df[df['latency_p99'] > 500]['request_rate'].min()
# Prophet으로 향후 요청 수 예측
prophet_df = df[['timestamp', 'request_rate']].rename(
columns={'timestamp': 'ds', 'request_rate': 'y'}
)
model = Prophet()
model.fit(prophet_df)
future = model.make_future_dataframe(
periods=forecast_hours * 12, # 5분 간격
freq='5min'
)
forecast = model.predict(future)
# 스케일 아웃 필요 시점 예측
scale_out_needed = forecast[
forecast['yhat'] > threshold_requests
]['ds'].min()
if pd.notna(scale_out_needed):
# 예측된 시간 30분 전에 선제적 스케일 아웃
preemptive_time = scale_out_needed - timedelta(minutes=30)
return {
'scale_out_recommended': True,
'recommended_time': preemptive_time,
'predicted_request_rate': forecast.iloc[-1]['yhat'],
'threshold': threshold_requests,
'current_replicas': get_current_replicas(service_name),
'recommended_replicas': calculate_required_replicas(
forecast.iloc[-1]['yhat'],
threshold_requests
)
}
return {'scale_out_recommended': False}
3. GPU 사용률 + 네트워크 대역폭 상관관계 분석
# GPU 사용률과 네트워크 대역폭의 상관관계
# (NVIDIA DCGM Exporter 메트릭 + Container Network Observability)
# GPU 사용률
DCGM_FI_DEV_GPU_UTIL{
namespace="ml-inference",
pod=~"vllm-.*"
}
# 동시 네트워크 수신 대역폭
sum(rate(pod_network_rx_bytes{
namespace="ml-inference",
pod=~"vllm-.*"
}[1m])) by (pod)
# 상관관계 분석: GPU 사용률 < 50% && 네트워크 대역폭 > 100MB/s
# → 네트워크 병목이 GPU 활용도를 저해하고 있음
최적화 전략:
# 네트워크 병목 해소: Enhanced Networking 및 ENA Express 활성화
apiVersion: karpenter.sh/v1
kind: NodePool
metadata:
name: ml-inference-pool
spec:
template:
spec:
requirements:
- key: karpenter.k8s.aws/instance-family
operator: In
values: ["p5", "p4d"] # 최신 GPU 인스턴스 (ENA Express 지원)
- key: karpenter.k8s.aws/instance-size
operator: In
values: ["24xlarge", "48xlarge"]
nodeClassRef:
name: ml-inference-class
---
apiVersion: karpenter.k8s.aws/v1
kind: EC2NodeClass
metadata:
name: ml-inference-class
spec:
amiSelectorTerms:
- alias: al2023@latest
userData: |
#!/bin/bash
# ENA Express 활성화 (100Gbps 네트워크 성능)
ethtool -K eth0 ena-express on
# TCP BBR congestion control (높은 대역폭 최적화)
echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf
sysctl -p