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

한 네임스페이스에 메모리 리소스 상한의 기본값을 정의하며, 이를 통해 미리 설정한 메모리 리소스 상한이 해당 네임스페이스의 새로운 파드에 설정되도록 한다.

이 페이지는 네임스페이스에 대한 기본 메모리 요청량(request) 및 상한(limit)을 구성하는 방법을 보여준다.

쿠버네티스 클러스터를 여러 네임스페이스로 나눌 수 있다. 기본 메모리 상한이 설정되어 있는 네임스페이스에 파드를 생성했는데, 해당 파드의 모든 컨테이너에 메모리 상한이 명시되어 있지 않다면, 컨트롤 플레인이 해당 컨테이너에 기본 메모리 상한을 할당한다.

쿠버네티스는 이 문서의 뒷부분에서 설명하는 특정 조건에서 기본 메모리 요청량을 할당한다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

클러스터에 네임스페이스를 생성할 수 있는 권한이 있어야 한다.

클러스터의 각 노드에는 최소 2GiB의 메모리가 있어야 한다.

네임스페이스 생성

이 연습에서 생성한 리소스가 클러스터의 다른 리소스와 격리되도록 네임스페이스를 생성한다.

kubectl create namespace default-mem-example

리밋레인지(LimitRange)와 파드 생성

다음은 예시 리밋레인지에 대한 매니페스트이다. 이 매니페스트는 기본 메모리 요청량 및 기본 메모리 상한을 지정한다.

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-limit-range
spec:
  limits:
  - default:
      memory: 512Mi
    defaultRequest:
      memory: 256Mi
    type: Container

default-mem-example 네임스페이스에 리밋레인지를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults.yaml --namespace=default-mem-example

이제 파드를 default-mem-example 네임스페이스에 생성하고, 해당 파드의 어떤 컨테이너도 자체 메모리 요청량(request)과 상한(limit)을 명시하지 않으면, 컨트롤 플레인이 해당 컨테이너에 메모리 요청량의 기본값(256 MiB)과 상한의 기본값(512 MiB)을 지정한다.

다음은 컨테이너가 하나인 파드의 매니페스트이다. 해당 컨테이너는 메모리 요청량과 상한을 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: default-mem-demo
spec:
  containers:
  - name: default-mem-demo-ctr
    image: nginx

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod.yaml --namespace=default-mem-example

파드에 대한 자세한 정보를 본다.

kubectl get pod default-mem-demo --output=yaml --namespace=default-mem-example

출력 결과는 파드의 컨테이너에 256MiB의 메모리 요청량과 512MiB의 메모리 상한이 있음을 나타낸다. 이것은 리밋레인지에 의해 지정된 기본값이다.

containers:
- image: nginx
  imagePullPolicy: Always
  name: default-mem-demo-ctr
  resources:
    limits:
      memory: 512Mi
    requests:
      memory: 256Mi

파드를 삭제한다.

kubectl delete pod default-mem-demo --namespace=default-mem-example

컨테이너 상한은 지정하고, 요청량을 지정하지 않으면 어떻게 되나?

다음은 컨테이너가 하나인 파드의 매니페스트이다. 해당 컨테이너는 메모리 상한은 지정하지만, 요청량은 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: default-mem-demo-2
spec:
  containers:
  - name: default-mem-demo-2-ctr
    image: nginx
    resources:
      limits:
        memory: "1Gi"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod-2.yaml --namespace=default-mem-example

파드에 대한 자세한 정보를 본다.

kubectl get pod default-mem-demo-2 --output=yaml --namespace=default-mem-example

출력 결과는 컨테이너의 메모리 요청량이 메모리 상한과 일치하도록 설정되었음을 보여준다. 참고로 컨테이너에는 기본 메모리 요청량의 값인 256Mi가 할당되지 않았다.

resources:
  limits:
    memory: 1Gi
  requests:
    memory: 1Gi

컨테이너의 요청량은 지정하고, 상한을 지정하지 않으면 어떻게 되나?

다음은 컨테이너가 하나인 파드의 예시 매니페스트이다. 해당 컨테이너는 메모리 요청량은 지정하지만, 상한은 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: default-mem-demo-3
spec:
  containers:
  - name: default-mem-demo-3-ctr
    image: nginx
    resources:
      requests:
        memory: "128Mi"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-defaults-pod-3.yaml --namespace=default-mem-example

파드 사양을 확인한다.

kubectl get pod default-mem-demo-3 --output=yaml --namespace=default-mem-example

출력을 보면 컨테이너의 매니페스트에 명시한 값대로 컨테이너의 메모리 요청량이 설정된 것을 알 수 있다. 해당 컨테이너의 메모리 상한은 512 MiB로 설정되며, 이는 네임스페이스의 메모리 상한 기본값과 일치한다.

resources:
  limits:
    memory: 512Mi
  requests:
    memory: 128Mi

기본 메모리 상한 및 요청량에 대한 동기

