Pod Affinity를 적용하여 Pod 분산 배포하기

Pod Affinity를 적용하여 Pod 분산 배포하기

0. Kubernetes 환경

현재 프로젝트에서 구축한 Kubernetes 환경은 Kubernetes 1.15 버전이고, Node Autoscaling과 Pod Autoscaling 이 적용되어 있다.

Worker Node가 AZ별로 이중화되어 있는 환경에서 Pod가 분산 배포되지 않고 한 Node에 몰려있으면, 그리고 그 Node가 Down 상태가 되면 Pod 의 서비스가 같이 Down되게 된다.

이러한 문제점을 피하기 위해 Pod에 Affinity 옵션을 설정하여 Pod을 분산 배포한다.

1. Pod Affinity

파드간 어피니티와 안티-어피니티를 사용하면 노드의 레이블을 기반으로 하지 않고, 노드에서 이미 실행 중인 파드 레이블을 기반으로 파드가 스케줄될 수 있는 노드를 제한할 수 있다.

규칙은 "X가 규칙 Y를 충족하는 하나 이상의 파드를 이미 실행중인 경우 이 파드는 X에서 실행해야 한다(또는 안티-어피니티인 경우에는 실행하면 안된다)"는 형태이다.

규칙 Y는 Label Selector를 기준으로 설정할 수 있다.

아래의 affinity 옵션은 4개의 pod가 다른 AZ, 다른 Worker node에서 뜰 수 있도록 하는 옵션이다.

affinity:

podAntiAffinity:

preferredDuringSchedulingIgnoredDuringExecution:

- weight: 99

podAffinityTerm:

labelSelector:

matchExpressions:

- key: "app.kubernetes.io/name"

operator: In

values:

-

topologyKey: "kubernetes.io/hostname"

- weight: 100

podAffinityTerm:

labelSelector:

matchExpressions:

- key: "app.kubernetes.io/name"

operator: In

values:

-

topologyKey: "failure-domain.beta.kubernetes.io/zone"

위의 코드는 두 가지 Anti Affinity 옵션으로 적용되어 있다.

첫 번째 옵션(podAffinityTerm)은 topologyKey가 "kubernetes.io/hostname"인 것을 기준으로 pod의 key가 "app.kubernetes.io/name"이고 value가 인 pod가 있는 node를 가급적 피해서 배포하라는 옵션이다.

위의 "kubernetes.io/hostname"은 worknode의 node명이므로, Pod들은 affinity옵션에 따라 node별로 분산 배포가 된다.

두 번째 옵션(podAffinityTerm)은 topologyKey가 "failure-domain.beta.kubernetes.io/zone"인 것을 기준으로 pod의 key가 "app.kubernetes.io/name"이고 value가 인 pod가 있는 node를 가급적 피해서 배포하라는 옵션이다.

위의 "failure-domain.beta.kubernetes.io/zone"은 availability zone이므로, Pod들은 affinity옵션에 따라 node별로 분산 배포가 된다.

아래의 사진은 위에서 설정한 topology key로 설정한 node의 label값이다.

node의 label들을 확인하는 명령어는 kubectl describe nodes이다.

affinityTerm.weight 옵션은 가중치로, 각 옵션의 가중치에 따라 가장 낮은 값을 가진 node에 배포하도록 한다.

위의 조건은 Anti Affinity 옵션이므로 가장 낮은 가중치의 node에 배포되며, Affinity는 가장 높은 가중치의 node에 배포된다.

아래의 그림은 4개의 Worker Node에 Pod가 1개에서 4개로 Autoscale될 때의 Pod 가중치 합과, 가중치에 따른 Pod 배포 순서를 보여준다.

2. Affinity 조건의 엄격함과 유연함

Pod Affinity 옵션 중에도 강제와 권고의 두 가지 선택 사항이 있다.

위에서 제공한 Affinity 옵션은 설정된 조건을 최대한 피하면서 배포하지만, 모든 node가 조건에 맞지 않아도 Pod 배포는 중단되지 않는 preferredDuringSchedulingIgnoredDuringExecution 옵션이 설정되어 있다.

만약 Affinity 옵션이 충족하지 않으면 pod를 배포하지 않고, pending 상태로 조건에 맞는 node를 기다리도록 강제하려면 아래와 같이 requiredDuringSchedulingIgnoredDuringExecution 옵션으로 설정한다.

affinity:

podAntiAffinity:

requiredDuringSchedulingIgnoredDuringExecution:

- labelSelector:

matchExpressions:

- key: "app.kubernetes.io/name"

operator: In

values:

-

topologyKey: "kubernetes.io/hostname"

requiredDuringSchedulingIgnoredDuringExecution 옵션은 preferredDuringSchedulingIgnoredDuringExecution 옵션과 달리 가중치 값을 설정하지 않는다.

설정된 조건이 충족하는 node를 무조건적으로 따르기 때문이다.

위의 코드로 Affinity 옵션을 설정하고 Node Autoscaler를 함께 적용하면, Pending상태인 Pod를 배포하기 위해 Node가 Autoscale된다.

from http://juniquerepo.tistory.com/19 by ccl(A) rewrite - 2021-09-01 17:26:25