클라우드/쿠버네티스

[Kubernetes] 14. 쿠버네티스 Node에 Pod 할당하기 (nodeSelector, Affinity, nodeName)

윤창이 2023. 3. 9. 15:02
728x90

[주의] 개인 공부를 위해 쓴 글이기 때문에 주관적인 내용은 물론, 쓰여진 정보가 틀린 것일 수도 있습니다!

피드백 부탁드립니다. (- -)(_ _) 꾸벅

 


 

Assigning Pods to Nodes

You can constrain a Pod so that it is restricted to run on particular node(s), or to prefer to run on particular nodes. There are several ways to do this and the recommended approaches all use label selectors to facilitate the selection. Often, you do not

kubernetes.io

 

어피니티를 통해 파드를 어디에 배포할지 제약할 수 있다.

 

 특정한 노드 집합에서만 동작하거나 선호하도록 파드를 제한할 수 있다. 보통은 쿠버 스케줄러가 자동으로 합리적인 배치를 수행하기에 이러한 제약 조건을 설정할 필요는 없지만, 예를 들어 SSD가 설치 된 노드 파드가 배포될 필요가 있다던지, 서로 간의 통신이 매우 많은 서로 다른 서비스들의 파드들은 동일한 가용영역(AZ) 배포해야 한다던지 등의 제어해야할 상황이 있을 때 사용한다.

 

 

파드를 특정 노드에 배포하기 위한 제약조건으로 여러가지 방법이 있는데 

  • Node Labels에 매칭되는 nodeSelector 필드
  • Affinity와  Anti-affinity
  • nodeName 필드
  • Pod topology 분재 제약 조건

 


[ Node Labels와 nodeSelector 필드 ]

Node Labels

다른 k8s 오브젝트와 마찬가지로 노드도 레이블을 가질 수 있고 수동으로 추가할 수 있다.

이 뿐만 아니라 클러스터의 모든 노드들은 생성 후 표준화 된 레이블이 자동으로 달리게 되는데, 아래처럼 master 노드를 describe로 확인해보면 알 수 있듯이  노드 레이블들이 kubernetes.io k8s.io 네임스페이스 아래에 정의돼있다.

 

(어노테이션은 레이블과 비슷하게 리소스의 메타데이터를 표시하는 방법이지만 레이블은 리소스를 태깅하고 그룹하는데 쓰는데 비해, 어노테이션이 좀 더 부가적인 정보(설명, 버전 등)를 제공하는 느낌이다)

master@master:~$ kubectl describe node master
Name:               master
Roles:              control-plane,master
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/os=linux
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=master
                    kubernetes.io/os=linux
                    node-role.kubernetes.io/control-plane=
                    node-role.kubernetes.io/master=
                    node.kubernetes.io/exclude-from-external-load-balancers=
Annotations:        flannel.alpha.coreos.com/backend-data: {"VNI":1,"VtepMAC":"12:4b:43:4e:d5:ef"}
                    flannel.alpha.coreos.com/backend-type: vxlan
                    flannel.alpha.coreos.com/kube-subnet-manager: true
                    flannel.alpha.coreos.com/public-ip: 192.168.127.129
                    kubeadm.alpha.kubernetes.io/cri-socket: /var/run/dockershim.sock
                    node.alpha.kubernetes.io/ttl: 0
                    volumes.kubernetes.io/controller-managed-attach-detach: true

 

nodeSelector

위와 같은 레이블을 Selector를 통해 지정하고 특정할 수 있다. 특정 오브젝트가 실행될 노드를 선택하기 위해 사용하는 방법 중 하나이며 가장 간단하면서도 추천하는 형태이다. 

nodeSelector 필드를 추가하고 타겟으로 삼고 싶은 노드가 갖고 있는 Node Label을 명시한다.

apiVersion: v1
kind: Pod
metadata:
  name: eshop-store
spec:
  containers:
  - image: nginx
    name: eshop-store
  nodeSelector:
    disktype: ssd

위와 같이 key-value 쌍으로 라벨을 지정하면, 디스크 타입이 ssd인 노드에만 파드가 배포되는 형태

 


[ Node Affinity - 노드 어피니티 ]

Affinity