네임스페이스에 리소스 쿼터가 설정되어 있는 경우, 메모리 상한에 기본값을 설정하는 것이 좋다. 다음은 리소스 쿼터가 네임스페이스에 적용하는 세 가지 제한 사항이다.

  • 네임스페이스에서 실행되는 모든 파드에 대해, 모든 컨테이너에 메모리 상한이 있어야 한다. (파드의 모든 컨테이너에 대해 메모리 상한을 지정하면, 쿠버네티스가 파드 내의 컨테이너의 상한을 합산하여 파드-수준 메모리 상한을 추론할 수 있다.)
  • 메모리 상한은 해당 파드가 스케줄링될 노드에 리소스 예약을 적용한다. 해당 네임스페이스의 모든 파드에 대해 예약된 메모리 총량이 지정된 상한을 초과하지 않아야 한다.
  • 해당 네임스페이스의 모든 파드가 실제로 사용하고 있는 메모리의 총량 또한 지정된 상한을 초과하지 않아야 한다.

리밋레인지를 추가할 때에는 다음을 고려해야 한다.

컨테이너를 갖고 있는 해당 네임스페이스의 파드가 자체 메모리 상한을 지정하지 않았다면, 컨트롤 플레인이 해당 컨테이너에 메모리 상한 기본값을 적용하며, 해당 파드는 메모리 리소스쿼터가 적용된 네임스페이스에서 실행되도록 허용될 수 있다.

정리

네임스페이스를 삭제한다.

kubectl delete namespace default-mem-example

다음 내용

클러스터 관리자를 위한 문서

앱 개발자를 위한 문서

2 - 네임스페이스에 대한 기본 CPU 요청량과 상한 구성

한 네임스페이스에 CPU 리소스 상한의 기본값을 정의하며, 이를 통해 미리 설정한 CPU 리소스 상한이 해당 네임스페이스의 새로운 파드에 설정되도록 한다.

이 페이지는 네임스페이스에 대한 기본 CPU 요청량(request) 및 상한(limit)을 구성하는 방법을 보여준다.

쿠버네티스 클러스터를 여러 네임스페이스로 나눌 수 있다. 기본 CPU 상한이 설정되어 있는 네임스페이스에 파드를 생성했는데, 해당 파드의 모든 컨테이너에 CPU 상한이 명시되어 있지 않다면, 컨트롤 플레인이 해당 컨테이너에 기본 CPU 상한을 할당한다.

쿠버네티스는 기본 CPU 사용량을 할당하는데, 이는 이 페이지의 이후 부분에서 설명될 특정 조건 하에서만 수행된다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

클러스터에 네임스페이스를 생성할 수 있는 권한이 있어야 한다.

쿠버네티스에서 “1.0 CPU”가 무엇을 의미하는지 익숙하지 않다면, CPU의 의미를 참조한다.

네임스페이스 생성

이 연습에서 생성한 리소스가 클러스터의 나머지와 격리되도록 네임스페이스를 생성한다.

kubectl create namespace default-cpu-example

리밋레인지(LimitRange)와 파드 생성

다음은 예시 리밋레인지에 대한 매니페스트이다. 이 매니페스트는 기본 CPU 요청량 및 기본 CPU 상한을 지정한다.

apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-limit-range
spec:
  limits:
  - default:
      cpu: 1
    defaultRequest:
      cpu: 0.5
    type: Container

default-cpu-example 네임스페이스에 리밋레인지를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-defaults.yaml --namespace=default-cpu-example

이제 파드를 default-cpu-example 네임스페이스에 생성하고, 해당 파드의 어떤 컨테이너도 자체 CPU 요청량(request)과 상한(limit)을 명시하지 않으면, 컨트롤 플레인이 해당 컨테이너에 CPU 요청량의 기본값(0.5)과 상한의 기본값(1)을 지정한다.

다음은 컨테이너가 하나인 파드의 매니페스트이다. 해당 컨테이너는 CPU 요청량과 상한을 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: default-cpu-demo
spec:
  containers:
  - name: default-cpu-demo-ctr
    image: nginx

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-defaults-pod.yaml --namespace=default-cpu-example

파드의 사양을 확인한다.

kubectl get pod default-cpu-demo --output=yaml --namespace=default-cpu-example

출력을 보면 파드 내 유일한 컨테이너의 CPU 요청량이 500m cpu("500 밀리cpu"로 읽을 수 있음)이고, CPU 상한이 1 cpu임을 알 수 있다. 이것은 리밋레인지에 의해 지정된 기본값이다.

containers:
- image: nginx
  imagePullPolicy: Always
  name: default-cpu-demo-ctr
  resources:
    limits:
      cpu: "1"
    requests:
      cpu: 500m

컨테이너 상한은 지정하고, 요청량을 지정하지 않으면 어떻게 되나?

다음은 컨테이너가 하나인 파드의 매니페스트이다. 해당 컨테이너는 CPU 상한은 지정하지만, 요청량은 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: default-cpu-demo-2
spec:
  containers:
  - name: default-cpu-demo-2-ctr
    image: nginx
    resources:
      limits:
        cpu: "1"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-defaults-pod-2.yaml --namespace=default-cpu-example

생성한 파드의 명세를 확인한다.

kubectl get pod default-cpu-demo-2 --output=yaml --namespace=default-cpu-example

