본문 바로가기

EKS/Kubernetes Intro

Kubernetes - LimitRange

쿠버네티스 환경을 구축 및 운영하다 보면, 

 

실수로 누군가 리소스를 많이 먹는 파드를 생성하여

해당 노드의 리소스를 많이 잡아먹기 시작하여서, 같은 노드에 띄워진 다른 파드 서비스에 문제를 일으킬 수도 있습니다.

 

따라서 Pod의 Resource Limit을 따로 정하지 않았거나,

혹은 기존에 정한 기준 이상으로 부여하는 것을 방지 할 필요가 있습니다.

 

이러한 부분을 통제하는 것이 LimitRagne입니다.

Namespace 단위로 조절할 수 있으며 리소스 타입을 Pod or Container로 주어서

파드 전체의 리소스 리밋이나 컨테이너 리소스에 대한 Default 값이나 Min, Max를 정할 수 있습니다.

 

기본적으로 아래 다큐를 참고하셔서 보셔도 충분합니다.

https://kubernetes.io/ko/docs/tasks/administer-cluster/manage-resources/memory-default-namespace/

 

네임스페이스에 대한 기본 메모리 요청량과 상한 구성

이 페이지는 네임스페이스에 대한 기본 메모리 요청량(request)과 상한(limit)을 구성하는 방법을 보여준다. 기본 메모리 상한이 있는 네임스페이스에서 컨테이너가 생성되고, 컨테이너가 자체 메

kubernetes.io

https://docs.openshift.com/enterprise/3.2/dev_guide/compute_resources.html#dev-viewing-limit-ranges\

 

Quotas and Limit Ranges | Developer Guide | OpenShift Enterprise 3.2

A resource quota, defined by a ResourceQuota object, provides constraints that limit aggregate resource consumption per project. It can limit the quantity of objects that can be created in a project by type, as well as the total amount of compute resources

docs.openshift.com

제가 사용하는 한 예시에 대해서 간단하게 설명드리고 보여드리도록 하겠습니다.

 

저의 경우에는 직접 deployment에서 Pod에 대한 resource limit을 설정합니다.

하지만 해당 네임스페이스에 다른 파드들을 누군가 악의적으로 혹은 실수로 띄울 수 있습니다.

 

따라서 파드 자체에 부여되는 cpu memory를 아래와 같이 설정하여,

deployment.yaml에서 다른 파드가 뜨더라도 아래 기준을 따르도록 설정하였습니다.

 

리소스의 리밋에 대해 제대로 조절하지 않는다면 큰 문제가 발생할 수 있는데,

Pod는 OOM이 되는 순간 파드가 죽게되므로 서비스가 중단될 수 있기 때문입니다.

 

쿠버네티스에서 노드에서 메모리가 부족하게 된다면

Pod Qos가 BestEffort, Burstable, Guranteed 순으로 프로세스가 종료되기 때문입니다.

(실제로 프로세스가 뜰 때, 우선순위가 앞의 등급대로 적용되어 상당히 낮은 순위를 가지게 됩니다.)

 

만약 같은 QoS인 경우에는 메모리 요청 비율이 높은 것 부터 강제로 종료하게 됩니다.

따라서 안정적인 서비스를 하기 위한 파드에 대해서는

deployment.yaml에서 limit = request를 설정하여 Guranteed QoS Class로 만들어 주어야 합니다.

 

QoS 및 다른 리소스에 대해 잘 정리한 블로그가 있어 이 링크 또한 아래를 참고하시면 될 것 같습니다.

yogae.github.io/kubernetes/2019/06/06/kubernetes_manage_resource.html

 

https://yogae.github.io/kubernetes/2019/06/06/kubernetes_manage_resource.html

kubernetes 리소스 관리 06 Jun 2019 포드 컨테이너의 리소스 요청 포드를 만들 때 컨테이너가 필요로 하는 CPU 및 메로리의 양과 한계를 지정할 수 있습니다. apiVerison: v1 kind: Pod metadata: name: requests-pod co

yogae.github.io

 

또한 우선순위에 대한 내용은 아래 공식 다큐를 참고하시면 좋습니다.

kubernetes.io/ko/docs/concepts/configuration/pod-priority-preemption/

 

파드 우선순위(priority)와 선점(preemption)

FEATURE STATE: Kubernetes v1.14 [stable] 파드는 우선순위 를 가질 수 있다. 우선순위는 다른 파드에 대한 상대적인 파드의 중요성을 나타낸다. 파드를 스케줄링할 수 없는 경우, 스케줄러는 우선순위가

kubernetes.io

 

따라서 Resource에 대해 Limit을 주고 관리하는 부분은 굉장히 중요합니다.

(실제로 request / limit을 안정하면 HPA도 설정할 수 없기도 합니다.)

 

Limit Range의 간단한 예시를 보도록 하겠습니다.

저의 경우 deployment.yaml의 경우 2Gi, 1CPU를 사용하지만

istio envoy가 사이드카로 뜨기 때문에 파드는 이보다 많은 리소스 리밋을 가져야합니다.

따라서 정확히 같은 리밋을 가지지 않고 envoy를 고려하여 계산한 후 아래와 같은 리밋을 적용하였습니다.

 

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-range
  namespace: phh-test-bo
spec:
  limits:
  - type: Pod
    max:
      cpu: 1.2
      memory: 2.5Gi
    min:
      cpu: 0.5
      memory: 1Gi

 

위와 같이 설정할 경우 phh-test-bo라는 네임스페이스에 뜨는 파드에 대해서는 해당 설정값을 통해 뜨게됩니다.

 

리소스가 적용되는 작동방식은 아래와 같습니다.

1. Pod Resource의 request / limit이 지정되지 않았다면, LimitRange의 limit의 defaultRequest와 max값을 지정합니다.

2. Request를 지정하였다면, Pod Resource Request값이 LimitRange limit의 min값 이상의 CPU/Memory값 인지 확인합니다.

3. Limit을 지정하였다면, Pod Resource Limit값이 LimitRange limit의 max값 이하의 CPU/Memory값 인지 확인합니다.

 

LimitRange 조건을 제대로 만족하지 않은 채로 Pod를 띄울 경우 아래와 같은 로그를 확인할 수 있습니다.

 

 

이 외에도 Namespace 전체의 리소스제한을 하는 ResourceQuota 또한 존재합니다.

하지만 어떠한 트래픽이 생길지 모르기 때문에 HPA에 대한 Replicas 수나 위의 limit만 잘 조절한다면,

다른 서비스에 영향을 줄 만큼 리소스를 차지할 일이 발생하지 않기 때문에

네임스페이스 자체에서 limit을 걸어버리는 것에 대해서는 심도깊은 고민을 해야할 것으로 생각합니다.

 

LimitRange 그리고 파드 리소스, 우선순위에 대한 내역을 간단하게 알아봤습니다.