본문 바로가기
K8S

kubernetes의 Request

by Rainbound-IT 2025. 12. 23.
반응형

― startup peak, steady-state, HPA 사이에서의 현실적인 해답

Kubernetes(EKS)를 운영하다 보면 거의 반드시 부딪히는 질문이 있다.

“request는 평소 사용량 기준으로 잡는 게 맞지 않나?”
“그런데 그렇게 하면 startup 시에 Pod가 안 뜨는 것 같은데?”
“그럼 request는 HPA용 수단 말고 무슨 의미가 있지?”

이 글은 resources.requests의 진짜 역할,
startup peak 때문에 발생하는 오해,
그리고 startup peak를 request에 포함하지 않고도 안전하게 운영하는 구조
운영 경험 관점에서 하나로 정리한다.


1. request에 대한 가장 흔한 오해

많은 사람들이 처음에 이렇게 이해한다.

“request는 초기 요청량이고,
이걸 초과하면 Pod가 실행이 안 되는 기준이다”

하지만 이건 틀린 이해다.

정확한 정의부터 다시 잡자

  • request
    • 스케줄러에게 주는 신호
    • “이 Pod는 최소 이만큼의 자원을 항상 보장받아야 한다
  • limit
    • 런타임에서의 상한선
    • CPU → throttling
    • Memory → OOMKill

👉 request를 초과해도 Pod는 실행된다
👉 Pod를 죽이는 기준은 limit이다


2. Pod가 “안 뜨는 것처럼 보이는” 진짜 이유

운영에서 자주 겪는 현상은 이렇다.

  • request를 평소 사용량 기준으로 낮게 잡음
  • 배포하거나 scale-out 시
  • Pod가 안 뜨는 것처럼 보임

이때 대부분 원인은 request가 아니다.

(1) Memory startup spike → OOMKill

  • 앱(JVM, Node, Python 등)이 시작 시 메모리를 크게 사용
  • memory limit을 넘는 순간 즉시 OOMKill
  • 결과: CrashLoopBackOff
  • 체감: “Pod가 실행이 안 된다”

👉 실제 원인: limit 부족


(2) CPU startup spike + CPU limit → throttling

  • startup 시 CPU가 많이 필요
  • CPU limit이 낮으면 severe throttling 발생
  • 초기화 지연 → readiness probe 실패
  • 결과: 서비스에서 트래픽을 못 받음

👉 실제 원인: CPU limit + probe 설계


3. request는 평소 사용량 기준으로 잡는 게 맞는가?

개념적으로는 맞다.

request는 원래:

  • steady-state(안정 상태)
  • 평소 트래픽
  • 평균 또는 p50~p80 사용량

을 기준으로 잡는 것이 합리적이다.

문제는 Kubernetes가 요구하는 “평소”의 범위가 우리가 생각하는 것보다 넓다는 데 있다.


4. Kubernetes가 기대하는 “항상”의 의미

Kubernetes에서 request는 다음 상황에서도 충족되길 기대한다.

  • Pod 최초 생성
  • 롤링 업데이트
  • 노드 재시작
  • Spot interruption 이후 재기동
  • HPA scale-out

👉 즉, 여러 Pod가 동시에 startup 상태가 되는 순간까지 포함된다.

그래서 단순 평균 기준 request는
운영 이벤트 순간에 깨지기 쉽다.


5. request를 startup peak까지 포함하면 왜 문제가 되나

  • steady 평균: 200Mi
  • startup peak: 600Mi
  • request = 600Mi

이렇게 잡으면:

  • 평소엔 400Mi가 항상 놀고 있음
  • 노드 밀도 ↓
  • 비용 ↑

👉 이건 기술적 문제라기보다 운영 비용과 효율 문제다.

그래서 질문이 생긴다.

“startup peak를 request에 포함하지 않고도
안전하게 운영할 수는 없을까?”


6. 정답: startup peak를 다른 메커니즘으로 흡수한다

성숙한 Kubernetes 운영에서는
startup peak를 request로 해결하지 않는다.

아래 구조들을 조합한다.


7. 안전한 운영을 위한 핵심 구조들

① startupProbe로 “느린 시작”을 허용한다

startup이 느린데 liveness/readiness만 쓰면

  • 초기 CPU throttling
  • GC
  • 캐시 로딩

때문에 불필요한 재시작이 발생한다.

startupProbe를 사용하면

  • startup 동안은 죽이지 않음
  • request를 평소 기준으로 유지 가능

② CPU limit을 제거하거나 충분히 높게 둔다

CPU는 memory와 다르다.

  • CPU limit은 “보호 장치”가 아니라
  • startup에서는 장애 유발 장치가 되는 경우가 많다

실무에서는:

  • CPU request는 설정
  • CPU limit은 제거 or 크게 설정
  • HPA로 scale 대응

하는 패턴이 매우 흔하다.


③ Memory는 request와 limit의 역할을 명확히 분리한다

  • memory request
    • steady-state 기준 (p50~p90)
  • memory limit
    • startup peak + 여유

메모리 spike를 request로 해결하려 하면
무조건 낭비가 커진다.


④ initContainer / warmup 분리

startup에만 필요한 무거운 작업이 있다면:

  • 캐시 생성
  • 데이터 preload
  • 모델 로딩
  • 마이그레이션

이를 initContainer나 별도 Job으로 분리하면

  • 본 컨테이너의 startup peak 자체를 줄일 수 있다
  • request를 평소 기준으로 잡기 쉬워진다

⑤ VPA + HPA 역할 분리

  • VPA
    • 실제 사용량 기반으로 request 추천/조정
    • “낭비 줄이기”
  • HPA
    • 트래픽 기반 replica 조정
    • “부하 대응”

request를 감으로 잡지 않고
관측 기반으로 수렴시키는 데 매우 효과적이다.


8. 그렇다면 request의 존재 의미는 무엇인가?

request는 단순히 HPA용 파라미터가 아니다.

request의 핵심 역할

  1. 스케줄링 기준
    • 노드에 올릴 수 있는지 판단
  2. 과밀 배치 방지
    • limit만으로는 막을 수 없는 문제
  3. QoS 결정
    • 메모리 압박 시 어떤 Pod가 먼저 죽을지
  4. 노드 오토스케일 기준
    • Cluster Autoscaler / Karpenter가 참고

👉 limit은 사후 처벌
👉 request는 사전 사고 방지


9. 실전 운영 가이드 요약

CPU

  • request: steady 평균 (HPA 기준)
  • limit: 없음 or 충분히 크게
  • HPA 사용

Memory

  • request: steady p50~p90
  • limit: startup peak + 여유
  • startupProbe 필수

공통

  • startup peak는 request로 해결하지 말 것
  • probe / 구조 / limit으로 흡수할 것

10. 한 문장으로 정리

request는 “평소 평균”이 아니라
“여러 Pod가 동시에 다시 살아날 때도
서비스가 무너지지 않게 하는 최소 보장선”이다.

startup peak까지 request에 포함할지 말지는
개념의 문제가 아니라 운영 전략의 선택이다.


마무리

resources.requests는 단순한 숫자 설정이 아니라
클러스터 밀도, 비용, 안정성, 스케일 전략이 모두 얽힌 설계 포인트다.

request를 줄이고 싶다면
먼저 startup peak를 분리하고 통제할 구조를 갖춰야 한다.

번외: 1.33 베타인 InPlacePodVerticalScaling 기능이 있는데 초기에만 cpu 높게 잡아주는 기능이 있다. 

하지만 베타라 아직 사용은 못한다. 1.34쯤 사용가능할지도 모르겠다.

반응형

댓글