Search

Resource Requirements & Limits

Created
2023/10/01 02:11
Tags
k8s
CKA
Mumshad Mannambeth
Scheduling

1) About

Kube Scheduler는 Pod를 노드에 배정할 때 Pod가 요구하는 적절한 자원량을 판단하여 최적의 노드에 배치
컨테이너가 요구하는 요청량은 일종의 최소 조건이라고 볼 수 있으며, 한계치는 일종의 최대 조건이라고 볼 수 있음
** kubectl top node ${NODE_NAME}으로 현재 노드의 자원량을 확인할 수 있으며, kubectl describe node ${NODE_NAME}으로 총량 확인 가능
이는 네임스페이스에서 ResourceQuota를 생성할 때와 그 방식이 비슷한데, Pod의 경우 spec.resources에 명시하게 됨
이와 같은 자원에 대한 조건은 Pod가 아닌 컨테이너 단위임을 잊으면 안 됨
apiVersion: v1 kind: Pod metadata: name: pod-sample spec: containers: - name: pod-sample image: pod-sample resources: requests: memory: "4Gi" cpu: 1 limits: memory: "10Gi" cpu: 4
YAML
복사
별도의 처리가 없다면 초기에는 자원 이용 한계치가 적용되어 있지 않기 때문에 필요한 만큼 자원을 소모할 수 있음
이와 같은 형태는 다른 노드에서 동작하는 네이티브 (가상화 되지 않은) 프로세스 혹은 다른 컨테이너들의 동작에 영향을 줄 수 있기 때문에 한계치를 지정할 수 있음
CPU의 경우 만일 한계치를 넘어서는 자원량을 소모하게 되면, Throttling이 걸림
메모리의 경우 만일 한계치를 넘어서는 자원을 소모했을 때, CPU 처럼 Throttling이 걸리는 방식은 아님
메모리는 한계치보다 조금 더 많은 자원을 소모할 수 있는데, 이러한 현상이 지속되면 Pod가 종료되면서 OOM (Out of Memory) 로그를 볼 수 있음

2) CPU

CPU라는 항목에 기재하는 값은 1 뿐만 아니라 0보다 작은 0.1 등의 값도 사용할 수 있는데, 0.1은 100m (milli), 1은 1000m를 의미
즉, CPU에 기재하는 값은 0보다 작아도 되지만 그 실제 값은 1m 아래로는 나타나선 안 됨
또한 CPU의 1이라는 값이 의미하는 바는 AWS의 1개의 vCPU, GCP 및 Azure의 1개의 Core, 다른 시스템의 1개의 Hyper Thread와 동일하다고 볼 수 있음

Behavior

A, B 컨테이너가 있고, CPU는 6개가 있다고 가정
** 대체로는 한계치를 두지 않는 4번이 적절하지만, 꼭 자원을 제한 해야하는 경우에는 한계치를 운용 (사용자가 인프라를 오용하는 것을 막기 위한 용도 등)

1. No Requests / No Limits

요청량도 한계치도 존재하지 않기 때문에 A가 6개의 CPU를 모두 점유할 수 있으며, B는 자원을 소모할 수 없는 상태가 발생할 수 있음

2. No Requests / Limits

요청량이 존재하지 않지만 한계치가 있는 경우엔 쿠버네티스가 요청량을 한계치와 동일하게 설정
만일 A, B의 한계치가 3으로 설정되어 있다면, 두 컨테이너는 각각 3개씩의 자원을 소모

3. Requests / Limits

두 값이 설정되어 있는 경우엔 최소 요청량만큼의 자원을 점유하고 최대 한계치만큼의 자원을 소모할 수 있음
이와 같은 시나리오가 최적으로 보일 수 있겠지만, A가 1 ~ 3 / B가 1 ~ 1로 명시되어 있는 경우엔 6개의 자원 중 2개가 남으며, 만일 A가 모종의 이유로 더 많은 자원을 요구하는 경우에는 남는 자원을 사용할 수 없는 상황이 발생할 수 있음

4. Requests / No Limits

