주제: 오토스케일링(HPA/KEDA), 롤아웃, Mesh, PDB, 비용 최적화
- 스케일링 삼총사: HPA(v2) + KEDA(이벤트/큐) + Cluster Autoscaler/Karpenter(노드)
- 안정성: PDB + Readiness/StartupProbe + PodPriority/Preemption + TopologySpread
- 롤아웃: Argo Rollouts(카나리/블루그린) + 자동 분석(p95/에러율)
- 메시(선택): Istio/Linkerd로 mTLS, 재시도, 타임아웃, 아웃라이어 제거
- 비용: 요청값 현실화(관측 기반), 온디맨드+스팟 혼합, ARM(Graviton) 풀, 이미지 슬림화
1) 리소스·프로브·QoS — “죽지 않고 잘 돈다”의 기본
요청/한도(Req/Lmt) 규칙
- vCPU 요청= p95 사용량(관측치) ± 여유 15~25%
- 메모리 요청= p95 (OOM 방지), 한도는 요청=한도 또는 한도 미설정(스로틀링 회피)
resources:
  requests: { cpu: "200m", memory: "256Mi" }
  limits:   { cpu: "500m", memory: "256Mi" }  # 메모리는 equal 권장
프로브
livenessProbe:  { httpGet: { path: /healthz, port: 8000 }, periodSeconds: 10 }
readinessProbe: { httpGet: { path: /readyz,  port: 8000 }, periodSeconds: 5, timeoutSeconds: 2 }
startupProbe:   { httpGet: { path: /healthz, port: 8000 }, failureThreshold: 30, periodSeconds: 5 }
QoS 클래스
- Guaranteed(요청=한도, 메모리 동일) → OOM에 가장 강함
- Burstable(일반) / BestEffort(지양)
2) HPA v2 (CPU/메모리/커스텀 메트릭)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
spec:
  minReplicas: 2
  maxReplicas: 20
  behavior:
    scaleUp:
      stabilizationWindowSeconds: 30
      policies: [{ type: Percent, value: 100, periodSeconds: 60 }]
    scaleDown:
      stabilizationWindowSeconds: 300
      policies: [{ type: Percent, value: 50, periodSeconds: 60 }]
  metrics:
  - type: Resource
    resource: { name: cpu, target: { type: Utilization, averageUtilization: 60 } }
  - type: Resource
    resource: { name: memory, target: { type: AverageValue, averageValue: "400Mi" } }
  # 커스텀 메트릭 예: QPS
  - type: Pods
    pods:
      metric:
        name: http_requests_per_second
      target:
        type: AverageValue
        averageValue: "20"
팁: Prometheus Adapter로 커스텀 메트릭(예: 요청/큐 길이) 노출.
3) KEDA — 이벤트 기반 스케일(큐/스트림/웹훅)
SQS 예:
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
spec:
  scaleTargetRef: { name: worker }
  pollingInterval: 10
  cooldownPeriod: 120
  minReplicaCount: 0
  maxReplicaCount: 50
  triggers:
  - type: aws-sqs-queue
    metadata:
      queueURL: https://sqs.ap-northeast-2.amazonaws.com/123456789012/ex.fifo
      queueLength: "100"
      awsRegion: ap-northeast-2
Kafka 랙 기준:
- type: kafka
  metadata:
    bootstrapServers: kafka:9092
    consumerGroup: ex-worker
    topic: user.created
    lagThreshold: "1000"
4) 노드 오토스케일: Cluster Autoscaler vs. Karpenter
- Cluster Autoscaler(CA): 전통적, 안정. 노드그룹 단위 증감
- Karpenter: 빠른 프로비저닝, 스팟 혼합/인스턴스타입 다양화 쉬움
- 프로비저닝 템플릿에서 requirements로 x86/ARM,on-demand/spot혼합
 
- 프로비저닝 템플릿에서 
예시(개념):
apiVersion: karpenter.sh/v1beta1
kind: NodePool
spec:
  template:
    spec:
      requirements:
      - key: kubernetes.io/arch
        operator: In
        values: ["arm64","amd64"]
      - key: karpenter.sh/capacity-type
        operator: In
        values: ["on-demand","spot"]
      taints: [{ key: "spot", value: "true", effect: "NoSchedule" }]
5) 중단 내성: PDB, PodPriority, TopologySpread
PodDisruptionBudget(PDB)
apiVersion: policy/v1
kind: PodDisruptionBudget
spec:
  minAvailable: 2     # 또는 maxUnavailable: 1
  selector: { matchLabels: { app: api } }
우선순위/선점
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata: { name: critical-svc }
value: 100000
globalDefault: false
spec:
  priorityClassName: critical-svc
토폴로지 분산
topologySpreadConstraints:
- maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: ScheduleAnyway
  labelSelector: { matchLabels: { app: api } }
6) 롤아웃: Argo Rollouts(요지)
카나리 + 자동 분석(9편 참고)을 prod 기본값으로:
strategy:
  canary:
    canaryService: api-canary
    stableService: api
    trafficRouting:
      istio: { virtualService: { name: api-vs, routes: ["primary"] } }
    steps:
    - setWeight: 10
    - pause: { duration: 2m }
    - analysis: { templates: [{ templateName: apislo }] }
    - setWeight: 50
    - pause: { duration: 3m }
    - analysis: { templates: [{ templateName: apislo }] }
    - setWeight: 100
