Affinity and Anti-affinity

nodeSelector는 특정 레이블이 있는 노드로 파드를 제한하는 매우 간단한 방법을 제공합니다. Affinity / anti-affinity 기능은 표현할 수 있는 제약 유형을 크게 확장합니다.

주요 개선 사항은 다음과 같습니다.

  • 언어가 더 표현력이 뛰어납니다 (단순 “AND of 정확히 일치”가 아님)

  • 규칙이 엄격한 요구 사항이 아니라 “소프트”/ “기본 설정”임을 나타낼 수 있으므로 스케줄러가 이를 충족 할 수 없는 경우 파드는 계속 예약 됩니다.

  • 노드 자체의 레이블이 아닌 노드 (또는 다른 토폴로지 도메인)에서 실행중인 다른 파드의 레이블에 대해 제한 할 수 있습니다. 이렇게 하면 파드가 함께 배치 될 수 있고 배치 될 수 없는 규칙이 허용됩니다.

Affinity 기능은 “노드 affinity” 및 “파드 간 affinity / anti-affinity”의 두 가지 affinity 유형으로 구성 됩니다. 노드 affinity는 기존의 ‘nodeSelector’와 비슷하지만 (위에 나열된 처음 두 가지 이점이 있음) 위에 나열된 세 번째 항목에 설명데로 파드 간 Affinity / anti-affinity는 노드 레이블이 아닌 파드 레이블에 대해 제한 합니다.

1. Node Affinity

Node affinity는 개념적으로 ‘nodeSelector’와 유사하나 노드의 라벨을 기반으로 파드를 예약 할 수 있는 노드를 제한 할 수 있습니다.

현재 ‘requiredDuringSchedulingIgnoredDuringExecution’과 ‘preferredDuringSchedulingIgnoredDuringExecution’이라는 두 가지 유형의 노드 선호도가 있습니다.

전자는 노드에서 파드를 예약하기 위해 충족 해야하는 규칙을 지정 한다는 점에서 각각 “하드” 및 “소프트”라고 생각할 수 있습니다 (nodeSelector와 비슷 하지만 보다 표현적인 구문 사용). 후자는 스케줄러가 적용하려고 하지만 보장하지는 않는 기본 설정을 지정 합니다.

이름의 “IgnoredDuringExecution” 부분은 nodeSelector가 작동하는 방식과 유사하게 노드의 레이블이 런타임시 변경되어 파드의 affinity 규칙이 더 이상 충족되지 않는 경우 파드가 노드에서 계속 실행된다는 것을 의미 합니다.

따라서 ‘requiredDuringSchedulingIgnoredDuringExecution’의 예는 ‘Intel CPU가 있는 노드에서만 파드 실행’이고 ‘preferredDuringSchedulingIgnoredDuringExecution’의 예는 ‘가용 영역 XYZ에서 이 파드 집합을 실행하려고 시도하지만 가능하지 않은 경우 일부가 다른 곳에서 실행 되도록 허용 하십시오.

Node affinity는 PodSpec에서 필드 affinity의 nodeAffinity 필드로 지정 됩니다.

노드 선호도를 사용하는 파드의 예를 살펴 보겠습니다.

마지막 실습에서와 동일한 노드에 다른 레이블을 만듭니다.

# export the first node name as a variable
export FIRST_NODE_NAME=$(kubectl get nodes -o json | jq -r '.items[0].metadata.name')

kubectl label nodes ${FIRST_NODE_NAME} azname=az1

Pod에 affinity를 만듭니다.

cat <<EoF > ~/environment/pod-with-node-affinity.yaml
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: azname
            operator: In
            values:
            - az1
            - az2
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: us.gcr.io/k8s-artifacts-prod/pause:2.0
EoF

이 node affinity 규칙은 키가 ‘azname’이고 값이 ‘az1’또는 ‘az2’인 라벨이있는 노드에만 파드를 배치 할 수 있음을 나타냅니다. 또한 해당 기준을 충족하는 노드 중에서 키가 ‘another-node-label-key’이고 값이 ‘another-node-label-value’인 라벨이 있는 노드를 선호해야 합니다.

이것을 적용해 봅니다

kubectl apply -f ~/environment/pod-with-node-affinity.yaml

그리고 작동하는지 확인 합니다.

kubectl get pods -o wide

파드를 다른 노드에 배치 할 것이므로 먼저 레이블을 정리하고 파드를 삭제하겠습니다.

kubectl delete -f ~/environment/pod-with-node-affinity.yaml

kubectl label nodes ${FIRST_NODE_NAME} azname-

이제 레이블을 두 번째 노드에 넣습니다.

export SECOND_NODE_NAME=$(kubectl get nodes -o json | jq -r '.items[1].metadata.name')

kubectl label nodes ${SECOND_NODE_NAME} azname=az1
kubectl apply -f ~/environment/pod-with-node-affinity.yaml

그리고 그것이 작동 하는지 확인 합니다.

kubectl get pods -o wide

예제에서 사용되는 연산자 In을 볼 수 있습니다.

새로운 노드 affinity 구문은 In,NotIn,Exists,DoesNotExist,Gt,Lt 연산자를 지원 합니다. NotInDoesNotExist를 사용하여 노드 anti-affinity 동작을 할 수 있습니다.

nodeSelectornodeAffinity를 모두 지정하는 경우 파드가 후보 노드에 예약 되려면 둘 다 충족 되어야 합니다.

nodeAffinity 유형과 연결된 여러 nodeSelectorTerms를 지정하는 경우 nodeSelectorTerms 중 하나가 충족되면 노드에 파드를 예약 할 수 있습니다.

nodeSelectorTerms와 연관된 여러matchExpressions를 지정하는 경우 모든 matchExpressions를 충족 할 수있는 경우에만 파드를 노드에 예약 할 수 있습니다.

파드가 예약 된 노드의 레이블을 제거하거나 변경하면 파드가 제거되지 않습니다. 즉, 선호도 선택은 파드를 예약 할 때만 작동합니다.

preferredDuringSchedulingIgnoredDuringExecution의 가중치 필드는 1-100 범위에 있습니다. 모든 스케줄링 요구 사항 (자원 요청, RequiredDuringScheduling 선호도 표현식 등)을 충족하는 각 노드에 대해 스케줄러는이 필드의 요소를 반복하고 노드가 해당 MatchExpressions과 일치하는 경우 합계에 “가중치”를 추가하여 합계를 계산합니다. 이 점수는 노드에 대한 다른 우선 순위 함수의 점수와 결합됩니다. 총 점수가 가장 높은 노드가 가장 선호 됩니다.

이제 두 파드를 모두 삭제를 합니다.

kubectl delete -f ~/environment/pod-nginx.yaml
kubectl delete -f ~/environment/pod-with-node-affinity.yaml

Last updated