K8s 환경에서 Pod를 배치할 때 목적에 따라서 특정 node에 배치하고 싶은 상황이 생기게 되는데 이럴 때 고려할 수 있는 것이 nodeSelector, affinity 이다. nodeSelector는 가장 간단하게 특정 node에 pod를 붙일 수 있게 해주는 기능으로 node에 새겨진 label을 기준으로 구별이 가능하다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
위와 같이 spec.nodeSelector 아래에 key: value 형태로 기입해주면 해당 key, value 를 label로 가지는 node에 배치가 되게 된다.
node의 label정보는 아래 kubectl get nodes --show-labels 명령어로 볼 수 있다.
affinity는 nodeSelector의 확장버전이라 생각하면 된다. 좀 더 select를 하는 방법을 다양하게 가져갈 수 있고 required, prefered 와 같이 무조건 지켜야할 조건 혹은 왠만하면 지켜야할 조건등을 표시할 수도 있다.
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
requiredDuringSchedulingIgnoredDuringExecution
required에서 알 수 있듯이 스케줄링시에 무조건 충족이 되어야한다는 의미로 사용이 된다.
위 예제의 설정값을 해석해보면 topology.kubernetes.io/zone이란 key 의 라벨이 존재하고 antarctica-east1 혹은 antarctica-west1 이라는 value를 가지고 있는 node에 배치를 하겠다는 의미이다.
preferredDuringSchedulingIgnoredDuringExecution
preferred에서 알 수 있듯이 왠만하면 지켜야할 조건으로 모두 충족할게 없다면 충족되지 않는 node에라도 배포되게 된다. 또한 weight 기능을 사용해서 여러 조건을 만들고 각 조건을 충족할 때마다 점수를 매겨서 가장 높은 weight가 부과된 node에 배치가 될 수 있도록 조정도 가능하다.
예제를 통해서 보면 node label에 another-node-label-key key값을 가지고 value를 another-node-label-key로 가지는 node를 우선하여 배치하겠다는 의미로 해석할 수 있다.
종합해보면 topology.kubernetes.io/zone key 값에는 antarctica-east1혹은 antarctica-west1 의 value값이 무조건 들어 있어야하고, 해당 조건은 만족하는 node 중에 another-node-label-key key 값에는 another-node-label-value value값을 가지고 있는 node에 우선순위를 두어서 배치를 하겠다는 의미이다.
여기서 2개의 조건 모두 IgnoredDuringExecution이라명명되어 있는데 해당 키워드의 의미는 스케쥴링시에만 고려를 하고 이미 배치가된 상태에서는 node 의 label이 바뀌더라도 그대로 운영을 하겠다는 의미이다.
nodeAffinity뿐 아니라 podAffinity도 존재한다. pod affinity는 이름에서 알 수 있듯이 node scope가 아닌 pod scope에서 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
위 nodeAffinity와 대부분 동일한데 한 가지 차이점이 있다면 topologyKey라는 것이 존재한다는 것이다.
topologyKey는 scope를 조절하는 것이라고 생각하면 되는데 총 3가지의 scope가 존재한다.
AWS EKS 와 같은 Cloud 서비스를 이용하게 되면 최초 Node 생성시에 default로 3가지 topology에서 사용될 label들이 자동으로 기입되게 된다.
보통 general하게 저렇게 사용이되고 따로 label을 추가해서 사용할 수도 있다.