출력 결과는 컨테이너의 CPU 요청량이 CPU 상한과 일치하도록 설정되었음을 보여준다. 참고로 컨테이너에는 CPU 요청량의 기본값인 0.5 cpu가 할당되지 않았다.

resources:
  limits:
    cpu: "1"
  requests:
    cpu: "1"

컨테이너의 요청량은 지정하고, 상한을 지정하지 않으면 어떻게 되나?

다음은 컨테이너가 하나인 파드의 예시 매니페스트이다. 해당 컨테이너는 CPU 요청량은 지정하지만, 상한은 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: default-cpu-demo-3
spec:
  containers:
  - name: default-cpu-demo-3-ctr
    image: nginx
    resources:
      requests:
        cpu: "0.75"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-defaults-pod-3.yaml --namespace=default-cpu-example

생성한 파드의 명세를 확인한다.

kubectl get pod default-cpu-demo-3 --output=yaml --namespace=default-cpu-example

출력을 보면 파드 생성 시 명시한 값대로 컨테이너의 CPU 요청량이 설정된 것을 알 수 있다(다시 말해, 매니페스트와 일치한다). 그러나, 해당 컨테이너의 CPU 상한은 1 cpu로 설정되며, 이는 네임스페이스의 CPU 상한 기본값이다.

resources:
  limits:
    cpu: "1"
  requests:
    cpu: 750m

CPU 상한 및 요청량의 기본값에 대한 동기

네임스페이스에 리소스 쿼터가 설정되어 있는 경우, CPU 상한에 대해 기본값을 설정하는 것이 좋다. 다음은 CPU 리소스 쿼터가 네임스페이스에 적용하는 두 가지 제한 사항이다.

  • 네임스페이스에서 실행되는 모든 파드에 대해, 모든 컨테이너에 CPU 상한이 있어야 한다.
  • CPU 상한은 해당 파드가 스케줄링될 노드에 리소스 예약을 적용한다. 해당 네임스페이스의 모든 파드에 대해 예약된 CPU 총량이 지정된 상한을 초과하지 않아야 한다.

리밋레인지를 추가할 때에는 다음을 고려해야 한다.

컨테이너를 갖고 있는 해당 네임스페이스의 파드가 자체 CPU 상한을 지정하지 않았다면, 컨트롤 플레인이 해당 컨테이너에 CPU 상한 기본값을 적용하며, 해당 파드는 CPU 리소스쿼터가 적용된 네임스페이스에서 실행되도록 허용될 수 있다.

정리

네임스페이스를 삭제한다.

kubectl delete namespace default-cpu-example

다음 내용

클러스터 관리자를 위한 문서

앱 개발자를 위한 문서

3 - 네임스페이스에 대한 메모리의 최소 및 최대 제약 조건 구성

한 네임스페이스 내에서 메모리 리소스 제한의 유효한 범위를 정의하며, 이를 통해 해당 네임스페이스의 새로운 파드가 미리 설정한 범위 안에 들어오도록 한다.

이 페이지는 네임스페이스에서 실행되는 컨테이너가 사용하는 메모리의 최솟값과 최댓값을 설정하는 방법을 보여준다. 리밋레인지(LimitRange) 오브젝트에 최소 및 최대 메모리 값을 지정한다. 파드가 리밋레인지에 의해 부과된 제약 조건을 충족하지 않으면, 네임스페이스에서 생성될 수 없다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

클러스터에 네임스페이스를 생성할 수 있는 권한이 있어야 한다.

클러스터의 각 노드에는 파드가 사용할 수 있는 메모리가 최소 1GiB 이상 있어야 한다.

네임스페이스 생성

이 연습에서 생성한 리소스가 클러스터의 나머지와 격리되도록 네임스페이스를 생성한다.

kubectl create namespace constraints-mem-example

리밋레인지와 파드 생성

다음은 리밋레인지의 예시 매니페스트이다.

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-min-max-demo-lr
spec:
  limits:
  - max:
      memory: 1Gi
    min:
      memory: 500Mi
    type: Container

리밋레인지를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints.yaml --namespace=constraints-mem-example

리밋레인지에 대한 자세한 정보를 본다.

kubectl get limitrange mem-min-max-demo-lr --namespace=constraints-mem-example --output=yaml

출력 결과는 예상대로 메모리의 최소 및 최대 제약 조건을 보여준다. 그러나 참고로 리밋레인지의 구성 파일에 기본값(default)을 지정하지 않아도 자동으로 생성된다.

  limits:
  - default:
      memory: 1Gi
    defaultRequest:
      memory: 1Gi
    max:
      memory: 1Gi
    min:
      memory: 500Mi
    type: Container

이제 constraints-mem-example 네임스페이스에 파드를 생성할 때마다, 쿠버네티스는 다음 단계를 수행한다.

  • 해당 파드의 어떤 컨테이너도 자체 메모리 요청량(request)과 상한(limit)을 명시하지 않으면, 컨트롤 플레인이 해당 컨테이너에 메모리 요청량과 상한의 기본값(default)을 지정한다.

  • 해당 파드의 모든 컨테이너의 메모리 요청량이 최소 500 MiB 이상인지 확인한다.

  • 해당 파드의 모든 컨테이너의 메모리 요청량이 1024 MiB(1 GiB)를 넘지 않는지 확인한다.

