EKS Observability

Resource Optimization

Junseok Oh

Sr. Solutions Architect

Amazon Web Services

Vertical Pod Autoscaler & Auto Mode

VPA와 Auto Mode의 시너지 효과

VPA

  • Pod CPU/Memory 사용량 관찰
  • requests 추천 (limits는 기존 비율 유지)
  • Recreate 또는 InPlaceOrRecreate로 적용
  • CPU: 24h 반감기, Memory: 일별 피크 8일 (기본값)
VPA 최적화된 requests
Auto Mode가 노드 정리 판단

Auto Mode

  • Pod requests 합계로 노드 선택
  • NodePool 조건 안에서 인스턴스 매칭
  • requests가 줄면 노드에 빈자리 발생
  • Consolidation이 삭제 또는 교체 판단
⚙

VPA

Pod의 CPU/Memory requests를 사용량에 맞게 조정

⚡

Auto Mode

줄어든 requests로 빈 노드를 정리 (EKS 1.37 신규 풀은 Balanced 기본)

✔

주의

같은 CPU/Memory 메트릭으로 HPA와 함께 쓰지 않기

📖 더 알아보기: VPA Pod Resize 가이드

VPA 모드 비교

updateMode별 동작 방식과 권장 사용 사례

Off 모드

추천값만 제공하고, Pod를 변경하지 않습니다. 가장 안전한 분석 모드입니다.

장점

Pod 재시작 없음, 안전하게 분석 가능, 프로덕션에서 먼저 테스트

단점

자동 적용되지 않음, 수동 업데이트 필요

권장 사용 사례

신규 워크로드 분석, 프로덕션 사전 검증, 리소스 패턴 파악

YAMLapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-app-vpa spec: targetRef: apiVersion: apps/v1 kind: Deployment name: my-app updatePolicy: updateMode: "Off"

Initial 모드

Pod 생성 시에만 추천값을 적용하고, 실행 중인 Pod는 변경하지 않습니다.

장점

실행 중 Pod 안정성 보장, 롤링 업데이트 시 자연스럽게 적용

단점

즉시 적용되지 않음, 새 Pod 생성까지 대기 필요

권장 사용 사례

Stateful 워크로드, 긴 실행 배치 작업, 재시작에 민감한 서비스

YAMLapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-app-vpa spec: targetRef: apiVersion: apps/v1 kind: Deployment name: my-app updatePolicy: updateMode: "Initial"

Recreate 모드

추천값과 차이가 크면 Updater가 Pod를 evict하고, Admission Controller가 새 Pod에 추천값을 넣습니다. VPA 1.5부터 기본 모드입니다.

장점

모든 Kubernetes 버전에서 동작, 동작이 예측 가능

단점

Pod 재시작 발생, PDB와 레플리카 2개 이상 필요

권장 사용 사례

Stateless 워크로드, 개발/스테이징 환경, 다중 레플리카 서비스

YAMLapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-app-vpa spec: targetRef: apiVersion: apps/v1 kind: Deployment name: my-app updatePolicy: updateMode: "Recreate"

InPlaceOrRecreate 모드 (VPA 1.6 GA)

Pod를 재시작하지 않고 resize subresource로 requests를 바꿉니다. 노드에 자리가 없는 등 in-place가 불가능하면 evict로 전환합니다.

장점

재시작 없이 조정, Kubernetes 1.35부터 in-place resize GA

단점

QoS class는 바꿀 수 없음, 노드 여유가 없으면 결국 evict

권장 사용 사례

재시작 비용이 큰 서비스, EKS 1.35 이상 클러스터. evict 없는 InPlace 모드는 VPA 1.8에서도 alpha

YAMLapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-app-vpa spec: targetRef: apiVersion: apps/v1 kind: Deployment name: my-app updatePolicy: updateMode: "InPlaceOrRecreate"

Auto 모드

VPA 1.5부터 deprecated이며 현재 Recreate와 같게 동작합니다. 향후 API 버전에서 제거될 예정이므로 Recreate 또는 InPlaceOrRecreate를 명시합니다.

장점

기존 매니페스트와 호환

단점

Deprecated, 의미가 바뀔 수 있음, Pod 재시작 발생

권장 사용 사례

신규 설정에는 사용하지 않음. 기존 Auto 설정은 명시적 모드로 전환

YAMLapiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: my-app-vpa spec: targetRef: apiVersion: apps/v1 kind: Deployment name: my-app updatePolicy: updateMode: "Auto"

