개발강의정리/DevOps

[데브옵스를 위한 쿠버네티스 마스터] 애플리케이션 스케줄링과 라이프사이클 관리 - 시스템 리소스 요구사항과 제한 설정

nineDeveloper 2021. 1. 19.
728x90

시스템 리소스 요구사항과 제한 설정


컨테이너에서 리소스 요구사항

  • CPU와 메모리는 집합적으로 컴퓨팅 리소스 또는 리소스로 부름

  • CPU 및 메모리 는 각각 자원 유형을 지니며 자원 유형에는 기본 단위를 사용

  • 리소스 요청 설정 방법

    • spec.containers[].resources.requests.cpu
    • spec.containers[].resources.requests.memory
  • 리소스 제한 설정 방법

    • spec.containers[].resources.limits.cpu
    • spec.containers[].resources.limits.memory
  • CPU는 코어 단위로 지정되며 메모리는 바이트 단위로 지정

자원 유형 단위
CPU m(millicpu)
Memory Ti, Gi, Mi, Ki, T, G, M, K

※ CPU 0.5가 있는 컨테이너 는 CPU 1 개를 요구하는 절반의 CPU
※ CPU 0.1은 100m과 동일한 기능
※ K, M, G의 단위는 1000씩 증가
※ Ki, Mi, Gi의 단위는 1024씩 증가

  • 환경에 따른 CPU의 의미
    • 1 AWS vCPU
    • 1 GCP 코어
    • 1 Azure vCore
    • 1 IBM vCPU
    • 1 하이퍼 스레딩 기능이 있는 베어 메탈 인텔 프로세서의 하이퍼 스레드

컨테이너에서 리소스 요구사항 yaml 작성 요령


연습문제

  • 다음 요구사항에 맞는 deploy를 구현하라
    • Deploy name: nginx
    • Image: nginx
    • 최소 요구사항
      • CPU: 1m
      • 메모리: 200Mi
    • 리소스 제한
      • CPU: 2m
      • 메모리: 400Mi
    • Port: 80

nginx Deployment 설정파일 생성

$ kubectl create deploy nginx --image nginx --dry-run=client -o yaml > nginx-deploy.yaml

nginx-deploy.yaml resources 설정 내용 요구사항에 맞게 수정

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources:
          requests:
            memory: "200Mi"
            cpu: "1m"
          limits:
            memory: "400Mi"
            cpu: "2m"
status: {}

kubectl로 생성 및 확인

$ kubectl create -f nginx-deploy.yaml
deployment.apps/nginx created

$ kubectl get pod
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7f87ccf9b7-nsgvg   1/1     Running   0          30s
nginx-7f87ccf9b7-qx59m   1/1     Running   0          30s
nginx-7f87ccf9b7-vqfx4   1/1     Running   0          30s

$ kubectl get pod nginx-7f87ccf9b7-nsgvg -o yaml
...
  resources:
    limits:
      cpu: 2m
      memory: 400Mi
    requests:
      cpu: 1m
      memory: 200Mi
...

limitRanges

https://kubernetes.io/docs/concepts/policy/limit-range/

  • 네임 스페이스에서 포드 또는 컨테이너별로 리소스를 제한하는 정책

  • 리미트 레인지의 기능

    • 네임 스페이스에서 포드나 컨테이너당 최소 및 최대 컴퓨팅 리소스 사용량 제한
    • 네임 스페이스에서 PersistentVolumeClaim 당 최소 및 최대 스토리지 사용량 제한
    • 네임 스페이스에서 리소스에 대한 요청과 제한 사이의 비율 적용
    • 네임 스페이스에서 컴퓨팅 리소스에 대한 디폴트 requests/limit를 설정하고 런타임 중인 컨테이너에 자동으로 입력
  • LimitRange 적용 방법

    • Apiserver 옵션에 --enable-admission-plugins=LimitRange를 설정
  • 컨테이너 수준의 리소스 제한

    • 제한하기 원하는 네임스페이스에 limitrange 리소스 생성
  • 예제 해석

    • 각 컨테이너에 설정
      기준 CPU 메모리
      최대 800m 1Gi
      최소 100m 99Mi
      기본 제한 700m 900Mi
      기본 요구사항 110m 111Mi
  • 리소스 조회

    • kubectl describe limitrange -n 네임스페이스

limit-mem-cpu-per-container.yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-mem-cpu-per-container
spec:
  limits:
  - max:
      cpu: "800m"
      memory: "1Gi"
    min:
      cpu: "100m"
      memory: "99Mi"
    default:
      cpu: "700m"
      memory: "900Mi"
    defaultRequest:
      cpu: "110m"
      memory: "111Mi"
    type: Container
  • 포드 수준의 리소스 제한

    • 제한하기 원하는 네임스페이스에 limitrange 리소스 생성
  • 예제 해석

    • 각 포드에 설정
      기준 CPU 메모리
      최대 2 2Gi
      최소 - -
      기본 - -
      최소 요구사항 - -
  • 리소스 조회

    • kubectl describe limitrange -n 네임스페이스