다음은 컨테이너가 하나인 파드의 매니페스트이다. 파드 명세 내에, 파드의 유일한 컨테이너는 600 MiB의 메모리 요청량 및 800 MiB의 메모리 상한을 지정하고 있다. 이는 리밋레인지에 의해 부과된 최소 및 최대 메모리 제약 조건을 충족시킨다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-mem-demo
spec:
  containers:
  - name: constraints-mem-demo-ctr
    image: nginx
    resources:
      limits:
        memory: "800Mi"
      requests:
        memory: "600Mi"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod.yaml --namespace=constraints-mem-example

파드가 실행 중이고 컨테이너의 상태가 정상인지 확인한다.

kubectl get pod constraints-mem-demo --namespace=constraints-mem-example

파드에 대한 자세한 정보를 본다.

kubectl get pod constraints-mem-demo --output=yaml --namespace=constraints-mem-example

출력을 보면 파드의 컨테이너의 메모리 요청량이 600 MiB이고 메모리 상한이 800 MiB임을 알 수 있다. 이는 리밋레인지에 의해 해당 네임스페이스에 부과된 제약 조건을 만족시킨다.

resources:
  limits:
     memory: 800Mi
  requests:
    memory: 600Mi

파드를 삭제한다.

kubectl delete pod constraints-mem-demo --namespace=constraints-mem-example

최대 메모리 제약 조건을 초과하는 파드 생성 시도

다음은 컨테이너가 하나인 파드의 매니페스트이다. 컨테이너는 800MiB의 메모리 요청량과 1.5GiB의 메모리 상한을 지정하고 있다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-mem-demo-2
spec:
  containers:
  - name: constraints-mem-demo-2-ctr
    image: nginx
    resources:
      limits:
        memory: "1.5Gi"
      requests:
        memory: "800Mi"

파드 생성을 시도한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-2.yaml --namespace=constraints-mem-example

결과를 보면 파드가 생성되지 않은 것을 확인할 수 있으며, 이는 해당 파드가 정의하고 있는 컨테이너가 허용된 것보다 더 많은 메모리를 요청하고 있기 때문이다.

Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-2.yaml":
pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi.

최소 메모리 요청량을 충족하지 않는 파드 생성 시도

다음은 컨테이너가 하나인 파드의 매니페스트이다. 컨테이너는 100MiB의 메모리 요청량과 800MiB의 메모리 상한을 지정하고 있다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-mem-demo-3
spec:
  containers:
  - name: constraints-mem-demo-3-ctr
    image: nginx
    resources:
      limits:
        memory: "800Mi"
      requests:
        memory: "100Mi"

파드 생성을 시도한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-3.yaml --namespace=constraints-mem-example

결과를 보면 파드가 생성되지 않은 것을 확인할 수 있으며, 이는 해당 파드가 정의하고 있는 컨테이너가 지정된 최저 메모리 요청량보다도 낮은 메모리 요청량을 지정하고 있기 때문이다.

Error from server (Forbidden): error when creating "examples/admin/resource/memory-constraints-pod-3.yaml":
pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi.

메모리 요청량 또는 상한을 지정하지 않은 파드 생성

다음은 컨테이너가 하나인 파드의 매니페스트이다. 해당 컨테이너는 메모리 요청량과 상한을 지정하지 않는다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-mem-demo-4
spec:
  containers:
  - name: constraints-mem-demo-4-ctr
    image: nginx

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/memory-constraints-pod-4.yaml --namespace=constraints-mem-example

파드에 대한 자세한 정보를 본다.

kubectl get pod constraints-mem-demo-4 --namespace=constraints-mem-example --output=yaml

출력을 보면 파드의 유일한 컨테이너에 대한 메모리 요청량이 1 GiB이고 메모리 상한도 1 GiB이다. 이 컨테이너는 어떻게 이런 값을 얻었을까?

resources:
  limits:
    memory: 1Gi
  requests:
    memory: 1Gi

파드가 해당 컨테이너에 대해 메모리 요청량과 상한을 지정하지 않았으므로, 클러스터가 리밋레인지로부터 메모리의 요청량과 상한 기본값을 적용하였다.

이는 곧 파드 정의에서 이 값들을 볼 수 있음을 의미한다. kubectl describe 명령을 사용하여 확인할 수 있다.

# 출력에서 "Requests:" 섹션을 확인한다
kubectl describe pod constraints-mem-demo-4 --namespace=constraints-mem-example

이 시점에서, 파드는 실행 중일 수도 있고 아닐 수도 있다. 이 태스크의 전제 조건은 노드에 최소 1GiB의 메모리가 있어야 한다는 것이다. 각 노드에 1GiB의 메모리만 있는 경우, 노드에 할당할 수 있는 메모리가 1GiB의 메모리 요청량을 수용하기에 충분하지 않을 수 있다. 메모리가 2GiB인 노드를 사용하는 경우에는, 메모리가 1GiB 요청량을 수용하기에 충분할 것이다.

