[k8s] Pod 리소스 할당 (requests, limits)

2022. 9. 10. 17:03[ DevOps ]/[ k8s ]

컨테이너 리소스 할당 개론

- 쿠버네티스가 관리하는 리소스는 CPU와 Memory이다.

- 기본적으로 컨테이너 단위로 리소스를 제한한다.

 

리소스를 제한하지 않을 경우 발생할 수 있는 문제

1) starvation

리소스를 제한하지 않으면 해당 노드에 할당된 컨테이너는 노드의 리소스를 전부 다 사용할 수 있다. 따라서 만약 리소스 제한을 두지 않고 특정 호스트에 Pod를 두 개 이상 띄웠을 경우, 하나의 Pod가 노드의 모든 리소스를 사용한다면 새로운 Pod가 스케줄링될 수 없다.

 

2) 보안 관련 이슈

만약 특정 Pod에 보안 관련 버그가 발생해서 해커가 해당 Pod에 디도스 공격을 주어 노드의 모든 리소스를 사용하게 된다면, 다른 Pod들은 스케줄링될 수 없다.

 

 

** 따라서 Pod 하나를 띄우더라도 해당 Pod가 리소스를 얼마나 사용할지를 결정하여 limit를 적절하게 걸어주어야 한다.

 

 

scheduler와 Pod 할당

- scheduler가 새로운 Pod를 워커 노드에 할당할 때, 단순히 가장 적은 수의 Pod를 가진 워커 노드에 새로운 Pod를 할당하는 게 아니라, 각 Pod들이 사용하는 리소스 지원까지도 고려하여 스케줄링한다. 이때 사용되는 것이 yaml의 requests field이다.

 

 

 

Pod Resource 요청(requests), 제한(limits)

1. requests 필드

- Pod를 '실행하기 위한(스케줄링되기 위한) 최소 리소스 양'을 요청한다.

- scheduler가 이를 판단하여 적절히 여유가 있는 노드로 스케줄링한다.

 

2. limits 필드

- Pod가 '사용할 수 있는 최대 리소스 양'을 제한한다.

- '메모리 limit'을 초과해서 사용하는 Pod는 OOM killer에 의해 종료되며 다시 스케줄링된다.

 

 

 


 

실습 예시

1. requests와 limits 모두 설정할 경우

resource-nginx-pod.yaml 파일 생성

apiVersion: v1
kind: Pod
metadata:
  name: resource-demo
spec:
  containers:
  - name: resource-demo-ctr
    image: nginx:1.14
    ports:
    - containerPort: 80
      protocol: TCP
    resources:
      requests:
        cpu: 200m
        memory: 250Mi
      limits:
        cpu: 1
        memory: 500Mi

 

$ kubectl describe pod resource-demo

- limits와 requests가 파일에 명시한 그대로 설정되어 있음을 확인할 수 있다.

 

 

 

2. requests 만 설정할 경우

 

- requests에 설정한 리소스만큼 여유가 있는 노드에 배치해달라는 요청사항이다.

- 위 그림과 같이 kubectl describe pod 커맨드로 확인한 결과 requests만 설정되며 limits는 설정되지 않는다.

 

 

3. limits 만 설정할 경우

 

 

- 해당 컨테이너가 최대 사용할 수 있는 메모리와 CPU를 명시하는 것이다.

- 위 그림과 같이 kubectl describe pod 커맨드로 확인한 결과 limits만 걸고 requests를 걸지 않으면 requests 역시 limits와 같은 양으로 설정된다.

 

 

 

cf. 위 resource-nginx-pod.yaml  파일 설명

- CPU는 core 수 단위로 설정하며 CPU의 core 번호는 0번부터 시작한다.

- 1밀리코어는 1 코어의 1/1000이다. (1 core = 1000m core)

- m을 생략하면 코어의 개수를 의미하도록 되어 있다. 따라서 위 예시에서 requests는 200 밀리코어를 요청했고 limits에서는 1 core로 제한한 것이다.

- 즉, requests에 설정된 CPU는 1/5 core이고 limits에 설정된 CPU는 1 core이다. 따라서 Pod 생성 요청 시 scheduler는 1/5 core와 메모리 250Mi의 여유 공간을 가지고 있는 노드로 스케줄링하며, 해당 컨테이너는 최대 core 1개, 최대 메모리 500Mi 이상을 사용할 수 없다. 특히, 메모리 500Mi 이상을 사용하게 될 경우, OOM 킬러에 의해 종료되며 다시 스케줄링된다.

- 메모리 리소스 할당 시,  IEC 단위를 기준으로 설정해야 한다.

 

 

 

- 즉, 정리하면 쿠버네티스에서는 resource 단위를 표현할 때, 'CPU는 밀리코어(m) 또는 core 개수'로 표현하며 'Memory는 IEC 단위(2진법, 2의 n승 단위)'로 표현한다.

 

 

 

 

** 주의 **

노드의 리소스와 같은 양으로 컨테이너에 리소스를 할당하면 해당 컨테이너는 스케줄링되지 않는다. 해당 노드에서 기본적으로 사용 중인 kubelet과 같은 컨테이너가 이미 있기 때문이다. 이렇게 할당할 경우 Pending 상태로 남게 된다. 만약 requests는 설정하지 않고 limits 만 설정한다면 requests에도 limits과 같은 양으로 설정되기 때문에 requests나 limits 모두 너무 크게 잡으면 안 된다.

 

 

 

 

Reference

- Pod resource 설정 k8s docs, https://kubernetes.io/docs/tasks/configure-pod-container/assign-cpu-resource/