참고
- nodeSelector - kubernetes
- affinity & anti-affinity - kubernetes
- taints & tolerations - kubernetes
- Node Scheduling - 문타리
- 29. Kubernetes Scheduler (Affinity) - 이쿠의 슬기로운 개발생활
요약
nodeNamenodeSelector pod가 요청한 node가 없으면 배포 실패
affinityantiAffinity | hard : pod가 요청한 node가 없으면 배포 실패 (nodeSelector와 동일)soft : pod가 요청한 node가 없어도 다른 여유있는 node에 배포 시도 |
tainttoleration | (위 둘과는 성격이 조금 다름)기본적으로 node에 taint를 설정하여 pod의 배포를 제한하되toleration설정된 pod는 배포가능 |
nodeSelector만 줄곧 알고 있었는데 taint라는것을 접하게 되어서 pod 스케줄링 하는 컨트롤러들을 정리해봅니다.
- nodeSelector
- nodeName
- affinity
- taint
nodeSelector
pod가 요청한 label과 정확히 일치하는 node에 pod를 배포합니다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
apiVersion: v1
kind: Pod
metadata:
name: cuda-test
spec:
containers:
- name: cuda-test
image: "k8s.gcr.io/cuda-vector-add:v0.1"
resources:
limits:
nvidia.com/gpu: 1
nodeSelector:
accelerator: nvidia-tesla-p100
nodeSelector:
accelerator: nvidia-tesla-p100
nodeName
pod가 배포될 노드의 이름을 지정하여 선택합니다.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # 특정 노드에 파드 스케줄
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeName이나 nodeSelector는 필요한 node가 없으면 pod가 배포되지 않습니다.
production환경에서 이런저런 이유로 pod가 요청한 node가 없는경우가 생기게 된다면
바로 서비스 장애로 이어질 수 있습니다.
하여 nodeSelector와 동일하게 혹은 좀 더 유연하게 설정이 가능한 affinity를 사용하는 것이 좋은 선택이 될 수 있습니다.
affinity & anti-affinity
affinity는 pod가 배포될 node를 선정 한다는 것 자체만 보면 nodeSelector와 동일하지만
차이점을 갖는 두 가지 특징이 있습니다.
- nodeAffinity : pod가 배포될 node를 지정하지만 꼭 해당 node가 아니여도 배포
- podAffinity : 동일한 pod가 있는 node배포, 혹은 동일한 pod가 없는 node에 배포
좀 더 자세히 보기 위해 affinity 전체를 펼치면 아래와 같습니다.
affinity
- nodeAffinity
- requiredDuringSchedulingIgnoredDuringExecution (hard)
- preferredDuringSchedulingIgnoredDuringExecution (soft)
- podAffinity
- requiredDuringSchedulingIgnoredDuringExecution (hard)
- preferredDuringSchedulingIgnoredDuringExecution (soft)
- podAntiAffinity
- requiredDuringSchedulingIgnoredDuringExecution (hard)
- preferredDuringSchedulingIgnoredDuringExecution (soft)
다 펼쳐 놓으니까 되게 어수선해 보이는데요.
정리해보면 사실 별거 없습니다.
- affinity 종류는 세 가지 이다.
- nodeAffinity : 특정 label이 있는 node에
- podAffinity : 동일한 pod 확장은 같은 node에
- podAntiAffinity : 동일한 pod 확장은 서로 다른 node에
- 각 affinity는 두 가지 모드로 사용할 수 있다.
- hard : 반드시
- soft : 되도록
간단하죠~ 이게 전부 입니다.
IgnoredDuringExecution 규칙은 pod가 배포된 뒤에 node label이 변경되어도 pod는 해당 node에서 계속 실행됩니다.
pod 매니패스트 예시를 한번 보고 머리속에 한번 더 정리를 하기 위해 표로도 표현해봅니다.
nodeAffinity
apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
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
podAffinity, podAntiAffinity
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: k8s.gcr.io/pause:2.0
pod 매니패스트에서 요청할 수 있는 affinity 종류
nodeAffinity lable이 특정키에 특정 값이 있는 node에 배포 희망 (nodeSelector와 동일하게 사용 가능)
podAffinity | (replicaset 등) 확장되는 pod들이 같은 node에 배포 되기를 희망 |
podAntiAffinity | (replicaset 등) 확장되는 pod들이 다른 node에 배포 되기를 희망 (가용성 목적 등) |
pod가 요청한 조건을 만족하는 node가 없으면
requiredDuringSchedulingIgnoredDuringExecution (hard type) | preferredDuringSchedulingIgnoredDuringExecution (soft type) | |
nodeAffinity | 배포 실패 | 다른 node에라도 배포 시도 |
podAffinity | 배포 실패 | 다른 node에라도 배포 시도 |
podAntiAffinity | 배포 실패 | 다른 node에라도 배포 시도 |
만약 특수목적으로 비용이 큰 gpu node도 병행하여 사용한다고 했을 때,
gpu를 사용하지 않는 pod가 gpu node에 끼어 들어오는것을 애초에 방지하려면
nodeSelector나 affinity hard type으로 방지하는 방법도 있을 것이고,
그게 아니라 서비스 용도별로 node를 분리 했는데 특정 용도의 node가 부족할 때는
soft type affinity로 양보 해주어 서비스 연속성을 유지해주는 것도 좋은 방법이 될 수 있을 것 같습니다.
그리고 저라면 다른 연산자는 사용하지 않을 것 같아서 그냥 넘길까 했지만 기록은 남겨둡니다.
pod 매니패스트에서 affinity 작성할 때, operator 필드로 논리 연산자를 지정할 수 있습니다.
- In
- NotIn
- Exists
- DoesNotExist
여러 연산자를 사용할 수 있지만 복잡성을 줄이기 위해 되도록
In 연산자만 사용하는 것이 정신건강에 좋을 것 같은 생각이 듭니다. -0-
추가로 soft type의 affinity의 경우 조건이 두 개 이상일 때 weight 로 가중치로 우선순위를 정해줄 수 있습니다.
apiVersion: v1
kind: Pod
metadata:
name: with-affinity-anti-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- antarctica-east1
- antarctica-west1
preferredDuringSchedulingIgnoredDuringExecution: soft type 의 두가지 조건
- weight: 1 <- 가중치 1
preference:
matchExpressions:
- key: label-1
operator: In
values:
- key-1
- weight: 50 <- 가중치 50
preference:
matchExpressions:
- key: label-2
operator: In
values:
- key-2
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0
위 매니패스트에서 soft type의 두 가지 조건 중 가중치가 높은 label-2 먼저 여건을 살핀 후 label-1의 여건을 살피게 됩니다.
아오~~
affinity에 관한 글들을 검색하는데 짧막짧막한 글들이 반복적으로 띄엄띄엄 나와서 머리속으로 정리하는데 살짝 멘붕이 왔었습니다. -0-
taints & tolerations
이건 다 필요없이 두 단어의 뜻을 먼저 보면 무조건 이해 됩니다.
taint
toleration
기본적으로 특정 조건이 없다면 pod는 어느 node에라도 배포가 가능 합니다.
여러 node 중 taint로 오염된 노드가 있으면 pod들은 오염된 node에 배포되지 않습니다.
다만 toleration설정으로 오염을 상관하지 않는 pod는 taint로 오염된 node에도 배포가 가능합니다.
- 끝 -
힘들게 알게 된 내용인데 짧게 끝내면 아쉬우니...
taint는 일반적으로 node를 선택할 수 있게 해주는 label과 전혀 관계가 없이 독립적으로 설정됩니다.
kubectl taint nodes <nodeName> <key>=<value>:<option> # taint
kubectl label nodes <nodeName> <key>=<value> # label
taint는 effect라고 불리는 세 가지 옵션이 있습니다.
- NoExecute : toleration 없는 pod는 배포되지 않고, 이미 배포된 pod도 종료됨
- NoSchedule : toleration 없는 pod는 배포되지 않고, 이미 배포된 pod는 유지됨
- PreferNoSchedule : toleration 없는 pod는 배포되지 않지만 cluster내 자원 부족 시 배포될 수 있음
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
tolerations:
- key: "example-key"
operator: "Exists"
effect: "NoSchedule"
gpu node는 비싸니까 일반 pod는 배포되지 않도록 gpu node에 gpu라는 taint를 설정하는 것도 좋은 방법일 것 같습니다.
아~ 주 좋습니다.
오늘은 여기까지 정리만 하고 마무~~ 리!
'IT > Kubernetes' 카테고리의 다른 글
다른 사용자가 생성한 EKS에 접근권한 얻기 (0) | 2023.04.12 |
---|---|
EKS 생성(AWS 모른채 삽질의 연속으로 어찌저찌 성공) (1) | 2023.04.12 |
K8S 리소스 제한 컨트롤러 (0) | 2023.04.12 |
liveness probe, readiness probe 기능의 차이는? (0) | 2023.04.12 |
상태 프로브(startup, liveness, readiness)란 무엇인가? (0) | 2023.04.12 |