파드를 삭제한다.

kubectl delete pod constraints-mem-demo-4 --namespace=constraints-mem-example

메모리의 최소 및 최대 제약 조건 적용

리밋레인지에 의해 네임스페이스에 부과된 메모리의 최대 및 최소 제약 조건은 파드를 생성하거나 업데이트할 때만 적용된다. 리밋레인지를 변경해도, 이전에 생성된 파드에는 영향을 미치지 않는다.

메모리의 최소 및 최대 제약 조건에 대한 동기

클러스터 관리자는 파드가 사용할 수 있는 메모리 양에 제한을 둘 수 있다. 예를 들면 다음과 같다.

  • 클러스터의 각 노드에는 2GiB의 메모리가 있다. 클러스터의 어떤 노드도 2GiB 이상의 요청량을 지원할 수 없으므로, 2GiB 이상의 메모리를 요청하는 파드를 수락하지 않으려고 한다.

  • 클러스터는 운영 부서와 개발 부서에서 공유한다. 프로덕션 워크로드가 최대 8GiB의 메모리를 소비하도록 하려면, 개발 워크로드를 512MiB로 제한해야 한다. 프로덕션 및 개발을 위해 별도의 네임스페이스를 만들고, 각 네임스페이스에 메모리 제약 조건을 적용한다.

정리

네임스페이스를 삭제한다.

kubectl delete namespace constraints-mem-example

다음 내용

클러스터 관리자를 위한 문서

앱 개발자를 위한 문서

4 - 네임스페이스에 대한 CPU의 최소 및 최대 제약 조건 구성

한 네임스페이스 내에서 CPU 리소스 제한의 유효한 범위를 정의하며, 이를 통해 해당 네임스페이스의 새로운 파드가 미리 설정한 범위 안에 들어오도록 한다.

이 페이지는 네임스페이스에서 컨테이너와 파드가 사용하는 CPU 리소스의 최솟값과 최댓값을 설정하는 방법을 보여준다. 리밋레인지(LimitRange) 오브젝트에 CPU의 최솟값과 최댓값을 지정한다. 리밋레인지에 의해 부과된 제약 조건을 파드가 충족하지 않으면, 해당 네임스페이스에 생성될 수 없다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

클러스터에 네임스페이스를 생성할 수 있는 권한이 있어야 한다.

클러스터의 각 노드는 파드 실행을 위해 적어도 1.0 CPU 이상이 사용 가능해야 한다. 쿠버네티스에서 “1 CPU”가 무엇을 의미하는지 알아보려면 CPU의 의미를 참조한다.

네임스페이스 생성

이 연습에서 생성한 리소스가 클러스터의 나머지와 격리되도록 네임스페이스를 생성한다.

kubectl create namespace constraints-cpu-example

리밋레인지와 파드 생성

다음은 리밋레인지 예제 매니페스트이다.

apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-min-max-demo-lr
spec:
  limits:
  - max:
      cpu: "800m"
    min:
      cpu: "200m"
    type: Container

리밋레인지를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-constraints.yaml --namespace=constraints-cpu-example

리밋레인지에 대한 자세한 정보를 본다.

kubectl get limitrange cpu-min-max-demo-lr --output=yaml --namespace=constraints-cpu-example

출력 결과는 예상대로 CPU의 최소와 최대 제약 조건을 보여준다. 그러나 참고로 리밋레인지에 대한 구성 파일에 기본값을 지정하지 않아도 자동으로 생성된다.

limits:
- default:
    cpu: 800m
  defaultRequest:
    cpu: 800m
  max:
    cpu: 800m
  min:
    cpu: 200m
  type: Container

이제 constraints-cpu-example 네임스페이스에 파드를 생성할 때마다(또는 다른 쿠버네티스 API 클라이언트가 동일한 파드를 생성할 때마다), 쿠버네티스는 다음 단계를 수행한다.

  • 해당 파드의 어떤 컨테이너도 자체 CPU 요청량(request)과 상한(limit)을 명시하지 않으면, 컨트롤 플레인이 해당 컨테이너에 CPU 요청량과 상한의 기본값(default)을 지정한다.

  • 해당 파드의 모든 컨테이너가 200 millicpu 이상의 CPU 요청량을 지정하는지 확인한다.

  • 해당 파드의 모든 컨테이너가 800 millicpu 이하의 CPU 상한을 지정하는지 확인한다.

다음은 컨테이너가 하나인 파드의 매니페스트이다. 컨테이너 매니페스트는 500 millicpu의 CPU 요청량 및 800 millicpu의 CPU 상한을 지정하고 있다. 이는 이 네임스페이스의 리밋레인지에 의해 부과된 CPU의 최소와 최대 제약 조건을 충족시킨다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-cpu-demo
spec:
  containers:
  - name: constraints-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        cpu: "800m"
      requests:
        cpu: "500m"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-constraints-pod.yaml --namespace=constraints-cpu-example

파드가 실행 중이고 컨테이너의 상태가 정상인지 확인한다.

