앞서 리소스 스케쥴링 중 Taint와 Tolerant, 그리고 node Affinity를 잠깐 알아보았다.
이번에는 리소스 스케쥴링 전략 중 Affinity를 알아보도록 한다.
Affinity
Pod가 특정 node에 배치되도록 설정하는 정책, Pod에 적용되는 설정
앞서 살펴본 Taint는 Pod가 특정 node에 배치되지 않도록 하는 정책으로, node에 적용하는 설정이였다.
Affinity에는 node를 기준으로 하는 node Affinity와 pod를 기준으로 하는 pod Affinity가 있다.
각 Affinity는 조건의 강도에 따라 2종류로 나뉘게 된다.
- requiredDuringSchedulingIgnoredDuringExecution : 이 조건을 만족하는 node에만 pod를 스케쥴링 (Hard)
- preferredDuringSchedulingIgnoredDuringExecution : 이 조건을 만족하는 node를 우선으로 pod를 스케쥴링, 반드시 해당 node에만 pod가 스케쥴링되는 단계가 아님 (Soft)
node Affinity
pod가 특정 조건을 가진 node에 배치되도록 하는 설정, 이 조건은 label을 기준으로 한다.
nodeSelector와 유사한 개념으로, 간단한 라벨 셀렉터 정도의 기능만 수행하는 nodeSelector에 비해 더 복잡한 연산을 수행할 수 있다.
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.21
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
- hdd
위 manifest에서 nginx pod를 disktype=ssd이거나 disktype=hdd인 라벨이 하나라도 존재하는 노드에 배치하려는 nodeAffinity가 적용되어 있는 것을 볼 수 있다.
연산자는 In, NotIn, Exists, Gt, Lt 등이 존재하며 더 자세한 연산자 내용들은 공식 Docs에서 확인할 수 있다.
학생을 교실에 배정해주는 상황을 예시로 생각해보자.
node Affinity는 마치 한 학생이 자신이 선호하는 교실이 있어서 그 요구사항에 맞는 교실에 배정해주는 것과 같은 원리로 생각할 수 있다.
이와 반대로 pod가 특정 node에 배치되지 않도록하는 설정인 nodeAntiAffinity도 존재한다. 이 경우 조건에는 배치되지 않기를 원하는 node의 내용을 작성해줄 수 있다.
pod Affinity
pod가 특정 조건을 만족하는 다른 pod들이 배치된 node에 배치되도록하는 방법, 배치를 결정하는 기준이 node가 아닌 pod가 된다.
교실 배정의 예시로 보면, 한 학생이 자기가 좋아하는 친구가 있는 반에 배정해주는 것이다.
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
labelSelector:
matchExpressions:
- key: "club"
operator: In
values:
- "science"
topologyKey: "kubernetes.io/hostname"
podAffinity는 크게 2가지 설정으로 구성된다.
- labelSelector : 특정 라벨을 가진 pod를 선택하는 조건문 (좋아하는 친구를 찾는 조건문)
- topologyKey : pod를 배치할 토폴로지 단위, affinity 규칙을 적용할 도메인 (node, host, 가용영역 등)
- 이 topologyKey와 동일한 값을 가진 node는 동일한 토폴로지에 있는 것으로 간주
topologyKey를 바탕으로 pod가 배치될 수 있는 node 후보를 선정한 뒤, labelSelector를 통해 특정 라벨이 있는 pod가 배치된 node를 선택하는 것이다.
클러스터 내의 모든 node들은 topologyKey 조건에 해당하는 라벨을 가지고 있어야 원활하게 pod 배치를 진행할 수 있다.
즉, 위의 예시에 따르면, "club=science" 라벨을 가진 pod(과학동아리 소속의 친구)가 있는 node(hostname)에 배치하는 것이다.
pod AntiAffinity
podAffinity와 반대로 pod가 특정 조건을 만족하는 다른 pod들이 배치된 node에 배치되지 않도록 하는 방법, pod Affinity의 반대 개념으로 볼 수 있다.
교실 배정에서 한 학생이 자기가 좋아하지 않는 친구가 있는 반을 피해서 배치해주는 것이다.
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
labelSelector:
matchExpressions:
- key: "behavior"
operator: In
values:
- "troublemaker"
topologyKey: "kubernetes.io/hostname"
위의 Manifest에 따르면, 이 pod(학생)를 "behavior=troublemaker" 라벨을 가진 pod가 있는 node(hostname)에 배정하지 않는 것이다.
Affinity 조건
만약 이러한 Affinity 조건(labelSelector, topologyKey)이 충족되지 않는다면 어떨까?
topologyKey에 맞는 node들이 없는 경우, pod를 배치할 node가 없게되어 "Pending" 상태로 계속 남게 된다.
다음으로 labelSelector의 경우를 살펴본다.
podAffinity의 labelSelector에 맞는 pod가 없는 경우, 이 pod를 배치할 node를 찾을 수 없게 되므로 "Pending" 상태로 남게 된다.
podAntiAffinity는 어떨까?
podAntiAffinity의 labelSelector에 맞는 pod가 없다는 것, 이는 곧 AntiAffinity 조건을 만족하는 node가 없다는 것이다.
즉, 이 pod는 배치 가능한 상태가 될 것이다.
그리고 requiredDuringSchedulingIgnoredDuringExecution이 아닌 preferredDuringSchedulingIgnoredDuringExecution의 경우에는 Affinity 조건이 만족되지 않는 경우, 조건이 무시되어 다른 node에 배치된다.
이러한 Affinity 조건을 잘 구성하여 유연하게 pod들이 스케쥴링되도록 해야할 것이다.