쿠버네티스 런타임과 파드 오버헤드 (RuntimeClass, Pod Overhead)

A. 본론
A.1. 사전지식 - cgroup
Linux에서는 cgroup을 통해서 프로세스의 리소스 사용을 제어합니다.
Kubernetes에서도 cgroup을 사용하여 파드(컨테이너)의 리소스 사용을 제한합니다.
대표적으로 cpu, memory에 대한 요청 및 제한(request & limit)이 있습니다.
A.2. 사전지식 - pod request, limit
cgroup에서 잠깐 언급한 request, limit은 파드의 각 컨테이너에 정의합니다.
이 정의에 따라서 QoS(Quality of Service, 서비스 품질) Class를 할당받게 됩니다.
쿠버네티스 파드 안정성 (QoS) [A.2-1]
일반적으로 리소스 압박(node-pressure)이 있을 때,
QoS Class, Pod Resource request, limit 등을 고려합니다.
A.3. Runtime, Handler, RuntimeClass 개념
Kubernetes는 기본적으로 컨테이너 엔진으로 containerd*를 사용하며,
containerd를 통해 설치된 handler와 이를 참조하는 RuntimeClas를 사용하여,
kata-container와 같은 별도의 런타임을 사용할 수 있게 됩니다.
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
name: sample-runtime
handler: sample-runtime
(왜 별도의 런타임을 쓰는지는 논외로 하고)
containerd*에서 설치된 기본 핸들러에 runc*가 있음을 확인할 수 있습니다.
cat /etc/containerd/config.toml | grep runtimes
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
아래 실습을 통해서 RuntimeClass, Pod를 간단하게 진행할 수 있었습니다.
RuntimeClass, Pod 생성하기
mkdir -p ~/runtime-class cd ~/runtime-class cat <<EOF > runc-sample.yaml --- apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: runtime-runc handler: runc --- apiVersion: v1 kind: Pod metadata: name: nginx spec: runtimeClassName: runtime-runc containers: - image: nginx name: nginx EOF kubectl apply -f runc-sample.yaml
Pod 생성확인하기
kubectl get pod nginx -o yaml| grep "runtimeClassName\:"
runtimeClassName: runtime-runc
RuntimeClass, Pod 삭제하기
cd ~/runtime-class kubectl delete -f runc-sample.yaml
A.3. Pod Overhead 개념
🚫
최초에는 Kata Container를 사용한 실습을 진행하려 하였으나, Kata Container의 설치 방식과 구문이 Ubuntu 22 버전에서 호환되지 않고 여러 가지 기능상의 문제가 있기 때문에 기본 핸들러인 runc를 사용했습니다. - https://github.com/kata-containers/documentation/blob/master/install/ubuntu-installation-guide.md
리소스 제한을 위해 N개의 컨테이너에 개별적으로 request, limit을 줄 수 있습니다.
이 값은 개별 컨테이너가 소모할 리소스에 대한 request, limit일 것입니다.
하지만 실제로는 파드(Pod)가 자체적으로 소모하는 리소스가 있습니다.
이 리소스는 쿠버네티스 구성 및 런타임에 따라 달라지며 일정한 값이 있습니다.
Pod Overhead를 통해서 더하여 파드의 request, limit을 안정화할 수 있습니다.
그렇다면 파드(Pod)가 자체적으로 소모하는 리소스에는 무엇이 있을까요?
이는 컨테이너 런타임이 격리(isolation)을 구현하는 방식에 따라 크기가 달라집니다.
gVisor : 사용자 공간 커널 사용
kata : 경량 VM 사용
firecracker : microVM 사용
따라서 Linux 커널 기반의 격리(isolation)을 쓰는 runc는 리소스 소모량이 적습니다.
이 양이 극히 적기 때문에 파드 오버헤드(Pod Overhead)값이 0으로 설정됩니다.
다만 실습 진행을 위해서
RuntimeClass, PodOverhead를 다음과 같이 설정할 수 있습니다.
RuntimeClass, Pod 생성하기
mkdir -p ~/runtime-class cd ~/runtime-class cat <<EOF > runc-sample.yaml --- apiVersion: node.k8s.io/v1 kind: RuntimeClass metadata: name: sample-runc handler: runc overhead: podFixed: cpu: 250m memory: 128Mi --- apiVersion: v1 kind: Pod metadata: name: nginx spec: runtimeClassName: sample-runc containers: - image: nginx name: nginx resources: limits: cpu: 1500m memory: 100Mi EOF kubectl apply -f runc-sample.yaml
Pod 생성확인하기
kubectl get pod nginx -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,CLASS:.spec.runtimeClassName,OVERHEAD:.spec.overhead,READY:.status.containerStatuses[*].ready,STATUS:.status.phase
RuntimeClass, Pod 삭제하기
cd ~/runtime-class kubectl delete -f runc-sample.yaml
A.4. 내용 정리
파드(Pod)는 자체적으로 소모하는 리소스가 있다.
자체적으로 소모하는 리소스는 주로 컨테이너 런타임의 구현방식에 따라 달라진다.
conatinerd의 기본 런타임인 runc는 자체 소모 리소스가 매우 낮아 0으로 갈음한다.
runc를 사용하더라도 Pod Security Standard/Context 등의 보안 기능을 많이 사용하면 자체 리소스 소모량이 증가하고 이 경우 RuntimeClass를 통해 Pod Overhead를 설정해야한다.
gVisor, KataContainer, FireCracker 등을 사용한다면 자체 리소스 소모량이 꽤 발생하며 이 경우 RuntimeClass를 통해 Pod Overhead를 설정해야 한다.
A.5. 더 공부할 부분
작성일(25.04.10) 시점,
RuntimeClass, Pod Overhead의 기본적인 개요를 알게 되었습니다.
현 시점에 gVisor, Kata Container, FireCracker 등의 공부 니즈가 없어서 여기서 문서를 마무리하려고 합니다.
만약 이 글을 이어서 작성하게 된다면 아래 부분을 작성할 예정입니다.
Scheduler와 연결하여 Pod Overhead 유무 및 크기에 따른 작동 과정 분석
Pod Overhead 크기를 직접 측정하기 위한 기법