kubectl get pod constraints-cpu-demo --namespace=constraints-cpu-example

파드에 대한 자세한 정보를 본다.

kubectl get pod constraints-cpu-demo --output=yaml --namespace=constraints-cpu-example

출력 결과는 파드 내 유일한 컨테이너의 CPU 요청량이 500 millicpu이고, CPU 상한이 800 millicpu임을 나타낸다. 이는 리밋레인지에 의해 부과된 제약 조건을 만족시킨다.

resources:
  limits:
    cpu: 800m
  requests:
    cpu: 500m

파드 삭제

kubectl delete pod constraints-cpu-demo --namespace=constraints-cpu-example

CPU 최대 제약 조건을 초과하는 파드 생성 시도

다음은 컨테이너가 하나인 파드의 매니페스트이다. 컨테이너는 500 millicpu의 CPU 요청량과 1.5 cpu의 CPU 상한을 지정하고 있다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-cpu-demo-2
spec:
  containers:
  - name: constraints-cpu-demo-2-ctr
    image: nginx
    resources:
      limits:
        cpu: "1.5"
      requests:
        cpu: "500m"

파드 생성을 시도한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-constraints-pod-2.yaml --namespace=constraints-cpu-example

결과를 보면 파드가 생성되지 않은 것을 확인할 수 있으며, 이는 해당 파드가 수용 불가능한 컨테이너를 정의하고 있기 때문이다. 해당 컨테이너가 수용 불가능한 이유는 너무 큰 CPU 상한을 지정하고 있기 때문이다.

Error from server (Forbidden): error when creating "examples/admin/resource/cpu-constraints-pod-2.yaml":
pods "constraints-cpu-demo-2" is forbidden: maximum cpu usage per Container is 800m, but limit is 1500m.

최소 CPU 요청량을 충족하지 않는 파드 생성 시도

다음은 컨테이너가 하나인 파드의 매니페스트이다. 컨테이너는 100 millicpu의 CPU 요청량과 800 millicpu의 CPU 상한을 지정하고 있다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-cpu-demo-3
spec:
  containers:
  - name: constraints-cpu-demo-3-ctr
    image: nginx
    resources:
      limits:
        cpu: "800m"
      requests:
        cpu: "100m"

파드 생성을 시도한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-constraints-pod-3.yaml --namespace=constraints-cpu-example

결과를 보면 파드가 생성되지 않은 것을 확인할 수 있으며, 이는 해당 파드가 수용 불가능한 컨테이너를 정의하고 있기 때문이다. 해당 컨테이너가 수용 불가능한 이유는 지정된 최저 CPU 요청량보다도 낮은 CPU 요청량을 지정하고 있기 때문이다.

Error from server (Forbidden): error when creating "examples/admin/resource/cpu-constraints-pod-3.yaml":
pods "constraints-cpu-demo-3" is forbidden: minimum cpu usage per Container is 200m, but request is 100m.

CPU 요청량 또는 상한을 지정하지 않은 파드 생성

다음은 컨테이너가 하나인 파드의 매니페스트이다. 컨테이너는 CPU 요청량을 지정하지 않았으며, CPU 상한도 지정하지 않았다.

apiVersion: v1
kind: Pod
metadata:
  name: constraints-cpu-demo-4
spec:
  containers:
  - name: constraints-cpu-demo-4-ctr
    image: vish/stress

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/cpu-constraints-pod-4.yaml --namespace=constraints-cpu-example

파드에 대한 자세한 정보를 본다.

kubectl get pod constraints-cpu-demo-4 --namespace=constraints-cpu-example --output=yaml

출력을 보면 파드의 유일한 컨테이너에 대한 CPU 요청량이 800 millicpu이고, CPU 상한이 800 millicpu이다. 이 컨테이너는 어떻게 이런 값을 얻었을까?

resources:
  limits:
    cpu: 800m
  requests:
    cpu: 800m

컨테이너가 자체 CPU 요청량과 상한을 지정하지 않았으므로, 컨테이너가 이 네임스페이스에 대해 리밋레인지로부터 CPU 요청량과 상한의 기본값을 적용했다.

이 시점에서, 파드는 실행 중일 수도 있고 아닐 수도 있다. 이 태스크의 전제 조건은 노드에 1 CPU 이상 사용 가능해야 한다는 것이다. 각 노드에 1 CPU만 있는 경우, 노드에 할당할 수 있는 CPU가 800 millicpu의 요청량을 수용하기에 충분하지 않을 수 있다. 2 CPU인 노드를 사용하는 경우에는, CPU가 800 millicpu 요청량을 수용하기에 충분할 것이다.

파드를 삭제한다.

kubectl delete pod constraints-cpu-demo-4 --namespace=constraints-cpu-example

CPU의 최소 및 최대 제약 조건의 적용

리밋레인지에 의해 네임스페이스에 부과된 CPU의 최대 및 최소 제약 조건은 파드를 생성하거나 업데이트할 때만 적용된다. 리밋레인지를 변경해도, 이전에 생성된 파드에는 영향을 미치지 않는다.

CPU의 최소 및 최대 제약 조건에 대한 동기

