본문 바로가기
클라우드/쿠버네티스

⚖️ Kubernetes Requests & Limits: 우리 앱 안정성 지키는 최소한의 약속

by gasbugs 2025. 9. 2.

안녕하세요! 👋 오늘은 쿠버네티스에서 애플리케이션의 안정성을 보장하는 가장 기본적이면서도 강력한 기능, RequestsLimits에 대해 알아보겠습니다.

 

아파트에 사는데, 옆집에서 물을 펑펑 쓰는 바람에 우리 집엔 물이 졸졸 나온다고 상상해 보세요. 😡 쿠버네티스 클러스터의 노드(서버)도 마찬가지입니다. 하나의 컨테이너가 CPU나 메모리를 독차지하면, 같은 노드에서 실행 중인 다른 컨테이너들은 버벅대거나 멈춰버릴 수 있습니다.

 

이런 '자원 독점' 대참사를 막고, 내 애플리케이션이 안정적으로 실행될 공간을 확보하는 약속이 바로 Requests와 Limits입니다.

 


🤔 왜 리소스 관리가 중요한가요?

"내 컴퓨터에서는 잘 돌아갔는데..." 클라우드 환경에서는 이 말이 통하지 않습니다. 하나의 노드는 여러 컨테이너가 함께 사용하는 '공용 공간'이기 때문입니다. 리소스 관리를 하지 않으면 다음과 같은 문제들이 발생할 수 있습니다.

  • 😭 리소스 부족 (Resource Starvation): 특정 컨테이너가 CPU를 100% 사용하면, 다른 컨테iner들은 CPU를 할당받지 못해 응답이 느려지거나 멈춥니다.
  • 💥 노드 불안정 (Node Instability): 메모리를 마구잡이로 사용하는 컨테이너 때문에 노드 자체의 메모리가 부족해지면, 노드 전체가 다운될 수 있습니다.
  • 쫓겨나는 내 앱 (Pod Eviction): 노드에 리소스가 부족해지면, 쿠버네티스는 우선순위가 낮은 파드부터 강제로 종료시켜 공간을 확보합니다.
  • 널뛰는 성능 (Unpredictable Performance): 주변 컨테이너의 리소스 사용량에 따라 내 앱의 성능이 갑자기 좋아졌다가 나빠지는 현상이 발생합니다.

이 모든 문제를 예방하기 위해, 우리는 쿠버네티스에게 "내 컨테이너는 이 정도의 자원이 필요하고, 이 이상은 쓰지 않을 거야"라고 명확하게 알려주어야 합니다.


🙏 Requests: "이만큼은 꼭 보장해주세요!" (최소 요청량)

Requests는 컨테이너가 안정적으로 동작하기 위해 필요한 최소한의 리소스 양을 쿠버네티스에게 알리는 값입니다.

  • 핵심 역할: 스케줄링! 🗓️ 쿠버네티스 스케줄러는 파드를 어떤 노드에 배치할지 결정할 때 바로 이 requests 값을 봅니다. 예를 들어, 어떤 파드가 "CPU 1코어, 메모리 1GiB가 필요해요"(requests)라고 요청하면, 스케줄러는 그만큼의 여유 공간이 있는 노드에만 해당 파드를 배치합니다. 만약 모든 노드가 꽉 차서 요청량을 만족시킬 수 없다면, 파드는 Pending 상태로 대기하게 됩니다.

즉, requests는 "내 앱이 실행될 최소한의 공간을 예약하는 것"과 같습니다. 이 공간은 다른 컨테이너가 함부로 침범할 수 없도록 보장됩니다.


🛑 Limits: "이 선은 절대 넘지 마세요!" (최대 제한량)

Limits는 컨테이너가 사용할 수 있는 리소스의 상한선, 즉 최댓값을 설정하는 것입니다. 얘기치 않은 버그나 트래픽 폭증으로 컨테이너가 리소스를 무한정 사용하는 것을 막는 안전장치 역할을 합니다.

