Kubernetes가 파드를 죽인다? 이유는.

발행: (2026년 6월 12일 AM 06:27 GMT+9)
9 분 소요
원문: Dev.to

출처: Dev.to

Kubernetes가 당신의 파드를 죽인다? 이유는 이렇다

dsplce.co

당신의 파드가 계속해서 죽어갑니다. 충돌이 아니라 죽음입니다. 어느 순간엔 정상적으로 실행되다가, 다음 순간엔 사라지고 Kubernetes가 대체 파드를 띄우기 시작합니다. 로그를 확인해도 유용한 정보가 없습니다. 파드가 그냥… 사라진 겁니다.

결국 Kubernetes가 의도적으로 파드를 죽인 것이었습니다. 그리고 애플리케이션이 실제로 얼마나 메모리를 필요로 하는지 알려주지 않으면, 계속해서 파드를 죽일 것입니다.

Kubernetes가 파드를 퇴출시키는 이유

Kubernetes는 노드(물리 혹은 가상 머신) 위에서 컨테이너를 실행합니다. 각 노드는 제한된 CPU와 메모리를 가지고 있습니다. 노드의 자원이 부족해지면, Kubernetes는 어떤 파드를 유지하고, 어떤 파드를 퇴출시켜야 할지 선택해야 합니다.

이 선택은 QoS 클래스(Quality of Service 등급)에 따라 결정됩니다. QoS 클래스는 파드에 설정한 리소스 요청(requests)리소스 제한(limits) 에 기반해 Kubernetes가 자동으로 부여합니다.

클래스는 세 가지가 있습니다:

  • BestEffort — 리소스 요청이나 제한이 전혀 정의되지 않은 경우. Kubernetes는 파드가 얼마나 CPU와 메모리를 필요로 하는지 전혀 모릅니다. 이 파드가 가장 먼저 퇴출됩니다.
  • Burstable — 요청과 제한은 정의했지만 값이 서로 다를 때(예: requests: 256Mi, limits: 512Mi). 파드는 요청량은 보장받지만, 필요에 따라 제한까지 폭증할 수 있습니다. 두 번째로 퇴출됩니다.
  • Guaranteed — 요청과 제한을 동일하게 설정한 경우. Kubernetes는 정확히 그 양만큼의 리소스를 파드에 예약합니다. 가장 마지막에 퇴출됩니다.

파드에 리소스 설정이 전혀 없다면, BestEffort 클래스로 실행됩니다. 노드에 메모리 압박이 걸리면, BestEffort 파드가 가장 먼저 사라집니다—별다른 질문 없이.

Guaranteed 클래스

파드를 Guaranteed 클래스로 만들려면 배포 설정에 한 줄만 추가하면 됩니다. CPU와 메모리 모두에 requestslimits 를 정의하고, 두 값을 동일하게 맞추세요:

resources:
  requests:
    memory: "512Mi"
    cpu: "500m"
  limits:
    memory: "512Mi"
    cpu: "500m"

그게 전부입니다. 이제 Kubernetes는 이 파드가 정확히 512 MiB RAM과 0.5 CPU 코어를 필요로 한다는 것을 알고, 노드에 파드를 스케줄링할 때 해당 용량을 예약합니다. 노드에 512 MiB가 남아 있지 않다면 파드는 그 노드에 배치되지 않으며, 노드가 메모리 압박에 직면했을 때도 이 파드는 마지막으로 퇴출됩니다—BestEffort와 Burstable 파드가 모두 사라진 뒤에야 말이죠.

부수 효과 — 더 나은 자동 스케일링

EKS 같은 관리형 Kubernetes 플랫폼에서는 추가적인 이점이 있습니다. 클러스터 자동 스케일러는 리소스 요청을 기준으로 새로운 노드가 필요한지 판단합니다.

파드가 BestEffort(리소스 설정 없음)라면, 자동 스케일러는 해당 파드가 0 리소스를 요구한다고 판단합니다. 하나의 노드에 10개의 파드가 실행돼도, 그 노드가 메모리 90% 사용 중이라도 새로운 노드를 추가하지 않습니다. “충족되지 않은 리소스 요구가 없으니”라고 판단하기 때문이죠.

하지만 같은 파드가 requests: 512Mi 로 Guaranteed 설정되어 있고, 현재 노드에 512 MiB 여유가 없다면, 자동 스케일러는 스케줄링되지 못한 파드가 존재한다고 보고 새로운 노드를 추가합니다. 파드가 하나의 노드에 몰려 있지 않고 여러 노드에 고르게 퍼지게 되는 겁니다.

EKS에서는 이 동작이 특히 엄격합니다. 다른 Kubernetes 제공업체는 다소 관대하게 동작할 수 있지만, EKS는 스케줄러의 리소스 계산을 정확히 따릅니다. 요청(request)을 정의하지 않으면 자동 스케일링이 트리거되지 않아, 모든 파드가 하나의 노드에 몰려 메모리가 부족해 퇴출이 발생하게 됩니다.

트레이드오프

Guaranteed 클래스의 단점은 정해진 메모리 한도에 묶인다는 점입니다. 애플리케이션이 성장해 설정한 한도보다 더 많은 메모리를 사용하게 되면, 파드는 OOMKilled(Out‑Of‑Memory 킬)당합니다. 제한을 초과해 버스트(burst)할 여지는 없습니다.

Burstable 클래스를 사용하면 requests: 256Mi, limits: 1Gi 와 같이 설정해, 애플리케이션이 급증할 때는 최대 1 GiB까지 사용할 수 있게 할 수 있습니다. 하지만 스케줄링 보장은 잃게 됩니다—Kubernetes는 오직 256 MiB만 예약하므로, 파드가 실제로 1 GiB를 필요로 할 때는 해당 리소스를 충분히 가진 노드에 배치되지 않을 수도 있습니다.

Guaranteed를 쓰려면 메모리 사용량을 지속적으로 모니터링하고, 필요할 때마다 한도를 올려야 합니다. 유지보수가 조금 더 필요하지만, 그 대가로 예측 가능한 스케줄링, 퇴출 방지, 그리고 실제 동작하는 자동 스케일링을 얻을 수 있습니다.

설정 방법

배포 매니페스트(deployment.yaml)에 containers 아래 resources 블록을 추가합니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: your-app
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: app
        image: your-image:latest
        resources:
          requests:
            memory: "512Mi"
            cpu: "500m"
          limits:
            memory: "512Mi"
            cpu: "500m"
kubectl apply -f deployment.yaml

QoS 클래스를 확인하려면:

kubectl get pod  -o jsonpath='{.status.qosClass}'

Guaranteed 라고 나오면 설정이 정상적으로 적용된 것입니다.

적절한 값 선택하기

먼저 현재 파드가 실제로 사용하는 리소스를 확인합니다. 메모리 사용량을 확인하려면:

kubectl top pods

가장 높은 값을 기준으로 20~30% 정도 여유를 더해 requestslimits 로 설정합니다. 예를 들어 파드가 400 MiB를 사용하고 있다면 512 MiB로 잡고, 지속적으로 800 MiB에 근접한다면 1 GiB로 설정합니다.

CPU는 대부분의 애플리케이션에 대해 500m(반 코어) 정도가 시작점

0 조회
Back to Blog

관련 글

더 보기 »

Eidentic 소개

Today we're releasing Eidentic, an open-source TypeScript SDK for building AI agents with self-improving memory and the production fundamentals built in — not b...

Typescript의 타입

Introdução Tipos são uma forma de definir a “forma” ou o contrato dos dados que estamos usando no código. Pensando em Javascript puro, ele é dinâmico: você pode...