클러스터 관리자는 파드가 사용할 수 있는 CPU 리소스에 제한을 둘 수 있다. 예를 들면 다음과 같다.

  • 클러스터의 각 노드에는 2 CPU가 있다. 클러스터의 어떤 노드도 요청량을 지원할 수 없기 때문에, 2 CPU 이상을 요청하는 파드를 수락하지 않으려고 한다.

  • 클러스터는 프로덕션과 개발 부서에서 공유한다. 프로덕션 워크로드가 최대 3 CPU를 소비하도록 하고 싶지만, 개발 워크로드는 1 CPU로 제한하려고 한다. 프로덕션과 개발을 위해 별도의 네임스페이스를 생성하고, 각 네임스페이스에 CPU 제약 조건을 적용한다.

정리

네임스페이스를 삭제한다.

kubectl delete namespace constraints-cpu-example

다음 내용

클러스터 관리자를 위한 문서

앱 개발자를 위한 문서

5 - 네임스페이스에 대한 메모리 및 CPU 쿼터 구성

한 네임스페이스에 대한 총 메모리 및 CPU 자원 상한을 정의한다.

이 페이지는 네임스페이스에서 실행 중인 모든 파드가 사용할 수 있는 총 메모리 및 CPU 양에 대한 쿼터를 설정하는 방법을 보여준다. 리소스쿼터(ResourceQuota) 오브젝트에 쿼터를 지정할 수 있다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

클러스터에 네임스페이스를 생성할 수 있는 권한이 있어야 한다.

클러스터의 각 노드에는 최소 1GiB의 메모리가 있어야 한다.

네임스페이스 생성

이 연습에서 생성한 리소스가 클러스터의 나머지와 격리되도록 네임스페이스를 생성한다.

kubectl create namespace quota-mem-cpu-example

리소스쿼터 생성

다음은 예시 리소스쿼터 오브젝트에 대한 매니페스트이다.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-demo
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

리소스쿼터를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/quota-mem-cpu.yaml --namespace=quota-mem-cpu-example

리소스쿼터에 대한 자세한 정보를 본다.

kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml

리소스쿼터는 이러한 요구 사항을 quota-mem-cpu-example 네임스페이스에 배치한다.

  • 네임스페이스의 모든 파드에 대해, 각 컨테이너에는 메모리 요청량(request), 메모리 상한(limit), CPU 요청량 및 CPU 상한이 있어야 한다.
  • 네임스페이스의 모든 파드에 대한 총 메모리 요청량은 1GiB를 초과하지 않아야 한다.
  • 네임스페이스의 모든 파드에 대한 총 메모리 상한은 2GiB를 초과하지 않아야 한다.
  • 네임스페이스의 모든 파드에 대한 총 CPU 요청량은 1 cpu를 초과해서는 안된다.
  • 네임스페이스의 모든 파드에 대한 총 CPU 상한은 2 cpu를 초과해서는 안된다.

쿠버네티스에서 “1 CPU”가 무엇을 의미하는지 알아보려면 CPU의 의미를 참조한다.

파드 생성

다음은 예시 파드에 대한 매니페스트이다.

apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-demo
spec:
  containers:
  - name: quota-mem-cpu-demo-ctr
    image: nginx
    resources:
      limits:
        memory: "800Mi"
        cpu: "800m"
      requests:
        memory: "600Mi"
        cpu: "400m"

파드를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/quota-mem-cpu-pod.yaml --namespace=quota-mem-cpu-example

파드가 실행 중이고 파드의 (유일한) 컨테이너의 상태가 정상인지 확인한다.

kubectl get pod quota-mem-cpu-demo --namespace=quota-mem-cpu-example

다시 한 번, 리소스쿼터에 대한 자세한 정보를 본다.

kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml

출력 결과는 쿼터와 사용된 쿼터를 함께 보여준다. 파드의 메모리와 CPU 요청량 및 상한이 쿼터를 초과하지 않은 것을 볼 수 있다.

status:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
  used:
    limits.cpu: 800m
    limits.memory: 800Mi
    requests.cpu: 400m
    requests.memory: 600Mi

jq 도구가 설치되어 있으면, (JSONPath를 사용하여) used 값만을 질의 하고, 정돈된 상태로 출력할 수 있다. 예시는 다음과 같다.

kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example -o jsonpath='{ .status.used }' | jq .

두 번째 파드 생성 시도

다음은 두 번째 파드에 대한 매니페스트이다.

apiVersion: v1
kind: Pod
metadata:
  name: quota-mem-cpu-demo-2
spec:
  containers:
  - name: quota-mem-cpu-demo-2-ctr
    image: redis
    resources:
      limits:
        memory: "1Gi"
        cpu: "800m"
      requests:
        memory: "700Mi"
        cpu: "400m"

매니페스트에서, 파드의 메모리 요청량이 700MiB임을 알 수 있다. 사용된 메모리 요청량과 이 새 메모리 요청량의 합계가 메모리 요청량 쿼터를 초과함에 유의한다(600 MiB + 700 MiB > 1 GiB).