limit-mem-cpu-per-pod.yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-mem-cpu-per-pod
spec:
  limits:
  - max:
      cpu: "2"
      memory: "2Gi"
    type: Pod
  • 스토리지 리소스 제한

    • 제한하기 원하는 네임스페이스에 limitrange 리소스 생성
  • 예제 해석

    • 각 PVC에 설정
      기준 용량
      최대 2Gi
      최소 1Gi
  • 리소스 조회

    • kubectl describe limitrange -n 네임스페이스

storagelimits.yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: storagelimits
spec:
  limits:
  - type: PersistentVolumeClaim
    max:
      storage: 2Gi
    min:
      storage: 1Gi

실습 1 - limit-mem-cpu-container

limitRange 실습을 하기 전에 limitRange에 대한 설정을 kube-apiserver.yaml 넣어야지 기능이 활성화 됨
manifests 파일을 변경하면 그대로 apiserver에 적용이 됨

kube-apiserver.yaml에 여러가지 옵션들을 줄 수 있음

manifests의 kube-apiserver.yaml에 limitRange 설정 내용 추가

$ sudo vi /etc/kubernetes/manifests/kube-apiserver.yaml

아래와 같이 --enable-admission-plugins 옵션에 LimitRanger 설정 추가
잘못된 설정을 줄 경우 apiserver 가 죽어버림

...
spec:
  containers:
  - command:
    ...
    - --enable-admission-plugins=NodeRestriction,LimitRanger # LimitRanger 설정 추가
    ...

limitrange-demo 네임스페이스 생성

$ kubectl create namespace limitrange-demo
namespace/limitrange-demo created

limit-mem-cpu-container.yaml

apiVersion: v1
kind: LimitRange
metadata:
  name: limit-mem-cpu-per-container
spec:
  limits:
  - max:
      cpu: "800m"
      memory: "1Gi"
    min:
      cpu: "100m"
      memory: "99Mi"
    default:
      cpu: "700m"
      memory: "900Mi"
    defaultRequest:
      cpu: "110m"
      memory: "111Mi"
    type: Container

kubectl 로 URL을 지정하여 생성 & 네임스페이스 연결 후 확인

$ kubectl create -f https://k8s.io/examples/admin/resource/limit-mem-cpu-container.yaml -n limitrange-demo
limitrange/limit-mem-cpu-per-container created

$ kubectl get limitranges -n limitrange-demo
NAME                          CREATED AT
limit-mem-cpu-per-container   2021-01-14T13:06:16Z

$ kubectl describe limitranges -n limitrange-demo
Name:       limit-mem-cpu-per-container
Namespace:  limitrange-demo
Type        Resource  Min   Max   Default Request  Default Limit  Max Limit/Request Ratio
----        --------  ---   ---   ---------------  -------------  -----------------------
Container   memory    99Mi  1Gi   111Mi            900Mi          -
Container   cpu       100m  800m  110m             700m           -

실습 2 - limit-range-pod-1

apiVersion: v1
kind: Pod
metadata:
  name: busybox1
spec:
  containers:
  - name: busybox-cnt01
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt01; sleep 10;done"]
    resources:
      limits:
        memory: 200Mi
        cpu: 500m
      requests:
        memory: 100Mi
        cpu: 100m
  - name: busybox-cnt02
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt02; sleep 10;done"]
    resources:
      requests:
        memory: 100Mi
        cpu: 100m
  - name: busybox-cnt03
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt03; sleep 10;done"]
    resources:
      limits:
        memory: 200Mi
        cpu: 500m
  - name: busybox-cnt04
    image: busybox
    command: ["/bin/sh"]
    args: ["-c", "while true; do echo hello from cnt04; sleep 10;done"]

kubectl 로 URL을 지정하여 생성 & 네임스페이스 연결 후 확인

$ kubectl apply -f https://k8s.io/examples/admin/resource/limit-range-pod-1.yaml -n limitrange-demo
pod/busybox1 created

$ kubectl get pod -n limitrange-demo busybox1
NAME       READY   STATUS    RESTARTS   AGE
busybox1   4/4     Running   0          61s

yaml 설정 내용 상세 확인

$ kubectl get pod -n limitrange-demo busybox1 -o yaml
...
spec:
  containers:
    name: busybox-cnt01
    resources:
      # requests 와 limits 가 설정된대로 잘 생성됨을 확인
      limits:
        cpu: 500m
        memory: 200Mi
      requests:
        cpu: 100m
        memory: 100Mi
...
    name: busybox-cnt02
        resources:
          # requests 만 설정했으므로 limits 는 기본값으로 설정된것을 확인
          limits:
            cpu: 700m
            memory: 900Mi
          requests:
            cpu: 100m
            memory: 100Mi