limits를 초과하면 어떤 일이 벌어질까요? 리소스 종류에 따라 다릅니다.

  • CPU Limits 초과: 컨테이너가 limits로 설정된 CPU보다 더 많은 연산을 하려고 하면, 쿠버네티스는 해당 컨테이너의 CPU 사용을 강제로 제어(Throttling)합니다. 컨테이너가 죽지는 않지만, 성능이 저하되어 응답이 느려집니다. 마치 과속 방지턱을 만난 것처럼요.
  • Memory Limits 초과: 메모리는 CPU와 다릅니다. 컨테이너가 limits로 설정된 메모리보다 더 많이 사용하려고 하면, 해당 컨테이너는 가차 없이 종료(Terminated)됩니다. 이를 OOMKilled(Out of Memory Killed)라고 부릅니다. 이는 메모리를 계속 사용하게 둘 경우 노드 전체가 위험해질 수 있기 때문에, 문제의 컨테이너를 희생시켜 전체 시스템을 보호하는 조치입니다.

📋 YAML 예시로 한눈에 보기

실제 파드 정의 파일(YAML)에서는 spec.containers.resources 필드에 다음과 같이 작성합니다.

apiVersion: v1
kind: Pod
metadata:
  name: my-app-pod
spec:
  containers:
  - name: my-app-container
    image: nginx
    resources:
      requests:
        memory: "128Mi"  # 최소 128 Mebibyte 메모리를 보장받습니다.
        cpu: "250m"     # 최소 0.25 코어(250 millicores) CPU를 보장받습니다.
      limits:
        memory: "256Mi" # 최대 256 Mebibyte 메모리까지만 사용할 수 있습니다.
        cpu: "500m"     # 최대 0.5 코어(500 millicores) CPU까지만 사용할 수 있습니다.

💡 단위(Unit)를 알아두세요!

  • CPU: m은 'millicore'를 의미합니다. 1000m이 1개의 vCPU 코어와 같습니다.
  • Memory: Ki(Kibibyte), Mi(Mebibyte), Gi(Gibibyte) 등 2의 거듭제곱 단위를 사용합니다. 우리가 흔히 쓰는 KB, MB, GB와는 약간의 차이가 있습니다.

✨ 그 결과: 서비스 품질(QoS) 등급이 정해져요

requests와 limits를 어떻게 설정하느냐에 따라 쿠버네티스는 파드를 세 가지의 서비스 품질(QoS) 등급으로 자동 분류합니다. 이 등급은 노드에 리소스가 부족할 때 어떤 파드를 먼저 종료시킬지 결정하는 중요한 기준이 됩니다.

  1. Guaranteed (최고 등급 👍):
    • 조건: requests와 limits가 설정되어 있고, 모든 리소스의 requests 값이 limits 값과 같을 때.
    • 특징: 가장 높은 우선순위를 가지며, 시스템 리소스가 부족할 때 가장 마지막까지 살아남습니다. 예측 가능성이 가장 중요할 때 사용합니다.
  2. Burstable (중간 등급 👌):
    • 조건: requests와 limits가 설정되어 있지만, requests 값이 limits 값보다 작을 때.
    • 특징: 평소에는 requests만큼의 자원을 보장받다가, 노드에 여유가 있으면 limits까지 자원을 더 사용할 수 있습니다. 일반적인 애플리케이션에 가장 많이 사용됩니다.
  3. BestEffort (최하 등급 👎):
    • 조건: requests와 limits가 전혀 설정되지 않았을 때.
    • 특징: 노드에 자원이 남을 때만 사용할 수 있으며, 리소스가 부족해지면 가장 먼저 종료(Evicted)될 대상 1순위입니다. 중요하지 않은 테스트나 배치 작업에 사용할 수 있습니다.

✅ 정리하며

Requests와 Limits는 단순히 숫자를 적는 것을 넘어, 내 애플리케이션의 안정성을 보장하고 클러스터 전체의 건강을 지키는 매우 중요한 약속입니다.

  • Requests는 '최소한의 생존 공간'을 예약하여 스케줄링과 안정적인 성능을 보장합니다.
  • Limits는 '넘지 말아야 할 한계선'을 그어 리소스 독점을 막고 전체 시스템을 보호합니다.
  • 이 설정에 따라 QoS 등급이 정해지고, 위기 상황에서 내 파드의 운명이 결정됩니다.

지금 바로 여러분의 쿠버네티스 파드 정의 파일에 resources 필드가 잘 설정되어 있는지 확인해보세요!


태그: Kubernetes, K8s, Requests, Limits, 리소스 관리, 안정성, DevOps, 컨테이너, QoS, 쿠버네티스