System Engineering/Kubernetes

7. K8s Resource / Scheduling

Hopulence 2021. 4. 5. 22:38

1. Resource Management

- Pod를 배포할 때 CPU / Memory / Network Bandwidth(Not supported yet)를 어떻게 할당할지 결정

- Memory는 MegaByte, CPU는 millisecond의 단위 사용 (1,000ms = 1vCore)

- limits는 Pod의 Max Resource, requests는 Min Resource이다

  apiVersion: v1
  kind: Pod
  metadata:
    name: frontend
  spec:
    containers:
    - name: db
      image: mysql
      resources:
        requests:
          memory: "64Mi"
          cpu: "250m"
        limits:
          memory: "128Mi"
          cpu: "500m"
      - name: wp
        image: wordpress
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"
# kubectl describe
# kubectl top {nodes or pods}

 

 - ResourceQuota : Namespace 내 정의되는 CPU와 Memory 전체의 상한

  apiVersion: v1
  kind: ResourceQuota
  metadata:
    name: demo
  spec:
    hard:
      requests.cpu: 500m
      requests.memory: 100Mib
      limits.cpu: 700m
      limits.memory: 500Mib

 - LimitRange : 각 컨테이너에 적용되는 Quota의 범위 

  apiVersion: v1
  kind: LimitRange
  metadata:
    name: demo
  spec:
    limits:
  - default:
      cpu: 600m
      memory: 100Mib
    defaultRequest:
      cpu: 100m
      memory: 50Mib
    max:
      cpu: 1000m
      memory: 200Mib
    min:
      cpu: 10m
      memory: 10Mib
    type: Container

  * Overcommitted State : 컨테이너의 limit의 총합이 물리적인 리소스를 넘어서는 상태(Resource Starving)이다. 이런 상태를 해결하기위해서 K8s에서는 CPU Throttling으로 할당된 CPU를 줄이거나 컨테이너를 Restart 시킨다.

 

 

2. Scheduling

 - Taint : Pod가 특정 노드로 배포되지 않도록 하는 마킹 기능으로 <key>=<value>:<effect>의 형식으로 사용된다.

    ex) Master Node에 Admin 기능의 Pod만 배포되도록 하는 경우

 

 - Toleration : key와 value가 일치할 때 Taint 처리된 Node로 배포가 가능하도록 하는 기능

  apiVersion: v1
  kind: Pod
  metadata:
    name: nginx
    labels:
      env: test
  spec:
    containers:
    - name: nginx
      image: nginx
      imagePullPolicy: IfNotPresent
    tolerations:
    - key: "example-key"
      operator: "Exists"
      effect: "NoSchedule"

  * key가 없으면 그냥 toleration 처리한다.

  ...
  tolerations:
  - operator: "Exists"

 

  • NoSchedule : Taint에 대해서 Tolerate 하지 않음. (Taint 처리 전에 배포된 Pod는 영향을 받지 않는다)
  • PerferNoSchedule : Resource 부족 등의 이유로 다른 Node에 배포가 불가능한 경우에 Toleration
  • NoExecute : Taint에 대해 Torerate 하지 않으며, 기존에 배포된 Pod도 제거하여 다른 Node로 Migration한다. Node를 Upgrade 또는 Restart하기 위해 Pod를 제거할 때 주로 사용

  * tolerationSeconds : Toleration을 적용 받는 기간으로, 이 기간이 지나면 toleration이 사라지고 해당 Pod는 제거

 

