[Kubernetes] Resource Request / Limit
쿠버네티스는 각 Pod별로 작동에 필요한 리소스를 지정하는 옵션이 있다.
지정하는 리소스는 대표적으로 CPU와 Memory가 있으며, 각각 request, limit 이라는 두 값을 입력해 주어야 한다.
- 이 때 CPU의 리소스 단위는 상수(1.0) 혹은 m으로 표현되며 공식문서에 따르면,
: 1.0 == 1개의 CPU 코어
: 100m == 0.1 == 100 밀리코어 라고 한다.
- 메모리의 리소스 단위는 주로 M, G, T, P와 같은 단위를 쓰며 바이트 단위를 의미한다.
: 128M == 128 메가바이트
: 혹은 2의 거듭제곱을 사용하는 방식인 128Mi 등이 있다.
Request VS Limit
Request와 Limit의 차이는 단순하다.
Request는 컨테이너가 생성될 때 노드에 요청하는 리소스의 양.
Limit은 해당 컨테이너가 생성된 후에 사용할 수 있는 리소스의 최대치.
즉, CPU가 request는 0.1, limit은 0.2라면 컨테이너 생성시에는 100 밀리코어만큼의 cpu가 해당 컨테이너에 할당되고, 해당 컨테이너가 작업량이 많아진 경우에는 최대 200 밀리코어만큼 사용 cpu를 사용 가능하다는 뜻.
주의해야 할 점은, CPU나 메모리나 둘 다 request를 너무 과도하게 설정하지 않아야 한다는 것.
더군다나, 만약 메모리가 모자란 경우 Pod가 죽게 되기 때문에 이를 고려해야 한다는 것.
- 이러한 경우중에 overcommitted 라는 상황도 있다. limit의 총 합이 노드의 실제 양보다 많은 경우.
- overcommitted가 발생되어도 컨테이너들이 강제적으로 종료되기 때문에 주의해야 한다.
- kubectl describe nodes로 확인해보면 다음과 같이 쓰여있다. overcommitted를 확인해야 한다는 것.
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.)
CPU Requests CPU Limits Memory Requests Memory Limits
------------ ---------- --------------- -------------
메모리가 모자라서 Pod가 죽는것을 걱정해서 Limit을 과도하게 설정하면 안된다.
그러지 말고 Kubernetes의 QoS 기능을 활용하자.
- QoS? 리소스 할당에 따라 파드별 중요도를 설정할 수 있도록 kubernetes가 자체적으로 지정하는 기능
- 크게 Guaranteed QoS, Burstable QoS, BestEffort QoS가 있다.
이 QoS는 내가 따로 입력해주는 것이 아니라, Pod에 할당되는 resource request/limit에 따라 결정된다.
- Guaranteed : Requeset == Limit 인 pod
- Burstable : Request < Limit 인 pod
- BestEffort : 둘 다 정의되지 않음
내가 Pod에 할당안 리소스에 따라 셋 중 하나의 qosClass 값이 Pod에 지정된다.
Kubernetes는 해당 노드에 리소스가 모자란 경우 Pod를 하나씩 죽이는데, 우선순위가 낮은 Pod부터 죽이게 된다.
이 우선순위는 앞서 말한 QoS에 따라 산정되며, 다음과 같다
- BestEffor << Burstable << Guaranteed
- 물론, 이 QoS 외에도 현재 Pod가 메모리를 얼만큼 사용하고 있는지 라던가, PriorityClass를 사용하는 경우라던가 별도의 경우가 있긴 하다.
결론은, 만약 해당 Pod가 가급적 종료되지 않아야 하는 Pod라면 Guaranteed QoS를 가질 수 있도록 request와 limit을 동일하게 주면 된다는 것.
ps. 사실 각 pod에 얼만큼의 리소스를 할당하는것이 옳은지는 잘 모르겠다. 실제 사용하면서도 이정도면 되겠지? 싶은 만큼 할당하거나, 생각보다 많이 사용한 경우는 파드를 내리고 리소스를 줄여서 다시 올리거나 하는식으로 진행했었다.
대부분 앱의 cpu는 특별한 경우를 제외하고는 0.1~0.2 전후로 설정하면 문제가 없었는데, 메모리가 좀 어렵더라.
ps2. 대부분의 앱을 guaranteed로 하는 것이 관리하기 편한 것 같다. 파드를 늘리다 보면 앞에서 말한 Overcommitted 상황이 발생하는 경우도 있었기에.
이러한 리소스를 그럼 namespace별로 제한하는 방법은?
ResourceQuota를 사용하면 된다.
ResourceQuota?
- Namespace별로 사용할 수 있는 리소스의 최대치를 할당할 수 있다.
- 마찬가지로 requests, limit 값을 줄 수 있고, 해당 네임스페이스 내의 Pod는 정해진 request와 limit 내에서 사용이 가능하다.
: Pod들의 request 총합/ limit 총합이 resourceQuota에 정의된것을 넘으면 안된다는 것.
- 이 외에도, 오브젝트의 총 갯수 : service, secret, configMap, PVC 등의 갯수를 제한할 수도 있고
- 스토리지 클래스의 크기나 PVC 갯수도 제한할 수 있다.
그러면 한 pod가 다 선점해버리면?
이를 막기 위해 LimitRange를 지정하면 된다.
LimitRange?
- Namespace 내의 컨테이너별 리소스의 최대치를 할당할 수 있다.
- default는 컨테이너를 생성할 때 리소스를 지정하지 않으면 갖게되는 기본 limits 값. defaultRequest는 request 값.
- max와 min은 limit의 최소/최대크기.