nodeSelector를 사용하면 간편하게 Pod을 특정 라벨을 지닌 Node에만 스케줄링되도록 제약할 수 있다. Affinity와 Anti-Affinity는 제약의 자유도를 확장해 여러 이점을 취할 수 있다:
nodeSelector를 사용하면 단순히 Node의 특정 라벨에 대한 제약 조건을 작성할 수 있었다. Affinity와 Anty-Affinity는 더욱 자유로운 제약 조건을 작성할 수 있게 해준다.nodeSelector와는 달리 Affinity/Anti-Affinity를 이용해 작성한 제약 조건은 반드시 절대적일 필요가 없기 때문에 제약 조건을 만족하는 Node가 없다면 스케줄러는 Pod에 부여된 제약 조건을 무시하고 스케줄링 할 수 있다.nodeSelector와는 달리 Node에서 이미 실행 중인 Pod의 라벨을 이용한 제약 조건을 작성하여 Pod 사이의 스케줄링 규칙을 작성할 수 있다.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
위의 예시에서, 다음과 같은 규칙들이 적용되었다:
antarctica-east1 혹은 antarctica-west1인 topology.kubernetes.io/zone 라벨이 설정되어있어야 한다.another-node-label-key=another-node-label-value 라벨을 지닌 Node를 선호한다.operator 필드로는 In, NotIn, Exists, DoesNotExist, Gt 혹은 Lt를 설정할 수 있다.
Note:
만약nodeSelector와nodeAffinity가 동시에 설정되면, 각각의 제약 조건을 모두 만족하는 Node에 스케줄링된다.만약
nodeAffinity에 대하여 여러개의nodeSelectorTerms가 존재하는 경우, Node가 하나의nodeSelectorTerms라도 만족한다면 해당 Node에 스케줄링 될 수 있다.만약
nodeSelectorTerms에 대하여 여러개의matchExpressions가 존재하는 경우, 모든matchExpressions을 만족하는 경우에만 해당 Node에 Pod이 스케줄링 될 수 있다.
preferredDuringSchedulingIgnoredDuringExecution 타입의 Affinity를 설정할 때, [1, 100] 사이의 값을 가지는 weight를 설정할 수 있다. 스케줄러는 Node가 만족하는 모든 규칙의 weight를 점수에 합산한다. 그리고 Affinity외의 여러 조건들에 대한 점수들과 함께 반영되어 최종적으로 점수가 가장 높은 Node에 Pod을 우선적으로 스케줄링한다.
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
Affinity and anty-affinity, kubernetes.io
Assign Pods to Nodes using Node Affinity, kubernetes.io