...
    name: busybox-cnt03
        resources:
          # limits 만 설정했으므로 requests 가 limits 에 맞춰진 것을 확인
          limits:
            cpu: 500m
            memory: 200Mi
          requests:
            cpu: 500m
            memory: 200Mi
...
    name: busybox-cnt04
        resources:
          # requests 와 limits 를 설정하지 않았으므로 둘다 기본값으로 설정된 것을 확인
          limits:
            cpu: 700m
            memory: 900Mi
          requests:
            cpu: 110m
            memory: 111Mi

실습 3 제한된 범위를 벗어나게 생성

$ cp nginx-deploy.yaml limit-test-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
  namespace: limitrange-demo
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources:
          requests:
            memory: "200Mi"
            cpu: "500m" # CPU 설정에 문제가 있도록 수정
          limits:
            memory: "1Gi"
            cpu: "1" # CPU 설정에 문제가 있도록 수정
status: {}

kubectl로 생성

$ kubectl create -f limit-test-deploy.yaml
deployment.apps/nginx created

확인 해보면 리소스 제한 설정에 문제가 있어 만들어지고 있지 않는 것을 확인할 수 있음

$ kubectl get deploy -n limitrange-demo
NAME    READY   UP-TO-DATE   AVAILABLE   AGE
nginx   0/3     0            0           91s

describe로 Events 를 확인 해보면 RelicaSet 을 Scaling 까지는 했지만 만들어 지고 있지 않는 것을 확인할 수 있음

$ kubectl describe deploy -n limitrange-demo
...
Events:
  Type    Reason             Age    From                   Message
  ----    ------             ----   ----                   -------
  Normal  ScalingReplicaSet  2m35s  deployment-controller  Scaled up replica set nginx-767875b7ff to 3

ReplicaSet 을 확인
Container 가 800m으로 설정되어 있는데 limit 가 1로 되어서 문제가 있어 pod 생성이 금지되었다는 것을 확인할 수 있음
limitRanges 를 통해서 정책을 셋팅해두면 정책을 넘어서서 다른사람들이 그 내용을 건드릴 수가 없게 된다
limitRanges 를 변경하면 설정할 수 있지만 RBAC를 활용해 API의 권한을 제한하면 limitRange 를 아무나 변경할 수 없게 할 수 있다

$ kubectl describe rs -n limitrange-demo
...
Events:
  Type     Reason        Age                 From                   Message
  ----     ------        ----                ----                   -------
  Warning  FailedCreate  6m8s                replicaset-controller  Error creating: pods "nginx-767875b7ff-bx72f" is forbidden: maximum cpu usage per Container is 800m, but limit is 1

  ...

  Warning  FailedCreate  40s (x8 over 6m6s)  replicaset-controller  (combined from similar events): Error creating: pods "nginx-767875b7ff-v9dhc" is forbidden: maximum cpu usage per Container is 800m, but limit is 1

ResourceQuata

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/

  • 네임스페이스별 리소스 제한

    • 제한하기 원하는 네임스페이스에 ResourceQuata 리소스 생성
    • 모든 컨테이너에는 CPU, 메모리에 대한 최소요구사항 및 제한 설정이 필요
  • 예제 해석

    • 네임스페이스 내의 모든 컨테이너의 합이 다음을 넘어서는 안됨
      기준 CPU 메모리
      최대 2 2Gi
      최소 요구사항 1 1Gi
  • 리소스 조회

    • kubectl describe resourcequota -n 네임스페이스

mem-cpu-demo.yaml

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

실습

네임스페이스별로 리소스 총량을 제한하는 Quota 설정을 테스트

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/#create-a-namespace

quota-mem-cpu-example 네임스페이스 생성

$ kubectl create namespace quota-mem-cpu-example
namespace/quota-mem-cpu-example created

kubectl 로 생성

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

ResourceQuota 상세 정보 확인
pod 를 만들때 마다 Used 의 숫자가 채워짐
Used 가 모두 차게되면 더이상 할당을 할 수 없게됨

$ kubectl describe resourcequotas -n quota-mem-cpu-example
Name:            mem-cpu-demo
Namespace:       quota-mem-cpu-example
Resource         Used  Hard
--------         ----  ----
limits.cpu       0     2
limits.memory    0     2Gi
requests.cpu     0     1
requests.memory  0     1Gi

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/#create-a-pod

첫번째 pod를 생성

quota-mem-cpu-pod.yaml

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로 생성 및 확인

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

$ kubectl describe resourcequotas -n quota-mem-cpu-example
Name:            mem-cpu-demo
Namespace:       quota-mem-cpu-example
Resource         Used   Hard
--------         ----   ----
limits.cpu       800m   2
limits.memory    800Mi  2Gi
requests.cpu     400m   1
requests.memory  600Mi  1Gi

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/#attempt-to-create-a-second-pod

두번째 pod를 생성

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"

kubectl로 생성 시 quota를 위반해서 생성이 제한되는 것을 확인할 수 있음

$ 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 "https://k8s.io/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
728x90

댓글

💲 추천 글