7) 서비스 메시(옵션이지만 강력)
Istio/Linkerd 핵심 설정(게이트웨이와 중복 조정):
- mTLS: 서비스간 암호화/신뢰
- 재시도/타임아웃: 멱등 GET만 재시도, 쓰기는 금지
- Outlier Detection: 불량 인스턴스 자동 제외
Istio VirtualService 예:
spec:
  http:
  - route:
    - destination: { host: api.default.svc.cluster.local, subset: v1, weight: 90 }
    - destination: { host: api.default.svc.cluster.local, subset: v2, weight: 10 }
    retries: { attempts: 2, perTryTimeout: 1s, retryOn: "5xx,connect-failure,refused-stream" }
    timeout: 5s
8) 스토리지/네트워킹 운영 팁
- PVC: IOPS/처리량 계층 인지(General SSD vs. io2 등). 로그/캐시는 디스크 의존 최소화
- 네트워크: ENI/Pod IP 고갈 주의, 노드당 최대 파드 수 확인
- Ingress: NLB(4계층) vs ALB(7계층) 장단점 파악, gRPC면 NLB+Envoy가 단순
9) 비용 최적화 플레이북
- 요청값 다운: 관측 기반으로 p95 맞추기(과도한 여유분 제거)
- 스팟 혼합: 워커/비핵심은 스팟+PDB+재시도/큐로 내성 확보
- ARM 전환: CPU 요금↓, Python/Node 호환 OK(이미지 멀티아치)
- 오토스케일 정책: scaleDown 빠르게(안정화창 5~10분), 워커는 0까지
- 이미지 다이어트: python:slim/node:alpine, readOnlyRootFS → 디스크 IO↓
- 로깅 비용: 샘플링/드롭(헬스체크, 디버그), 보존 기간 차등
10) 장애 런북(요지)
- CPU Throttle: container_cpu_cfs_throttled_seconds_total↑ → 한도 제거/상향, 코드 핫스팟
- OOMKill: oom_killed=1→ 메모리 한도=요청, 누수/캐시 튜닝, 이미지 최적화
- Evicted(디스크/노드압박): 노드 디스크/인노드/메모리 확인 → 노드 확장, 로그/캐시 정책 수정
- PodPending: 자원부족/스케줄러 조건 → 요청값↓, 우선순위/토폴로지 조정, 노드 증설
- Cold Start(Edge/Node 혼합): 런타임 분리, startupProbe완화, 롤링 Surge 증가
11) 48시간 액션 플랜
- 상위 3개 워크로드에 HPA v2 도입(behavior 포함)
- 워커에 KEDA 적용(SQS/Kafka 트리거) + minReplicaCount: 0
- PDB + TopologySpread 적용으로 배포/장애 내성 확보
- PriorityClass 생성해 핵심/비핵심 분리, 스팟 전용 노드 풀에 taint 부여
- 프로브/리소스 요청 재설정(p95 기반), OOM/Throttle 대시보드 구성
12) 2주 액션 플랜
- Karpenter(또는 CA)로 스팟 혼합·다양 인스턴스 자동화
- Argo Rollouts 전면 적용 + 분석 템플릿(p95/에러율) 표준화
- 메시(또는 게이트웨이)로 재시도/타임아웃/아웃라이어 정책 일원화
- ARM 노드 풀 PoC 및 멀티아치 이미지 파이프라인 추가
- 비용 리포트(월별) 자동 생성: 노드 타입/네임스페이스/워크로드별 분해
13) “복붙” 모음
A. Prometheus Adapter(커스텀 메트릭 선언)
rules:
- seriesQuery: 'http_requests_total{namespace!="",pod!=""}'
  resources: { overrides: { namespace: { resource: "namespace" }, pod: { resource: "pod" } } }
  name: { matches: "http_requests_total", as: "http_requests_per_second" }
  metricsQuery: 'sum(rate(http_requests_total{<<.LabelMatchers>>}[1m])) by (<<.GroupBy>>)'
B. 워커 배포 with KEDA + PDB
apiVersion: apps/v1
kind: Deployment
metadata: { name: worker }
spec:
  replicas: 0
  selector: { matchLabels: { app: worker } }
  template:
    metadata: { labels: { app: worker } }
    spec:
      tolerations: [{ key: "spot", operator: "Equal", value: "true", effect: "NoSchedule" }]
      containers:
      - name: worker
        image: ghcr.io/org/repo/worker:main
        resources: { requests: { cpu: "50m", memory: "128Mi" }, limits: { cpu: "1", memory: "256Mi" } }
---
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata: { name: worker-pdb }
spec:
  maxUnavailable: 1
  selector: { matchLabels: { app: worker } }
C. Descheduler(노드 균형·비용) 기본
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: descheduler
        args: ["--policy-config-file=/policy.yaml","--descheduling-interval=10m"]
마무리
쿠버네티스 운영의 핵심은 **“스케일·내성·비용”**의 균형입니다.
HPA/KEDA/노드 오토스케일을 맞물리게 하고, PDB/프로브/토폴로지로 안전한 롤링을 보장하며, 관측 데이터로 요청값을 주기적으로 다이어트하세요.
다음은 11편. 보안·컴플라이언스 — 비밀관리, 암호화, PII, ISMS-P/개인정보보호법 대응으로 이어갈게요.