시스템 데몬을 위한 컴퓨팅 리소스 예약하기
시스템 데몬을 위한 컴퓨팅 리소스 예약하기 (Reserve Compute Resources for System Daemons)
쿠버네티스 노드는 Capacity까지 스케줄링될 수 있어요. 기본적으로 파드가 노드의 모든 사용 가능한 용량을 소비할 수 있어요. 이는 노드가 보통 OS와 쿠버네티스 자체를 작동시키는 꽤 많은 시스템 데몬을 실행하기 때문에 문제가 돼요. 이 시스템 데몬들을 위해 리소스가 따로 배정되지 않으면, 파드와 시스템 데몬이 리소스를 위해 경쟁해 노드의 리소스 부족 문제를 초래해요.
kubelet은 시스템 데몬을 위해 컴퓨팅 리소스를 예약하는 데 도움을 주는 'Node Allocatable'이라는 기능을 노출해요. 쿠버네티스는 클러스터 관리자가 각 노드의 워크로드 밀도에 기반해 'Node Allocatable'을 구성할 것을 권장해요.
출처: 문서
본문
시작하기 전에 (Before you begin)
쿠버네티스 클러스터가 필요하고, kubectl 명령줄 도구가 클러스터와 통신하도록 구성돼 있어야 해요. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 두 개 이상 있는 클러스터에서 실행하는 것을 권장해요. 아직 클러스터가 없다면 minikube로 만들거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있어요.
- iximiuz Labs
- Killercoda
- KodeKloud
kubelet 구성 파일을 사용해 아래 kubelet 구성 설정을 구성할 수 있어요.
Node Allocatable (Node Allocatable)
쿠버네티스 노드의 'Allocatable'은 파드에 사용 가능한 컴퓨팅 리소스의 양으로 정의돼요. 스케줄러는 'Allocatable'을 초과 예약하지 않아요. 현재 'CPU', 'memory', 'ephemeral-storage'가 지원돼요.
Node Allocatable은 API의 v1.Node 객체의 일부로, CLI의 kubectl describe node의 일부로 노출돼요.
kubelet에는 두 가지 범주의 시스템 데몬을 위해 리소스를 예약할 수 있어요.
QoS 및 파드 레벨 cgroups 활성화 (Enabling QoS and Pod level cgroups)
노드에서 노드 할당 가능 제약을 제대로 강제하려면 cgroupsPerQOS 설정을 통해 새 cgroup 계층을 활성화해야 해요. 이 설정은 기본적으로 활성화돼 있어요. 활성화되면 kubelet은 모든 최종 사용자 파드를 kubelet이 관리하는 cgroup 계층 아래에 놓아요.
cgroup 드라이버 구성하기 (Configuring a cgroup driver)
kubelet은 cgroup 드라이버를 사용해 호스트의 cgroup 계층 조작을 지원해요. 드라이버는 cgroupDriver 설정으로 구성돼요. 지원되는 값은 다음과 같아요.
cgroupfs— cgroup 샌드박스를 관리하기 위해 호스트의 cgroup 파일시스템을 직접 조작하는 기본 드라이버예요.systemd— 그 init 시스템이 지원하는 리소스에 대해 일시적 슬라이스를 사용해 cgroup 샌드박스를 관리하는 대체 드라이버예요.
연관된 컨테이너 런타임의 구성에 따라 운영자가 적절한 시스템 동작을 보장하기 위해 특정 cgroup 드라이버를 선택해야 할 수 있어요. 예를 들어 운영자가 containerd 런타임이 제공하는 systemd cgroup 드라이버를 사용한다면 kubelet도 systemd cgroup 드라이버를 사용하도록 구성해야 해요.
Kube Reserved
- KubeletConfiguration 설정:
kubeReserved: {}. 예시 값{cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000} - KubeletConfiguration 설정:
kubeReservedCgroup: ""
kubeReserved는 kubelet, container runtime 같은 쿠버네티스 시스템 데몬을 위한 리소스 예약을 담기 위한 것이에요. 파드로 실행되는 시스템 데몬을 위한 리소스를 예약하는 것이 아니에요. kubeReserved는 보통 노드의 pod density의 함수예요.
cpu, memory, ephemeral-storage에 더해, 쿠버네티스 시스템 데몬을 위한 프로세스 ID 수를 예약하려면 pid를 지정할 수 있어요.
선택적으로 쿠버네티스 시스템 데몬에 kubeReserved를 강제하려면, kube 데몬의 상위 컨트롤 그룹을 kubeReservedCgroup 설정의 값으로 지정하고, enforceNodeAllocatable에 kube-reserved를 추가하세요.
쿠버네티스 시스템 데몬을 최상위 컨트롤 그룹(systemd 머신에서 runtime.slice 같은) 아래에 두는 것이 권장돼요. 각 시스템 데몬은 이상적으로 자신의 하위 컨트롤 그룹 안에서 실행되어야 해요. 권장되는 컨트롤 그룹 계층에 대한 자세한 내용은 설계 제안을 참고하세요.
Kubelet은 kubeReservedCgroup이 존재하지 않으면 만들지 않는다는 점에 주의하세요. 유효하지 않은 cgroup이 지정되면 kubelet이 시작에 실패해요. systemd cgroup 드라이버에서는 정의하는 cgroup 이름에 대해 특정 패턴을 따라야 해요: 이름은 kubeReservedCgroup에 설정한 값 뒤에 .slice를 붙인 것이어야 해요.
System Reserved
- KubeletConfiguration 설정:
systemReserved: {}. 예시 값{cpu: 100m, memory: 100Mi, ephemeral-storage: 1Gi, pid=1000} - KubeletConfiguration 설정:
systemReservedCgroup: ""
systemReserved는 sshd, udev 같은 OS 시스템 데몬을 위한 리소스 예약을 담기 위한 것이에요. systemReserved는 kernel 메모리도 예약해야 해요. 현재 쿠버네티스에서 kernel 메모리는 파드에 계상되지 않기 때문이에요. 사용자 로그인 세션을 위한 리소스 예약도 권장돼요(systemd 세계에서 user.slice).
cpu, memory, ephemeral-storage에 더해, OS 시스템 데몬을 위한 프로세스 ID 수를 예약하려면 pid를 지정할 수 있어요.
선택적으로 시스템 데몬에 systemReserved를 강제하려면 OS 시스템 데몬의 상위 컨트롤 그룹을 systemReservedCgroup 설정의 값으로 지정하고, enforceNodeAllocatable에 system-reserved를 추가하세요.
OS 시스템 데몬을 최상위 컨트롤 그룹(systemd 머신에서 system.slice 같은) 아래에 두는 것이 권장돼요.
kubelet은 systemReservedCgroup이 존재하지 않으면 만들지 않는다는 점에 주의하세요. 유효하지 않은 cgroup이 지정되면 kubelet이 실패해요. systemd cgroup 드라이버에서는 정의하는 cgroup 이름에 대해 특정 패턴을 따라야 해요: 이름은 systemReservedCgroup에 설정한 값 뒤에 .slice를 붙인 것이어야 해요.
명시적으로 예약된 CPU 목록 (Explicitly Reserved CPU List)
기능 상태: Kubernetes v1.17부터 Stable.
KubeletConfiguration 설정: reservedSystemCPUs:. 예시 값 0-3
reservedSystemCPUs는 OS 시스템 데몬과 쿠버네티스 시스템 데몬을 위한 명시적 CPU 집합을 정의하기 위한 것이에요. reservedSystemCPUs는 cpuset 리소스에 관해 OS 시스템 데몬과 쿠버네티스 시스템 데몬을 위한 별도의 최상위 cgroup을 정의하려 하지 않는 시스템을 위한 것이에요. Kubelet에 kubeReservedCgroup과 systemReservedCgroup이 없으면, reservedSystemCPUs가 제공하는 명시적 cpuset이 kubeReservedCgroup과 systemReservedCgroup 옵션으로 정의된 CPU보다 우선해요.
이 옵션은 제어할 수 없는 인터럽트/타이머가 워크로드 성능에 영향을 줄 수 있는 Telco/NFV 사용 사례를 위해 특별히 설계됐어요. 이 옵션을 사용하면 시스템/쿠버네티스 데몬과 인터럽트/타이머를 위한 명시적 cpuset을 정의해, 시스템의 나머지 CPU를 제어할 수 없는 인터럽트/타이머의 영향을 덜 받으며 워크로드에 독점적으로 사용할 수 있게 해요. 시스템 데몬, 쿠버네티스 데몬, 인터럽트/타이머를 이 옵션으로 정의된 명시적 cpuset으로 이동하려면 쿠버네티스 외부의 다른 메커니즘을 사용해야 해요. 예를 들어 Centos에서는 tuned 도구 모음을 사용해 할 수 있어요.
퇴거 임계값 (Eviction Thresholds)
KubeletConfiguration 설정: evictionHard: {memory.available: "100Mi", nodefs.available: "10%", nodefs.inodesFree: "5%", imagefs.available: "15%"}. 예시 값: {memory.available: "<500Mi"}
노드 레벨의 메모리 압력은 시스템 OOM으로 이어지며, 이는 전체 노드와 그 노드에서 실행되는 모든 파드에 영향을 줘요. 노드는 메모리가 회수될 때까지 잠시 오프라인이 될 수 있어요. 시스템 OOM을 피하거나(또는 확률을 줄이거나) kubelet은 리소스 부족 관리(out of resource management)를 제공해요. 퇴거는 memory와 ephemeral-storage에서만 지원돼요. evictionHard 설정으로 일부 메모리를 예약함으로써 kubelet은 노드의 메모리 가용성이 예약된 값 아래로 떨어질 때마다 파드를 퇴거하려 시도해요. 가정적으로 노드에 시스템 데몬이 없으면 파드는 capacity - eviction-hard보다 더 많은 것을 사용할 수 없어요. 이런 이유로 퇴거를 위해 예약된 리소스는 파드에 사용할 수 없어요.
Node Allocatable 강제하기 (Enforcing Node Allocatable)
KubeletConfiguration 설정: enforceNodeAllocatable: [pods]. 예시 값: [pods,system-reserved,kube-reserved]
스케줄러는 'Allocatable'을 파드의 사용 가능한 capacity로 취급해요. kubelet은 기본적으로 파드에 걸쳐 'Allocatable'을 강제해요. 강제는 모든 파드에 걸친 전체 사용량이 'Allocatable'을 초과할 때마다 파드를 퇴거함으로써 수행돼요. 퇴거 정책에 대한 더 자세한 내용은 노드 압력 퇴거 페이지에서 찾을 수 있어요. 이 강제는 KubeletConfiguration 설정 enforceNodeAllocatable에 pods 값을 지정해 제어돼요.
선택적으로 kubelet은 같은 설정에 kube-reserved와 system-reserved 값을 지정해 kubeReserved와 systemReserved를 강제하도록 할 수 있어요. 추가로, kube-reserved-compressible과 system-reserved-compressible을 지정해 압축 가능한 리소스만 강제할 수 있어요. kubeReserved 또는 systemReserved를 강제하려면 각각 kubeReservedCgroup 또는 systemReservedCgroup을 지정해야 한다는 점에 주의하세요.
일반 지침 (General Guidelines)
시스템 데몬은 Guaranteed 파드와 비슷하게 취급될 것으로 기대돼요. 시스템 데몬은 바운딩 컨트롤 그룹 안에서 버스트할 수 있으며, 이 동작은 쿠버네티스 배포의 일부로 관리되어야 해요. 예를 들어 kubelet은 자체 컨트롤 그룹을 가져야 하고 컨테이너 런타임과 kubeReserved 리소스를 공유해야 해요. 하지만 kubeReserved가 강제되면 Kubelet은 버스트해 노드의 모든 사용 가능한 리소스를 소비할 수 없어요.
systemReserved 예약을 강제할 때는 매우 주의해야 해요. 이는 중요한 시스템 서비스가 CPU 부족, OOM 종료, 또는 노드에서 fork 불가능 상태가 되게 할 수 있기 때문이에요. systemReserved를 강제하는 것은 사용자가 정확한 추정치를 내기 위해 노드를 철저히 프로파일링하고, 그 그룹의 어떤 프로세스가 oom-kill되면 회복할 수 있는 능력에 자신이 있을 때만 권장돼요.
kubeReserved와 systemReserved에 압축 가능한 리소스만 강제하는 것은 경합이 있을 때 리소스가 적절히 할당되도록 보장하면서 중단을 일으킬 가능성이 더 낮아요.
- 시작하려면
pods에 'Allocatable'을 강제해요. - kube와 시스템 데몬을 추적하기 위한 적절한 모니터링과 알림이 마련되면
kubeReserved와systemReserved에 압축 가능한 리소스를 강제하려 시도해요. - 사용량 휴리스틱에 기반해 비압축
kubeReserved리소스를 강제하려 시도해요. - 절대적으로 필요하다면 시간이 지나면서 비압축
systemReserved리소스를 강제해요.
kube 시스템 데몬의 리소스 요구는 기능이 점점 더 추가되면서 시간이 지나며 커질 수 있어요. 시간이 지나면서 쿠버네티스 프로젝트는 노드 시스템 데몬의 사용률을 낮추려 시도하겠지만, 그것은 현재 우선순위가 아니에요. 그러니 향후 릴리스에서 Allocatable 용량이 감소할 것으로 기대하세요.
예시 시나리오 (Example Scenario)
Node Allocatable 계산을 설명하는 예시를 들어 드릴게요.
- 노드에
32Gi의memory,16 CPUs,100Gi의Storage가 있음 kubeReserved가{cpu: 1000m, memory: 2Gi, ephemeral-storage: 1Gi}로 설정됨systemReserved가{cpu: 500m, memory: 1Gi, ephemeral-storage: 1Gi}로 설정됨evictionHard가{memory.available: "<500Mi", nodefs.available: "<10%"}로 설정됨
이 시나리오에서 'Allocatable'은 14.5 CPUs, 28.5Gi의 메모리, 88Gi의 로컬 스토리지가 돼요. 스케줄러는 이 노드의 모든 파드에 걸친 총 메모리 requests가 28.5Gi를, 스토리지가 88Gi를 초과하지 않도록 보장해요. Kubelet은 파드에 걸친 전체 메모리 사용량이 28.5Gi를 초과하거나 전체 디스크 사용량이 88Gi를 초과할 때마다 파드를 퇴거해요. 노드의 모든 프로세스가 할 수 있는 만큼 CPU를 소비하면, 파드는 합쳐서 14.5 CPUs보다 더 많이 소비할 수 없어요.
kubeReserved 및/또는 systemReserved가 강제되지 않고 시스템 데몬이 예약을 초과하면, kubelet은 노드 전체 메모리 사용량이 31.5Gi보다 높거나 storage가 90Gi보다 클 때마다 파드를 퇴거해요.