Debugging Sparrow

Kubernetes Container Resource

2020/10/26 kubernetes k8s cgroup

컨테이너 리소스, docker, cgroup(control group)

쿠버네티스는 파드에서 컨테이너를 실행하기 위해 kubelet을 통하고 kubelet은 노드의 컨테이너 런타임을 사용하게 된다. 컨테이너 런타임(docker)은 리눅스의 cgroup을 이용해 컨테이너의 리소스 사용량을 제한하고 격리한다. 그렇기 때문에 쿠버네티스에서 컨테이너에 리소스를 할당하고 제한하는 것은 노드의 컨테이너 런타임(docker)과 cgroup을 통해 구현된다.

요청한 값과 실제 cgroup 값 사이의 관계

spec.containers[].resources.requests.cpu

이 값에서 1,024를 곱한 값이 docker run –cpu-shares 및 cgroup의 cpu.shares의 값에 해당된다.

1
2
3
(1 -> 1,024)
(0.1 -> 102)
(100m -> 102)

spec.containers[].resources.limits.cpu

이 값에서 100,000을 곱한 값이 docker run –cfs-quota의 값이 되고 cpu-period는 100,000으로 고정된다. cpu.cfs_quota_us, cpu.cfs_period_us 또한 동일하다.

1
2
3
(1 -> 100,000)
(0.1 -> 10,000)
(100m -> 10,000)

cpu-period가 100,000으로 고정되기 때문에 값을 1로 준 경우 period와 quota가 같아 최대 cpu 하나를 전부 점유할 수 있다는 것을 알 수 있다.

spec.containers[].resources.requests.memory

cgroup 설정에 사용되지 않고 Pod Scheduling에만 이용. 컨테이너가 메모리 요청을 초과한 경우 축출될 수 있다.

spec.containers[].resources.limits.memory

이 값을 bytes 정수로 치환한 것이 docker run –memory 및 memory.limit_in_bytes에 해당 된다.

1
(170Mi -> 178,257,920)

메모리의 상한을 넘어선 경우 컨테이너는 강제 종료된다.

cgroup

이제 cgroup값이 실제로 어떻게 작용하는지 알아본다.

cpu.cfs_period_us, cpu.cfs_quota_us

cfs_period_us는 cpu bandwidth를 결정하는 스케줄러 주기를 의미한다. 값이 클수록 cpu-bound workload를 오래 유지할 수 있으므로 현재 컨테이너의 처리량이 올라가게 된다.
cfs_quota_us는 period를 통해 결정된 주기 내에서 최대 얼마나 실행될 수 있는지를 나타낸다. 즉 2개의 cpu를 온전히 사용하고 싶다면 이 값을 cfs_period_us의 2배로 설정한다.

cpu.shares

차지할 cpu의 시간 비율 나타낸다. 같은 계층에 있는 cpu.shares 값의 비율에 따라 스케줄러의 cpu에 할당에 사용 될 weight가 결정 된다. 예를들어 cpu.shares가 512인 컨테이너와 1,024인 컨테이너가 있으면 1,024인 컨테이너가 2배 더 많이(시간상) cpu를 차지하게 된다.

memory.limit_in_bytes

최대 메모리 사용량을 나타낸다.

스케줄링

0 <= request <= Node Allocatable & request <= limit <= Infinity

스케줄러는 파드의 cpu와 memory의 requests의 합이 노드의 용량보다 작도록 한다. 이때 노드의 현재 리소스 사용량을 보지 않음에 주의한다. 또한 limit은 스케줄링에 영향을 끼치지 않는다. 즉 노드의 실제 용량보다 크게 overcommit이 가능하다.

QoS(Quality of Service)

노드가 오버커밋된 경우(limit의 합 > 노드 용량)인 경우 노드는 컨테이너를 종료시켜야 할 수도 있다. 실제 리소스의 사용량이 노드의 용량보다 많아진 경우가 그렇다. 이때 어떤 컨테이너를 종료시켜야 할까? 쿠버네티스는 limit과 requests 값을 비교하여 세 가지 QoS Class에 매치시켜 우선순위를 둔다. QoS Class를 정하는 방식은 추후에 유저가 직접 API를 통해 정하는 방식도 구현될 예정이라 한다. 종료 우선순위는 Guaranteed < Burstable < Best-Effort 이다.

