목차
Resource Requests
Pod를 생성할 때 필요 CPU와 메모리를 지정할 수 있다. 이는 container에 대한 resource request이며, 컨테이너의 최소 CPU나 메모리에 대한 요청이다.
Resource Request를 지정하면 스케줄러는 그 값을 가지고 Pod를 Node에 배치시킬 때 가용한 리소스를 가진 node를 식별해 배치한다.
# pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
labels:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
resources:
requests:
memory: "4Gi"
cpu: 2
YAML
복사
CPU
Resource Request에서 Pod가 실행되기 위해 필요한 최소한의 CPU 양을 정의한다.
CPU는 vCPU(가상 CPU)와 동일시된다, CPU는 1m 이상의 값을 가져야 한다.
1CPU는 1000m에 해당하며, ‘m’은 mili를 의미한다.
Memory
Resource Request에서 Pod가 실행되기 위해 필요한 최소한의 Memory 양을 정의한다.
Mi, Gi 같은 접미사를 이용해 지정할 수 있으며 직접적으로 바이트 값을 지정할 수도 있다.
1 G (Gigabyte) | 1,000,000,000 bytes |
1 M (Megabyte) | 1,000,000 bytes |
1 K (Kilobyte) | 1,000 bytes |
1 Gi (Gibibyte) | 1,073,741,824 bytes |
1 Mi (Mebibyte) | 1,048,576 bytes |
1 Ki (Kibibyte) | 1,024 bytes |
Resource Limits
기본값으로 컨테이너는 Node에서 소비할 수 있는 리소스에 대한 limit가 없다.
Pod의 일부 컨테이너의 사용 CPU나 Memory가 무한정 늘어나면 Node나 다른 리소스 컨테이너의 프로세스를 죽일 수 있다.
따라서 Pod의 리소스 사용에 대한 Limit을 정할 수 있다.
# pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp-color
labels:
name: simple-webapp-color
spec:
containers:
- name: simple-webapp-color
image: simple-webapp-color
ports:
- containerPort: 8080
resources:
requests:
memory: "1Gi"
cpu: 1
limits:
memory: "2Gi"
cpu: 2
YAML
복사
Exceed Limits
Exceeding CPU
•
Pod가 CPU 한도를 초과해 자원을 사용하려는 경우 시스템이 CPU를 조절해 지정 한도를 넘지 않도록 한다.
•
따라서 컨테이너는 Limit 이상으로 리소스를 사용할 수 없다
Exceeding Memory
•
CPU와 달리 Memory는 Limit을 초과한 메모리 리소스를 사용할 수 있다.
•
Pod가 지속적으로 한도를 초과하여 메모리를 사용하려고 하면 Pod는 종료(terminated)된다.
•
describe 명령어나 log를 확인하면 OOM(Out Of Memory) error로 종료되는 것을 볼 수 있다.
Behavior
Default Behavior
•
기본적으로 쿠버네티스는 CPU, Memory에 대한 Request, Limit가 없다
→ 어떤 Pod든 아무 Node에서 원하는만큼의 리소스를 소비하며, 이는 다른 Pod를 질식시키는 현상을 불러 일으킬 수 있다.
Behavior - CPU
클러스터에서 CPU 리소스를 두고 경쟁하는 두 개의 Pod가 있다고 가정 (실제 리소스를 요청하는 것은 컨테이너)
No Requests & No Limits
•
Pod 하나가 노드의 모든 CPU 리소스를 소비할 수 있음
◦
2번 Pod의 리소스 요청을 막음
No Requests & Limits
•
Pod가 자동으로 Request를 Limit과 동일하게 설정함
•
Pod마다 정해진 Limit에 맞는 vCPU가 보장됨
Requests & Limits
•
각 Pod에는 Request에 맞는 vCPU가 보장됨
•
각 Pod의 최대 사용 CPU는 정의된 Limit까지로 제한됨
•
이상적인 시나리오로 보이지만 Pod 1은 CPU 사이클을 더 소비하려하고, Pod 2는 CPU 사이클을 그만큼 소비하려하지 않는 경우가 있을 수 있음
Requests & No Limits
•
시스템에 충분한 CPU 사이클이 있다면 불필요하게 Limit을 설정할 필요가 없음
•
Request가 있어 최소 vCPU는 보장받음과 동시에 Limit이 없기 때문에 Pod마다 CPU 사이클을 최대한 많이 사용할 수 있다.
모든 Pod는 Limit을 가질 필요는 없지만, Request는 정의되어야 실행을 보장받는다.
Behavior - Memory
No Requests & No Limits
•
Pod 하나가 노드의 모든 Memory 리소스를 소비할 수 있음
◦
2번 Pod의 리소스 요청을 막음
No Requests & Limits
•
Pod가 자동으로 Request를 Limit과 동일하게 설정함
•
Pod마다 정해진 Limit에 맞는 Memory가 보장됨
Requests & Limits
•
각 Pod에는 Request에 맞는 Memory가 보장됨
•
각 Pod의 최대 사용 Memory는 정의된 Limit까지로 제한됨
Requests & No Limits
•
각 Pod는 정의된 Request에 따른 Memory가 보장됨
•
어떤 Pod든 Node의 가용한 Memory를 소모할 수 있음
◦
Pod 1이 Pod 2로부터 메모리를 더 요청하면 Pod 2를 죽이는 수밖에 없음
◦
Memory는 CPU와 달리 조절할 수 없기 때문
LimitRange
•
LimitRange를 정의하면 Request나 Limit을 설정하지 않은 컨테이너의 기본값을 정의할 수 있다.
•
Namespace 레벨에서도 적용이 가능하며, 오브젝트로 취급된다.
•
Pod가 생성될 때 LimitRange에 대한 영향을 받으며, 이미 만들어진 Pod는 영향 받지 않는다.
# limit-range-cpu.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-resource-constraint
spec:
limits:
- default: # limit
cpu: 500m
defaultRequest: # request
cpu: 500m
max: # limit
cpu: "1"
min: # request
cpu: 100m
type: Container
YAML
복사
# limit-range-memory.yaml
apiVersion: v1
kind: LimitRange
metadata:
name: memory-resource-constraint
spec:
limits:
- default: # limit
memory: 1Gi
defaultRequest: # request
memory: 1Gi
max: # limit
memory: 1Gi
min: # request
memory: 500Mi
type: Container
YAML
복사
Resource Quotas
•
모든 Pod가 특정 양의 CPU나 Memory를 소비해선 안된다고 한다면 Namespace 레벨에서 Quotas를 생성할 수 있다
•
Resource Quota는 네임스페이스 레벨 객체로, 요청과 한계에 대한 엄격한 제한을 설정하기 위해 생성될 수 있다.
# resource-quota.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: my-resource-quota
spec:
hard:
requests.cpu: 4
requests.memory: 4Gi
limits.cpu: 10
limits.memory: 10Gi
YAML
복사
참고
kube-scheduler는 Pod의 요구 리소스와 Node에 가용한 CPU와 메모리를 파악하여 Pod를 배치한다. 만약 Node에 가용한 리소스가 충분하지 않다면 scheduler는 Pod를 배치하지 않고 Pending 상태를 유지한다. kubectl describe pod 명령어를 통해 확인해보면 CPU 부족에 대한 이벤트를 확인할 수 있다.