Kubernetes(이하 K8s)에 대한 질문 중의 하나가 리소스의 요청량(Request)과 제한량(Limit)이다. 두가지 모두 k8s에서 서비스를 운영할 때 주요한 부분을 담당하고 있어 더 그러한 듯 하다.

본 글에서는 k8s의 리소스 요청량과 제한량에 대해 자주 질문 되는 몇가지를 살펴 보도록 하겠다.

Resource Request와 Limit은 무엇인가?

K8s에서 Resource Request와 Limit은 컨테이너에 할당 되는 CPU와 Memory 자원량을 말한다. CPU는 Milicore단위(1,000 Milicore = 1Core)로 Memory는 Mbyte단위로 할당 된다.

Request량은 k8s의 Pod 스케쥴링의 기준이다. K8s의 Pod는 하나 이상의 컨테이너로 구성 됨으로 실제 Request량은 Pod의 모든 컨테이너 Request량을 합친 값이 된다.

Pod 스케쥴링이란 Pod를 어떤 Node에 배치하는가를 결정하는 과정으로 k8s는 Round-Robin방식으로 수행한다. 즉, 첫 번째 Node가 요청되는 Pod Request량을 수용 할 자원을 가지고 있다면 배치(생성)를 하고 만약 그렇지 않다면 다음 차례의 Node에 대해 동일한 작업을 수행하는 방식이다. 만약 모든 Node가 Pod Request량을 수용 할 수 없으면 Pod는 Pending상태로 되며 Pod 스케쥴링을 할 수 없다는 Event가 발생된다. 단, 노드를 지정하여 Pod를 배치 하는 경우는 해당 노드에 대해서만 스케쥴링을 수행 한다.

Limit량은 Pod가 사용하는 자원을 제한한다. 즉 Pod는 Limit량 이상의 자원을 사용 할 수 없다. 만약 Limit량 이상을 사용 한다면 Pod는 비 정상 동작을 할 것이고 최악의 경우 오류 와 함께 종료 될 수 도 있다. Liveness Pobe를 설정 하였다면 k8s가 Pod가 비정상임을 알고 Restart정책에 따라 재시작 또는 재배치(스케쥴링)를 수행한다. Limit 량은 Request량보다 반드시 같거나 커야한다.

Request량을 초과 사용하면 어떻게 되는가?

Pod가 Request량을 초과 하여 사용해도 Limit량을 넘지 않으면 문제는 없다. 다만 Node의 자원이 부족할 경우에는 Request량을 초과 한 Pod는 퇴거(Eviction)의 대상이 된다.

K8s는 Node 자원 부족 시(예:Out of memory) Request량을 초과한 Pod부터 종료를(Terminate) 수행 한다. 이렇게 하는 이유는 자원이 부족한 노드에서 다른 노드로 재배치를 수행하기 위함이다. 만약 모든 Node가 자원이 부족하다면 이 Pod는 Pending상태로 지속 된다.

따라서 서비스 운영 시 자원의 부족에 따른 Pod의 재배치 또는 Pending상태에 대비 하여 복제(Replication)를 설정하거나 주요한 Pod를 특정 Node에 한정하여 배치하는 것을 고려해야 한다.

Limit량을 초과하여 사용하면 어떻게 되는가?

Pod가 Limit량을 초과 하게 되면 overcommitted 상태가 된다. 이 상태에서 CPU는 throttling을 통해 압축 조정된다. 하지만 Memory의 경우 앞서 설명한 것 처럼 Pod는 이상 동작을 보일 수 있고, Node자원 부족 시 퇴거 대상이 된다.

Request와 Limit량 산정은 어떻게 해야 하는가?

사실 용량 산정이 그렇듯이 이 것에 대한 정답은 없다. 하지만 내 경험으로는 Request는 평균 사용량+10%로 Limit은 Peek 사용량 중 최대 사용량을(비 정상 Peek 제외) 기준으로 설정하는 것을 권장한다. 이 경우 사용량은 대부분 Request 이하가 될 것이고 특정 Peek시 에는 Request-Limit구간을 보여 안정된 자원관리를 할 수 있다. 만약 Peek가 장시간 지속되는 경우가 있다면 Pod Scaling을 설정하여 자동으로 스케일링을 하도록 한다.

Request와 Limit량을 설정하지 않으면 어떻게 되는가?

개발 중에는 자원량을 설정하지 않아도 문제는 없다. Request와 Limit량을 설정하지 않으면 Node의 자원 전체를 사용할 수 있다는 의미와 같다. 하지만 운영 시에는 Request량이 설정되어 있지 않으면 k8s는 Node자원을 기준으로 정확한 스케쥴링을 수행 하지 못한다.즉 한 Node에 Pod가 초과 배치 될 수 있고, Node자원 부족시 퇴거 대상이 많아지는 경우가 발생한다. Request량이 설정되지 않은 Pod는 요청량을 초과 사용하고 있다고 k8s가 판단 하기 때문이다. Limit량의 경우도 마찬가지로 Node자원 부족시 퇴거 우선 순위가 된다

Request와 Limit량은 컨테이너에만 설정 하는가?

Request와 Limit량은 네임스페이스(Namespace)에 설정 할 수 있다. 이를 ResourceQutoas라고 하는데 이 경우에는 네임스페이스안의 Pod들이 ResourceQutoa를 초과 할수 없도록 제한한다.

주로 운영 서비스에 적용하는데 한정된 Node(클러스터) 자원 안에서 타 서비스의 자원 사용에 영향을 주지 않도록 한정 할 때 사용한다.

LimitRange라는 것도 있는데 이는 기본(default)와 Max/Min에 해당하는 Request와 Limit량을 네임스페이스에 설정하여 그 안의 Pod의 Request와 Limit량의 범위를 한정하는 데 사용한다. 기본 값은 Request와 Limit량을 설정하지 않은 Pod에 적용되고 Max/Min은 Pod에 설정한 Request와 Limit량에 최대/최소 범위를 한정하는데 사용한다.

끝으로…

K8s에서 자원의 Request와 Limit량 설정은 스케쥴링과 스케일링, 모니터링의 기준이됨으로 매우 중요하다. K8s가 사람의 개입이 없는 동적관리(Dynamic Management)를 수행하여 가용성과 확정성이 뛰어나지만 Request와 Limit량을 적절히 설정하지 못하면 그 혜택을 누릴 수 없는 것이다.

따라서 서비스 운영자는 k8s의 자원 관리에 대한 깊은 이해를 통해 지속적인 최적화를 할 필요가 있다.