VPA 추천값 시뮬레이터

리소스 사용량 기반 VPA 추천값 시각화

1000m
2Gi
300m
512Mi
예상 리소스 절감률
68%
# VPA Recommendation Status recommendation: containerRecommendations: - containerName: app target: cpu: "345m" memory: "589Mi" lowerBound: cpu: "173m" memory: "353Mi" upperBound: cpu: "863m" memory: "1178Mi" # Savings: CPU 66% | Mem 71%

VPA + Auto Mode 연동 패턴

리소스 최적화에서 노드 비용 절감까지의 자동화 흐름

1

VPA 리소스 모니터링

CPU 24h 반감기 histogram, Memory 일별 피크 8일

2

추천값 생성

target = P90 × 1.15: CPU 300m, Memory 512Mi

3

Pod Requests 업데이트

InPlaceOrRecreate: 먼저 in-place, 불가하면 evict

4

노드에 빈자리 발생

노드는 그대로이고 requests 합계만 줄어듦

5

Consolidation 판단

빈 노드 삭제 또는 더 저렴한 노드로 교체

6

결과 확인

노드 수, Pod 재시작, 비용을 함께 측정

▶ Play를 눌러 VPA 흐름을 확인하세요

리소스 요청 최적화 전략

QoS Class와 Request/Limit 설정 가이드

CPU Settings

500m
1000m

Memory Settings

512Mi
512Mi

Guaranteed

request == limit

Burstable

request < limit

BestEffort

no request/limit

Production Best Practices

  • CPU: request만 설정, limit 없음 - Burstable로 CPU throttling 방지
  • Memory: request == limit, 다른 Pod의 메모리 압박으로 인한 eviction 위험 감소
  • 권장 패턴: CPU request only + Memory request == limit (Pod QoS는 Burstable)
Recommended Patternresources: requests: cpu: "500m" # CPU request only memory: "512Mi" # Memory request == limit limits: # cpu: (no limit) # Allows bursting memory: "512Mi" # Same as request
현재 설정: CPU request만, Memory request == limit: 권장 패턴입니다 (Pod QoS는 Burstable).
📖 더 알아보기: 리소스 최적화 가이드

비용 절감 계산 예시 (Before/After)

가정: us-east-1 On-Demand, 730시간/월, 사용량 불변, Spot 미반영. 실제 고객 결과가 아닙니다

✖ Before (최적화 전)

Nodes 20개 m5.xlarge (80 vCPU, 320GiB)
CPU 활용률 25%
Memory 활용률 30%
월 비용
$2,803

✔ After (최적화 후)

Nodes 8개 m6g.xlarge (32 vCPU, 128GiB)
CPU 활용률 63%
Memory 활용률 75%
월 비용
$899

예시 절감률

68%
requests 적정화
노드 20 → 8
Graviton 단가
$0.192 → $0.154/h
Spot
이 예시에 미반영
측정할 것
재시작, Pending, 지연

HPA: Horizontal Pod Autoscaler

CPU, Memory, Custom Metrics 기반 수평 확장

# HorizontalPodAutoscaler (autoscaling/v2) spec: scaleTargetRef: { name: my-app } minReplicas: 2 / maxReplicas: 20 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 70 # CPU 70% - type: Resource resource: name: memory target: type: Utilization averageUtilization: 80 # Memory 80% behavior: scaleDown: { stabilizationWindowSeconds: 300 } scaleUp: { stabilizationWindowSeconds: 30 }
# Prometheus Adapter 설치 필요 # helm install prometheus-adapter prometheus-community/prometheus-adapter apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: my-app-rps-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: my-app minReplicas: 2 maxReplicas: 20 metrics: - type: Pods pods: metric: name: http_requests_per_second target: type: AverageValue averageValue: 100 # Pod당 100 RPS - type: External external: metric: name: sqs_queue_length target: type: AverageValue averageValue: 50

HPA 한계점

  • minReplicas ≥ 1: 기본적으로 Scale-to-Zero 불가 (HPAScaleToZero는 alpha feature gate)
  • Custom Metrics: Prometheus Adapter 별도 설치, 관리 필요
  • AWS 통합: SQS, MSK 등은 External metrics adapter 별도 필요
  • PromQL 직접 사용 불가: Adapter 규칙으로 변환해야 해서 복잡도 증가
  • 대상당 HPA 1개: 같은 Deployment에 HPA를 여러 개 두면 서로 충돌 (KEDA는 ScaledObject 하나에 trigger 여러 개)