한계치가 없다는 점에서 1번의 상황과 비슷해보일 수 있지만, 1번의 경우는 컨테이너가 요구하는 최소 자원량을 보장할 수 없는 상황이 있을 수 있는데, Requests의 명시가 된 경우 적어도 컨테이너가 요구하는 최소 자원량의 확보는 가능하다는 점에 차이가 있음
따라서 적어도 최소 자원량만큼을 점유하고 남은 자원은 유동적으로 사용됨
** 애초에 노드 내에 자원량에는 한계가 있음을 명심

3) Memory

접미사를 사용할 수도 있고, 숫자를 이용하여 표현할 수도 있음
1G (Gigabyte) = 1,000,000,000 bytes 1M (Megabyte) = 1,000,000 bytes 1K (kilobyte) = 1,000 bytes 1Gi (Gibibyte) = 1,073,741,824 bytes 1Mi (Megibyte) = 1,048,576 bytes 1Ki (Kibibyte) = 1,024 bytes
Plain Text
복사

Behavior

A, B 컨테이너가 있고, 메모리는 6Gi만큼 있다고 가정
** 대체로는 3번이 적절하므로 시스템의 안정성을 위해 요청량과 한계치를 모두 정하는 것이 좋음

1. No Requests / No Limits

CPU의 상황과 마찬가지로 A가 모든 메모리를 소모하고, B는 메모리를 사용할 수 없는 상황이 발생할 수 있음

2. No Requests / Limits

CPU의 상황과 마찬가지로 쿠버네티스가 요청량을 한계치와 동일하게 설정
만일 A, B의 한계치가 3Gi로 설정되어 있다면, 이들의 요청량 역시 3Gi로 설정

3. Requests / Limits

CPU의 상황과 마찬가지로 동작하여, 두 값이 설정되어 있는 경우엔 최소 요청량만큼의 자원을 점유하고 최대 한계치만큼의 자원을 소모할 수 있음
예를 들어 A가 1Gi ~ 3Gi / B가 1Gi ~ 1Gi로 명시되어 있는 경우엔, 이 범위에 해당하는 메모리만 소모

4. Requests / No Limits

CPU에서는 Limits를 지정하지 않는 것이 유휴 자원을 두지 않아서 대체로 좋은 방법이었는데, 이는 연산을 위해 일시적으로만 점유하여 다른 컨테이너가 사용할 수 있기 때문
반면에 메모리의 경우 CPU처럼 일시적인 점유가 아니라 컨테이너가 한 번 점유하면 이 현상이 지속됨
따라서 메모리의 확보가 필요한 경우엔 기존 객체를 종료해야 메모리의 점유가 풀리게 됨
예를 들어 A가 5Gi를 점유하고 있었고 B가 1Gi를 점유하고 있었는데, B가 추가적인 메모리를 요구하는 경우 A가 점유한 메모리를 얻어내는 수 밖에 없고, 이는 정상적으로 구동 중인 A의 일부 종료로 이어짐

4) LimitRange

모든 Pod들이 기본적인 요청량과 한계치를 지정하는 것이 아니라 기본 값을 두는 방식이 없을까?
이는 LimitRange라는 객체로 처리할 수 있으며, 이는 ResourceQuota처럼 네임스페이스 단위의 적용이 가능
** ResourceQuota로 네임스페이스에 가용할 수 있는 자원을 얻고, 내부에서 사용할 수 있는 Pod의 기본 자원을 LimitRange로 명시하는 식으로 운용 가능
apiVersion: v1 kind: LimitRange metadata: name: cpu-and-memory-resource-constraint-sample spec: limits: - type: Container max: memory: "6Gi" cpu: "600m" min: memory: "1Gi" cpu: "100m" default: memory: "4Gi" cpu: "400m" defaultRequest: memory: "2Gi" cpu: "200m"
YAML
복사

5) ResourceQuota

이전 설명에 언급된 적이 있지만, ResourceQuota는 네임스페이스 내에서의 자원 가용량을 지정할 수 있는 객체
apiVersion: v1 kind: ResourceQuota metadata: name: rq-sample namespace: ns-sample spec: hard: pods: "10" requests.cpu: "4" requests.memory: 5Gi limits.cpu: "10" limits.memory: 10Gi
YAML
복사