Guaranted

limit과 requests가 같은 경우다. 혹은 requests값을 지정하지 않고 limit값을 준 경우 requests값이 limit값과 같게 설정되므로 이 경우 또한 해당된다. 종료 우선순위가 가장 낮기 때문에 컨테이너가 limit을 초과하거나 Garaunted 컨테이너만 남은 상태에서 노드의 용량이 부족한 경우에만 종료 된다.

Burstable

limit이 requests보다 큰 경우다. 혹은 limit을 주지 않고 requests만 준 경우에 해당된다. Best-Effort 컨테이너가 없고 노드의 용량이 부족한 경우에 종료 된다.

Best-Effort

Best-Effort는 최대한 노력하겠다는 의미인데 사실은 노력하지 않겠다는 의미다. 즉 제일 우선순위가 낮다. 노드의 용량이 부족한 경우 최우선으로 종료 된다.

Compressible Resource Guarantees

뒤에 서술하여 미안하지만, 위의 종료 정책은 사실 memory에만 해당된다. cpu 같은 경우 Compressible Resource Guarantees를 따르기 때문이다. cpu는 limit을 초과하게 된 경우에 종료되진 않는다. 대신 노드의 리소스 사용량이 초과된 경우 쓰로틀링에 걸릴 수 있다. 리소스 할당에 있어 cpu는 시간적 개념을 따르고 memory는 공간적 개념을 따르기 때문이라 생각된다.

네임스페이스 리밋 레인지

LimitRange를 통해 cpu, memory의 reqeusts, limit값이 주어지지 않은 경우 기본 값을 지정할 수 있다.

리서치를 위해 사용한 명령어 혹은 Path

/sys/fs/cgroup/cpu/kubepods/

kubectl descirbe nodes {노드명}

docker inspect {컨테이너 명} (CgroupParent 값)

참고

https://kernel.googlesource.com/pub/scm/linux/kernel/git/glommer/memcg/+/cpu_stat/Documentation/cgroups/cpu.txt

https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/resource-qos.md

https://kubernetes.io/ko/docs/setup/production-environment/container-runtimes/

https://kubernetes.io/ko/docs/concepts/configuration/manage-resources-containers/

https://kubernetes.io/ko/docs/tasks/administer-cluster/manage-resources/cpu-default-namespace/

https://kubernetes.io/ko/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/

https://ssup2.github.io/theory_analysis/Kubernetes_Pod/

https://box0830.tistory.com/293

http://jake.dothome.co.kr/bandwidth/

Author: dbgsprw

Link: https://dbgsprw.github.io/2020/10/26/Kubernetes-Container-Resource/

Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.

NextPost >
Poetry를 통한 파이썬 패키지 관리
CATALOG
  1. 1. 컨테이너 리소스, docker, cgroup(control group)
  2. 2. 요청한 값과 실제 cgroup 값 사이의 관계
    1. 2.1. spec.containers[].resources.requests.cpu
    2. 2.2. spec.containers[].resources.limits.cpu
    3. 2.3. spec.containers[].resources.requests.memory
    4. 2.4. spec.containers[].resources.limits.memory
  3. 3. cgroup
    1. 3.1. cpu.cfs_period_us, cpu.cfs_quota_us
    2. 3.2. cpu.shares
    3. 3.3. memory.limit_in_bytes
  4. 4. 스케줄링
  5. 5. QoS(Quality of Service)
    1. 5.1. Guaranted
    2. 5.2. Burstable
    3. 5.3. Best-Effort
    4. 5.4. Compressible Resource Guarantees
  6. 6. 네임스페이스 리밋 레인지
  7. 7. 리서치를 위해 사용한 명령어 혹은 Path
  8. 8. 참고