파드 오버헤드

파드 오버헤드 (Pod Overhead)

파드를 노드에서 실행하면 파드 자체가 일정량의 시스템 리소스를 차지해요. 이 리소스는 파드 안의 컨테이너를 실행하는 데 필요한 리소스에 추가되는 거예요. Kubernetes에서 파드 오버헤드(Pod Overhead)는 컨테이너 요청·제한(request & limits) 위에 파드 인프라스트럭처가 소비하는 리소스를 계산하는 방법이에요.

Kubernetes에서 파드의 오버헤드는 파드의 RuntimeClass와 연결된 오버헤드에 따라 admission 시점에 설정돼요.

파드의 오버헤드는 파드를 스케줄링할 때 컨테이너 리소스 요청의 합에 추가로 고려돼요. 마찬가지로 kubelet은 파드 cgroup 크기를 정할 때와 파드 축출(eviction) 순위를 매길 때 파드 오버헤드를 포함해요.

출처: 문서

본문

파드 오버헤드 구성하기

overhead 필드를 정의하는 RuntimeClass를 사용하는지 확인해야 해요.

사용 예시 (Usage example)

파드 오버헤드를 다루려면 overhead 필드를 정의하는 RuntimeClass가 필요해요. 예를 들어 파드당 가상 머신과 게스트 OS에 약 120MiB를 사용하는 가상화 컨테이너 런타임(이 예시에서는 Firecracker 가상 머신 모니터와 결합한 Kata Containers)과 함께 다음 RuntimeClass 정의를 사용할 수 있어요.

# You need to change this example to match the actual runtime name, and per-Pod
# resource overhead, that the container runtime is adding in your cluster.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: kata-fc
handler: kata-fc
overhead:
  podFixed:
    memory: "120Mi"
    cpu: "250m"

kata-fc RuntimeClass 핸들러를 지정해 생성되는 워크로드는 리소스 쿼터 계산, 노드 스케줄링, 파드 cgroup 크기 결정에서 메모리와 CPU 오버헤드를 고려하게 돼요.

주어진 예시 워크로드 test-pod를 실행한다고 생각해 봐요.

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  runtimeClassName: kata-fc
  containers:
  - name: busybox-ctr
    image: busybox:1.28
    stdin: true
    tty: true
    resources:
      limits:
        cpu: 500m
        memory: 100Mi
  - name: nginx-ctr
    image: nginx
    resources:
      limits:
        cpu: 1500m
        memory: 100Mi

admission 시점에 RuntimeClass admission 컨트롤러는 RuntimeClass에 설명된 대로 오버헤드를 포함하도록 워크로드의 PodSpec을 업데이트해요. PodSpec에 이미 이 필드가 정의되어 있으면 파드는 거부돼요. 주어진 예시에서는 RuntimeClass 이름만 지정되었으므로, admission 컨트롤러가 파드를 변형해 overhead를 포함해요.

RuntimeClass admission 컨트롤러가 수정한 후, 업데이트된 파드 오버헤드 값을 확인할 수 있어요.

kubectl get pod test-pod -o jsonpath='{.spec.overhead}'

출력은 다음과 같아요.

map[cpu:250m memory:120Mi]

ResourceQuota가 정의되어 있다면, 컨테이너 요청의 합과 overhead 필드가 함께 계산돼요.

kube-scheduler가 새 파드를 실행할 노드를 결정할 때, 스케줄러는 그 파드의 오버헤드와 컨테이너 요청의 합을 고려해요. 이 예시에서 스케줄러는 요청과 오버헤드를 더한 2.25 CPU와 320 MiB 메모리가 가용한 노드를 찾아요.

파드가 노드에 스케줄링되면 그 노드의 kubelet은 파드를 위한 새 cgroup을 만들어요. 이 파드 안에서 기반 컨테이너 런타임이 컨테이너를 만들어요.

각 컨테이너에 리소스 한도가 정의되어 있다면(Guaranteed QoS 또는 한도가 정의된 Burstable QoS), kubelet은 그 리소스와 연결된 파드 cgroup에 상한을 설정해요(CPU의 경우 cpu.cfs_quota_us, 메모리의 경우 memory.limit_in_bytes). 이 상한은 컨테이너 한도의 합에 PodSpec에 정의된 overhead를 더한 값을 기반으로 해요.

CPU의 경우, 파드가 Guaranteed 또는 Burstable QoS라면 kubelet은 컨테이너 요청의 합에 PodSpec에 정의된 overhead를 더한 값에 따라 cpu.shares를 설정해요.

예시를 보면서 워크로드의 컨테이너 요청을 확인해 봐요.

kubectl get pod test-pod -o jsonpath='{.spec.containers[*].resources.limits}'

총 컨테이너 요청은 2000m CPU와 200MiB 메모리예요.

map[cpu: 500m memory:100Mi] map[cpu:1500m memory:100Mi]

이 값이 노드가 관찰하는 값과 일치하는지 확인해 봐요.

kubectl describe node | grep test-pod -B2

출력은 2250m CPU와 320MiB 메모리 요청을 보여줘요. 이 요청에는 파드 오버헤드가 포함되어 있어요.

Namespace    Name       CPU Requests  CPU Limits   Memory Requests  Memory Limits  AGE
  ---------    ----       ------------  ----------   ---------------  -------------  ---
  default      test-pod   2250m (56%)   2250m (56%)  320Mi (1%)       320Mi (1%)     36m

파드 cgroup 한도 확인

워크로드가 실행되는 노드에서 파드의 메모리 cgroup을 확인해요. 다음 예시에서는 노드에서 crictl을 사용하며, 이것은 CRI 호환 컨테이너 런타임에 대한 CLI를 제공해요. 파드 오버헤드 동작을 보여주는 고급 예시이며, 사용자가 노드에서 cgroup을 직접 확인해야 할 것으로 기대하지는 않아요.

먼저, 해당 노드에서 파드 식별자를 확인해요.

# Run this on the node where the Pod is scheduled
POD_ID="$(sudo crictl pods --name test-pod -q)"

이 값에서 파드의 cgroup 경로를 확인할 수 있어요.

# Run this on the node where the Pod is scheduled
sudo crictl inspectp -o=json $POD_ID | grep cgroupsPath

결과 cgroup 경로에는 파드의 pause 컨테이너가 포함돼요. 파드 수준 cgroup은 한 디렉터리 위에 있어요.

"cgroupsPath": "/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/7ccf55aee35dd16aca4189c952d83487297f3cd760f1bbf09620e206e7d0c27a"

이 특정 경우 파드 cgroup 경로는 kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2예요. 파드 수준 cgroup의 메모리 설정을 확인해요.

# Run this on the node where the Pod is scheduled.
# Also, change the name of the cgroup to match the cgroup allocated for your pod.
 cat /sys/fs/cgroup/memory/kubepods/podd7f4b509-cf94-4951-9417-d1087c92a5b2/memory.limit_in_bytes

예상대로 320 MiB예요.

335544320

관찰성 (Observability)

kube-state-metrics에서 일부 kube_pod_overhead_* 메트릭을 사용할 수 있어, 파드 오버헤드가 사용되고 있는 때를 식별하고 정의된 오버헤드로 실행되는 워크로드의 안정성을 관찰하는 데 도움을 줘요.

다음 단계

더 알아보기 (Learn more)