개념적으로 nodeSelector와 비슷하지만 선택 로직에 대한 좀 더 많은 제어권을 제공한다.  

  • "소프트(soft)" 또는 "선호사항(preference)" 을 나타내어, 매치되는 노드를 찾지 못한 경우에도 파드를 스케줄링 할 수 있다.
  • 파드 간 어피니티/안티-어피니티는 다른 파드의 레이블을 이용하여 해당 파드를 제한할 수 있게 해 준다.

  • requiredDuringSchedulingIgnoredDuringExecution  (필수로 반드시 지켜야하는)
    규칙이 만족되지 않으면 스케줄러가 파드를 스케줄링 X
    nodeSelector와 유사하지만, 좀 더 표현적인 문법을 제공한다.
  • preferredDuringSchedulingIgnoredDuringExecution  (필수는 아니지만 가급적인)
    스케줄러는 조건을 만족하는 노드를 가급적이면 찾으려고 노력.
    해당되는 노드가 없더라도, 다른 노드에 파드를 스케줄링한다.
  • Operator로 key 값이 values에 어떻게 포함되는지에 대한 다양한 연산 표현방식을 제공한다.
    In, NotIn, Exists, DoesNotExist, Gt, Lt 

apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - antarctica-east1
            - antarctica-west1
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:2.0

 예시에서는 다음의 규칙이 적용된다.

  • 노드는 키가 topology.kubernetes.io/zone인 레이블을 갖고 있어야 하며, 레이블의 값이 antarctica-east1 혹은 antarctica-west1여야 한다.
  • 키가 another-node-label-key이고 값이 another-node-label-value인 레이블을 갖고 있는 노드를 선호한다 .

 

Affinity weight (어피니티 가중치)

 preferredDuringSchedulingIgnoredDuringExecution 어피니티 타입 인스턴스에 대해 1-100 범위의 weight를 명시할 수 있다. 선호하는 노드를 가중치로 표현하여 계산하며 스케줄러는 점수가 가장 높은 노드에 우선적으로 배포한다.

 

      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: label-1
            operator: In
            values:
            - key-1
      - weight: 50
        preference:
          matchExpressions:
          - key: label-2
            operator: In
            values:
            - key-2

각각 label-1:key-1 레이블, label-2:key-2 레이블이 붙은 노드가 각각 있다면, 스케줄러는 각 노드의 weight를 확인한 뒤 해당 노드에 대한 다른 점수에 가중치를 더하고, 최종 점수가 가장 높은 노드에 해당 파드를 스케줄링한다.

 

Pod 간 Affinity와 Anti-Affinity

위에서는 노드에 달린 레이블을 기준으로 어피니티 되었다면, 파드 간 어피니트를 사용하여 각 노드에 이미 실행 중인 다른 파드의 레이블을 기반으로 파드가 스케줄링 될 노드를 제한할 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: registry.k8s.io/pause:2.0
  • 만약 security=S1 파드 레이블이 있는 하나 이상의 기존 파드를 실행하고 있는 노드가 zone=V에 하나 이상 존재한다면, 스케줄러는 파드를 topology.kubernetes.io/zone=V 레이블이 있는 노드에 배치해야 한다.
  • 만약 security=S2 파드 레이블이 있는 파드가 실행되고 있는 zone=R에 다른 노드도 존재한다면, 스케줄러는 topology.kubernetes.io/zone=R 레이블이 있는 노드에는 가급적 해당 파드를 스케줄링하지 않야아 한다.

 


[ nodeName - 노드 네임]

nodeName은 어피니티랑 nodeSelector보다 더 직접적인 노트 선택 방법이다.

apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
  nodeName: kube-01

위 파드는 무조건 kube-01 이라는 노드에서만 실행될 것이다.

  • 만약 명명된 노드가 없으면, 파드가 실행되지 않고 따라서 자동으로 삭제될 수 있다.
  • 만약 명명된 노드에 파드를 수용할 수 있는 리소스가 없는 경우 파드가 실패하고, 그 이유는 다음과 같이 표시된다. 예: OutOfmemory 또는 OutOfcpu.
  • 클라우드 환경의 노드 이름은 항상 예측 가능하거나 안정적인 것은 아니다.

 

728x90