KEDA가 해결하는 것: HPA를 직접 생성, 관리하면서 70개 이상의 스케일러를 지원하고 Scale-to-Zero까지 가능하게 합니다.

HPA 동작 흐름

Metrics Server / Prometheus Adapter
메트릭 수집 & API 제공
↓ 15초마다 조회
HPA Controller
현재값 vs 목표값 비교
↓ replicas 계산
Deployment
desiredReplicas = ceil(currentReplicas × currentValue / targetValue)
Resource
CPU / Memory
기본 내장
Custom
Pods / External
Adapter 필요

KEDA: Event-Driven Autoscaling

HPA를 넘어서: 이벤트 기반 스케일링과 Scale-to-Zero

Event Sources
SQS / MSK / Prometheus
→
KEDA
ScaledObject
→
HPA
자동 생성/관리
→
Deployment
0 ~ N Replicas
항목HPA (기본)KEDA
메트릭 소스CPU / Memory만70+ 스케일러 (SQS, Kafka, Prometheus 등)
최소 레플리카min: 1 (기본)min: 0 (Scale-to-Zero → 비용 절감)
설정 방식HPA 리소스 직접 관리ScaledObject → HPA 자동 생성/관리
Prometheus 연동Prometheus Adapter 필요네이티브 PromQL 지원
AWS 통합CloudWatch Adapter 별도 설치SQS, Kafka(MSK IAM 포함), CloudWatch 스케일러 내장
🔄
Scale-to-Zero

트래픽 없을 때 0으로 축소, 비용 절감

🔌
70+ Scalers

AWS, GCP, Azure, Kafka, Redis 등

📊
PromQL Native

기존 Prometheus 인프라 재활용

⚙️
CRD 기반

GitOps 친화적 선언형 관리

KEDA v2.21 (2026-09-23)의 테스트 범위는 Kubernetes 1.34 ~ 1.36입니다. EKS 1.37 클러스터는 공식 테스트 범위 밖이므로 스테이징에서 먼저 검증합니다. KEDA는 EKS add-on이 아니며 Helm으로 설치합니다.

📖 더 알아보기: KEDA 실전 가이드

AWS 메트릭 기반 스케일링

SQS Queue Depth / MSK Consumer Lag / ALB Request Count

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: sqs-consumer-scaler
spec:
  scaleTargetRef:
    name: sqs-consumer
  minReplicaCount: 0  # Scale-to-Zero!
  maxReplicaCount: 20
  triggers:
  - type: aws-sqs-queue
    authenticationRef:
      name: keda-aws-credentials
    metadata:
      queueURL: https://sqs.ap-northeast-2...
      queueLength: "5"  # 메시지 5개당 1 Pod
      awsRegion: ap-northeast-2

🎯 SQS 네이티브 스케일러

  • aws-sqs-queue: Prometheus 불필요
  • queueLength: "5": 메시지 5개당 Pod 1개
  • Scale-to-Zero: 큐 비어있으면 Pod 0
  • IRSA 기반 인증 (TriggerAuthentication, podIdentity.provider: aws)
💡 IRSA 설정 필수: TriggerAuthentication의 podIdentity.provider: aws로 SQS 조회 권한 부여. aws-eks는 deprecated
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: msk-consumer-scaler
spec:
  scaleTargetRef:
    name: kafka-consumer
  minReplicaCount: 1
  maxReplicaCount: 30
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      query: |
        sum(kafka_consumergroup_lag{
          group="my-consumer",
          topic="orders"
        })
      threshold: "1000"  # Lag 1000당 1 Pod

📊 Prometheus 스케일러 + MSK

  • prometheus 스케일러로 Consumer Lag 모니터링
  • kafka_consumergroup_lag 메트릭 활용
  • threshold: "1000": Lag 1000당 Pod 1개
  • 대안: kafka 스케일러 + sasl: aws_msk_iam (KEDA에 aws-msk 타입은 없음)
⚠️ Scale-to-Zero 주의: 0에서 다시 뜰 때 consumer group rebalance와 첫 처리 지연이 생깁니다. 지연에 민감하면 minReplicaCount: 1을 유지합니다
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: alb-scaler
spec:
  scaleTargetRef:
    name: web-app
  minReplicaCount: 2
  maxReplicaCount: 50
  triggers:
  - type: aws-cloudwatch
    authenticationRef:
      name: keda-aws-credentials
    metadata:
      namespace: AWS/ApplicationELB
      dimensionName: TargetGroup
      dimensionValue: targetgroup/my-tg/...
      metricName: RequestCountPerTarget
      targetMetricValue: "100"  # Pod당 100 req
      metricStatPeriod: "60"