파드 생성을 시도한다.

kubectl apply -f https://k8s.io/examples/admin/resource/quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example

두 번째 파드는 생성되지 않는다. 출력 결과는 두 번째 파드를 생성하면 메모리 요청량의 총 합계가 메모리 요청량 쿼터를 초과함을 보여준다.

Error from server (Forbidden): error when creating "examples/admin/resource/quota-mem-cpu-pod-2.yaml":
pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo,
requested: requests.memory=700Mi,used: requests.memory=600Mi, limited: requests.memory=1Gi

토론

이 연습에서 보았듯이, 리소스쿼터를 사용하여 네임스페이스에서 실행 중인 모든 파드에 대한 메모리 요청량의 총 합계를 제한할 수 있다. 메모리 상한, CPU 요청량 및 CPU 상한의 총 합계를 제한할 수도 있다.

네임스페이스 내의 총 자원을 관리하는 것 대신, 개별 파드 또는 파드 내의 컨테이너별로 제한하고 싶을 수도 있다. 이러한 종류의 제한을 걸려면, 리밋레인지(LimitRange)를 사용한다.

정리

네임스페이스를 삭제한다.

kubectl delete namespace quota-mem-cpu-example

다음 내용

클러스터 관리자를 위한 문서

앱 개발자를 위한 문서

6 - 네임스페이스에 대한 파드 쿼터 구성

한 네임스페이스 내에 만들 수 있는 파드의 수를 제한한다.

이 페이지는 네임스페이스에서 실행할 수 있는 총 파드 수에 대한 쿼터를 설정하는 방법을 보여준다. 리소스쿼터(ResourceQuota) 오브젝트에 쿼터를 지정할 수 있다.

시작하기 전에

쿠버네티스 클러스터가 필요하고, kubectl 커맨드-라인 툴이 클러스터와 통신할 수 있도록 설정되어 있어야 한다. 이 튜토리얼은 컨트롤 플레인 호스트가 아닌 노드가 적어도 2개 포함된 클러스터에서 실행하는 것을 추천한다. 만약, 아직 클러스터를 가지고 있지 않다면, minikube를 사용해서 생성하거나 다음 쿠버네티스 플레이그라운드 중 하나를 사용할 수 있다.

클러스터에 네임스페이스를 생성할 수 있는 권한이 있어야 한다.

네임스페이스 생성

이 실습에서 생성한 리소스가 클러스터의 나머지와 격리되도록 네임스페이스를 생성한다.

kubectl create namespace quota-pod-example

리소스쿼터 생성

다음은 예시 리소스쿼터 오브젝트에 대한 매니페스트이다.

apiVersion: v1
kind: ResourceQuota
metadata:
  name: pod-demo
spec:
  hard:
    pods: "2"

리소스쿼터를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/quota-pod.yaml --namespace=quota-pod-example

리소스쿼터에 대한 자세한 정보를 본다.

kubectl get resourcequota pod-demo --namespace=quota-pod-example --output=yaml

출력 결과는 네임스페이스에 두 개의 파드 쿼터가 있고, 현재 파드가 없음을 보여준다. 즉, 쿼터 중 어느 것도 사용되지 않았다.

spec:
  hard:
    pods: "2"
status:
  hard:
    pods: "2"
  used:
    pods: "0"

다음은 디플로이먼트(Deployment)에 대한 예시 매니페스트이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: pod-quota-demo
spec:
  selector:
    matchLabels:
      purpose: quota-demo
  replicas: 3
  template:
    metadata:
      labels:
        purpose: quota-demo
    spec:
      containers:
      - name: pod-quota-demo
        image: nginx

매니페스트에서, replicas: 3 은 쿠버네티스가 모두 동일한 애플리케이션을 실행하는 세 개의 새로운 파드를 만들도록 지시한다.

디플로이먼트를 생성한다.

kubectl apply -f https://k8s.io/examples/admin/resource/quota-pod-deployment.yaml --namespace=quota-pod-example

디플로이먼트에 대한 자세한 정보를 본다.

kubectl get deployment pod-quota-demo --namespace=quota-pod-example --output=yaml

출력을 보면 디플로이먼트가 3개의 레플리카를 정의하고 있음에도, 앞서 설정한 쿼터로 인해 2개의 파드만 생성되었음을 보여준다.

spec:
  ...
  replicas: 3
...
status:
  availableReplicas: 2
...
lastUpdateTime: 2021-04-02T20:57:05Z
    message: 'unable to create pods: pods "pod-quota-demo-1650323038-" is forbidden:
      exceeded quota: pod-demo, requested: pods=1, used: pods=2, limited: pods=2'

리소스 선택

이 예제에서는 총 파드 수를 제한하는 리소스쿼터를 정의하였다. 하지만, 다른 종류의 오브젝트의 총 수를 제한할 수도 있다. 예를 들어, 한 네임스페이스에 존재할 수 있는 크론잡의 총 수를 제한할 수 있다.

정리

네임스페이스를 삭제한다.

kubectl delete namespace quota-pod-example

다음 내용

클러스터 관리자를 위한 문서

앱 개발자를 위한 문서