K8S> Affinity와 Anti-Affinity

머성·2022년 8월 5일

CKA 자격증 공부

목록 보기
2/2

Affinity 와 Anti-Affinity

nodeSelector를 사용하면 간편하게 Pod을 특정 라벨을 지닌 Node에만 스케줄링되도록 제약할 수 있다. Affinity와 Anti-Affinity는 제약의 자유도를 확장해 여러 이점을 취할 수 있다:

  • nodeSelector를 사용하면 단순히 Node의 특정 라벨에 대한 제약 조건을 작성할 수 있었다. Affinity와 Anty-Affinity는 더욱 자유로운 제약 조건을 작성할 수 있게 해준다.
  • nodeSelector와는 달리 Affinity/Anti-Affinity를 이용해 작성한 제약 조건은 반드시 절대적일 필요가 없기 때문에 제약 조건을 만족하는 Node가 없다면 스케줄러는 Pod에 부여된 제약 조건을 무시하고 스케줄링 할 수 있다.
  • nodeSelector와는 달리 Node에서 이미 실행 중인 Pod의 라벨을 이용한 제약 조건을 작성하여 Pod 사이의 스케줄링 규칙을 작성할 수 있다.

Node Affinity

Node Affinity를 사용하면 Pod이 특정 조건을 만족하는 Node에 스케줄링되도록 만들 수 있다. Node Affinity로는 다음과 같이 두 가지 종류가 있다:

  • requiredDuringSchedulingIgnoredDuringExecution: 스케줄러는 제약 조건을 만족하는 Node에만 Pod을 할당 할 수 있다.
  • preferredDuringSchedulingIgnoredDuringExecution: 스케줄러는 제약 조건을 만족하는 Node에 우선적으로 Pod을 할당한다. requiredDuringSchedulingIgnoredDuringExecution과는 달리 제약 조건을 만족하는 Node가 없더라도 스케줄러는 Pod을 할당 할 수 있다.

~IgnoredDuringExecution이 의미하는 바는 Pod이 이미 할당된 이후에 Node Affinity가 변경되면 해당 변경 사항이 반영되지 않고 Pod이 그대로 실행된다는 것이다.

Pod의 .spec.affinity.nodeAffinity 필드를 설정하여 NodeAffinity를 설정할 수 있다.

# pods/pod-with-node-affinity.yaml

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: k8s.gcr.io/pause:2.0

위의 예시에서, 다음과 같은 규칙들이 적용되었다:

  • Node는 반드시 값이 antarctica-east1 혹은 antarctica-west1topology.kubernetes.io/zone 라벨이 설정되어있어야 한다.
  • another-node-label-key=another-node-label-value 라벨을 지닌 Node를 선호한다.

operator 필드로는 In, NotIn, Exists, DoesNotExist, Gt 혹은 Lt를 설정할 수 있다.

Note:
만약 nodeSelectornodeAffinity가 동시에 설정되면, 각각의 제약 조건을 모두 만족하는 Node에 스케줄링된다.

만약 nodeAffinity에 대하여 여러개의 nodeSelectorTerms가 존재하는 경우, Node가 하나의 nodeSelectorTerms라도 만족한다면 해당 Node에 스케줄링 될 수 있다.

만약 nodeSelectorTerms에 대하여 여러개의 matchExpressions가 존재하는 경우, 모든 matchExpressions을 만족하는 경우에만 해당 Node에 Pod이 스케줄링 될 수 있다.

Node Affinity Weight

preferredDuringSchedulingIgnoredDuringExecution 타입의 Affinity를 설정할 때, [1, 100] 사이의 값을 가지는 weight를 설정할 수 있다. 스케줄러는 Node가 만족하는 모든 규칙의 weight를 점수에 합산한다. 그리고 Affinity외의 여러 조건들에 대한 점수들과 함께 반영되어 최종적으로 점수가 가장 높은 Node에 Pod을 우선적으로 스케줄링한다.

Inter-Pod Affinity and Anti-Affinity

Inter-Pod (Anti-)Affinity를 사용하면 이미 Node에서 실행 중인 Pod들의 라벨을 사용하여 새로운 Pod의 스케줄링 제약 조건을 설정할 수 있다.

Inter-Pod (Anti-)Affinity을 설정하면 스케줄링에 상당한 오버헤드가 발생한다. 따라서 수백개 이상의 Node들로 구성된 클러스터에서는 사용하지 않는걸 권장한다.

Pod Anti-Affinity는 Node들이 일관된 라벨을 보유하고 있을 때 정상적으로 동작한다. 즉, 클러스터 내의 모든 노드들은 적절할 topologyKey 라벨을 지니고 있어야 한다. 만약 몇몇 Node들이 topologyKey 라벨이 없다면, 의도한 대로 동작하지 않을 수 있다.

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIngnoredDuringExecution:
      - 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: k8s.gcr.io/pause:2.0

References

Affinity and anty-affinity, kubernetes.io
Assign Pods to Nodes using Node Affinity, kubernetes.io

0개의 댓글