☁️ CloudWatch 직접 쿼리

  • aws-cloudwatch 스케일러: Prometheus 불필요
  • RequestCountPerTarget 메트릭
  • TargetGroup 단위 세밀한 제어
  • IRSA로 CloudWatch 조회 권한 (cloudwatch:GetMetricData)
💡 ALB + HPA 대비 장점: CloudWatch 네이티브 쿼리로 Adapter 오버헤드 제거, 정확도 향상
📖 더 알아보기: KEDA 실전 가이드 — SQS, MSK, ALB 스케일러

Istio Gateway RPS 기반 스케일링

PromQL + KEDA로 Istio 메트릭 기반 자동 스케일링

apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: istio-rps-scaler
spec:
  scaleTargetRef:
    name: my-app
  minReplicaCount: 0
  maxReplicaCount: 10
  cooldownPeriod: 120
  triggers:
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      query: |
        sum(rate(istio_requests_total{
          destination_service=~"my-app.*"
        }[1m]))
      threshold: "50"  # Pod당 50 RPS
🔴 Error Rate

5xx > 5% → 즉시 스케일아웃

⏱ Latency P99

P99 > 500ms → Pod 추가

🔌 Circuit Breaker

outlierDetection 연동

⏰ Cron + RPS

피크타임 사전 확보

100
📖 더 알아보기: KEDA Istio 연동 & PromQL 스케일링

Best Practices 체크리스트

리소스 최적화를 위한 운영 가이드

VPA 설정

  • VPA를 Off 모드로 먼저 분석 (메모리 기본 창 8일 이상)
  • 핵심 워크로드부터 VPA 적용
  • CPU는 request만, Memory는 request=limit
  • 적용은 Recreate 또는 InPlaceOrRecreate 명시 (Auto 사용 안 함)

NodePool 전략

  • NodePool 분리: 웹/배치/GPU
  • Graviton 인스턴스 허용 (arm64)
  • Spot 혼합 전략 (Stateless 워크로드)
  • Pod Priority로 중요 워크로드 보호

KEDA 스케일링

  • TriggerAuthentication podIdentity.provider: aws 구성
  • cooldownPeriod로 스케일링 진동 방지
  • fallback 설정으로 메트릭 장애 대비
  • CPU/Memory는 VPA와 HPA 중 하나만 사용

비용 & 모니터링

  • 정기적 비용 리뷰 (월 1회)
  • Cost Allocation Tags 적용
  • VPA 추천값 대시보드 구성
  • 노드 활용률 알림 설정
📖 더 알아보기: Auto Mode 리소스 최적화

추가 학습 리소스

심화 학습 참고 자료, 2026-10-15 버전 검토와 공식 출처

전체 과정 요약

Key Takeaways

BLOCK 01

EKS Auto Mode 내부 아키텍처

Auto Mode는 AWS가 관리하는 Karpenter 기반 노드 관리. NodePool과 NodeClass로 제어하고, 직접 설치한 Karpenter(v1.15.0)와 API와 운영 책임이 다릅니다.

BLOCK 02

노드 라이프사이클 모니터링

Pod, 노드, 이벤트 순서로 진단. Spot 회수 대응, expireAfter와 Disruption Budget으로 Day-2 운영 안정화.

BLOCK 03

3-Signal Correlation

Exemplars, Derived Fields, tracesToLogsV2로 Logs, Metrics, Traces 상관분석. 근본 원인 분석 가속화.

BLOCK 04

VPA + KEDA + Auto Mode 최적화

VPA(InPlaceOrRecreate)로 requests 조정, KEDA로 이벤트 기반 스케일링, Auto Mode Consolidation으로 빈 노드 정리.

Q&A

질문과 답변

오늘 교육이 도움이 되셨나요?

피드백은 더 나은 콘텐츠를 만드는 데 큰 힘이 됩니다.

Session: EKS Auto Mode & Karpenter 운영 (2 Hours)

Thank You

Block 4: VPA, KEDA, 리소스 최적화 완료

수고하셨습니다! 🎉

← 목차로 돌아가기