# kubectl taint nodes [NODE_NAME] [Key]=[Value]:[Effect]
# kubectl taint nodes node1 key=value:NoSchedule
# kubectl taint node -l myLabel=X dedicated=foo:PreferNoSchedule

 

 

 *  Toleration이 있다고해서 Taint처리된 Node로 반드시 배포되는 것은 아니다.

 

 

 - Node Affiniy

  • Hard affinity : nodeSelector와 같다.
  • Soft affinity : 되도록이면 조건에 맞는 Node로 가중치에 따라 Pod를 배포
  pod-with-node-affinity.yaml docs/concepts/configuration
  apiVersion: v1
  kind: Pod
  metadata:
    name: with-node-affinity
  spec:
    affinity:
      nodeAffinity:
        requiredDuringSchedulingIgnoredDuringExecution: ### Hard affinity
          nodeSelectorTerms:
          - matchExpressions:
            - key: kubernetes.io/e2e-az-name
              operator: In
              values:
              - e2e-az1
              - e2e-az2
          preferredDuringSchedulingIgnoredDuringExecution: ### Soft affinity
          - weight: 1
            preference:
              matchExpressions:
              - key: another-node-label-key
                operatior: In
                values:
                - another-node-label-value
    containers:
    - name: with-node-affinity
      image: k8s.gcr.io/pauser:2.0

 

 - Pod Affinity

 스케쥴러가 Affinity설정을 기반으로 새로운 Pod를 배포할 때, 이미 배포된 Pod의 Label(app=mongodb)과 일치하는 Node를 찾는다. 그리고 해당 Node의 topologyKey(zone:z1)를 받은 뒤, 그 값과 일치하는 Node로 새로운 Pod를 배포한다.

  * topologyKey(Node Label) : Node, Rack, Zone, Region과 같은 Place 개념

 → Node-2의 Label(zone:z1)과 일치하는 Node들이 배포 타겟이 된다.

 

 Pod Affinity는 주로, 아래와 같이 사용하기 위해 설정한다.

  • DB Pod를 Backend Server가 있는 Rack의 Node에 배포하는 경우
  • Front Server를 Backend Server와 동일한 Zone에 배포하는 경우
  • 한 Cluster를 여러 다른 Node들에 분산시켜 배포하는 경우 

 

ex1) 

Inter-pod affinity

  apiVersion: v1
  kind: Pod
  metadata:
    name: with-pod-affinity
  spec:
    affinity:
      podAffinity:
        requiredDuringSchedulingIgnoredDuringExecution:
        - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
          topologyKey: cloud/zone
    containers:
    - name: with-pd-affinity
      image: k8s.gcr.io/pause:2.0

 

ex2) 하나의 Node에 Redis-cache가 2개 이상 중첩되어 배포되지 않도록 하는 경우

  kind: Deployment
  metadata:
    name: redis-cache
  spec:
    selector:
      matchLabels:
        app: store
      replicas: 3
      template:
        metadata:
          labels:
            app: store
        spec:
          affinity:
            podAntiAffinity:
              requiredDuringSchedulingIgnoredDuringExecution:
              - labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - store
              topologyKey: "kubernetes.io/hostname"
          containers:
          - name: redis-server
            iamge: redis:3.2-alpine

 → redis가 배포된 Node의 hostname과 같지 않은 Node에만 해당 Pod를 배포

 

ex3) Nginx가 한 Node에 하나씩 Redis와 같이 Pair로 배포되는 경우

  apiVersion: apps/v1
  kind: Deployment
  metadata:
    name: web-server
  spec:
    selector:
      matchLabels:
        app: web-store
    replicas: 3
    template:
      metadata:
        labels:
          app: web-store
      spec:
        affinity:
          podAntiAffinity:
            requiredDuringSchedulingIgnoredDuringExpression:
            - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web-store
              topologyKey: "kubernetes.io/hostname"
          podAffinity:
            requiredDuringSchedulingIgnoredDuringExpression:
              - labelSelector:
                matchExpressions:
                - key: app
                  operator: In
                  values:
                  - store
                topologyKey: "kubernetes.io/hostname"
          containers:
          - name: web-app
            iamge: nginx:1.12-alpine

 

 

- Anti-affinity

  apiVersion: extensions/v1beta1
  kind: Deployment
  metadata:
    name: frontend
  spec:
    replicas: 5
    template:
      ...
      spec:
        Affinity:
          podAntiAffinty:
            requiredDuringSchedulingIgnoredDuringExecution:
            - topologyKey: kubernetes.io/hostname
              labelSelector:
                matchLabels:
                  app: backend

 

3. Reference

Kubernetes Advanced Workshop
조대협의 블로그