Kubernetes

Pod Affinity - topologyKey 상세 동작

사실 나도 모름 2024. 1. 3. 23:06

어피니티는 노드 어피니티와 파드 어피니티가 있다.

노드 어피니티는 노드의 레이블을 검사하여 어떤 노드에 스케줄링할 지 결정하는 방법을 정의한 것이고,

파드 어피니티는 이미 스케줄링된 파드의 레이블을 검사하여 같은 노드에 스케줄링할 것인지 아닌지 결정하는 방법을 정의한 것이다.

 

파드 어피니티에 대해 topologyKey를 통한 파드 스케줄링이 어떻게 달라지는 지 연구해볼 것이다.

토폴로지 분배 제약 조건을 사용하여 지역(regions), 영역(zones), 노드 또는 사용자가 정의한 다른 토폴로지 도메인과 같은 장애 도메인 사이에서 파드가 클러스터 전체에 분산되는 방식을 제어할 수 있다. 성능, 예상 가용성 또는 전체 활용도를 개선하기 위해 이 작업을 수행할 수 있다.

현재는 클라우드 환경에서 진행하는 상황이 아니기에 개인 VM환경에서 hostname 단위의 스케줄링 차이를 볼 것이다.

 

작업환경은 마스터 1대, 워커노드 5대로 운영한다.

 

 

내가 생각한 의문 몇가지

  1. topologyKey: kubernetes.io/hostname 으로 파드 어피니티가 정의되어있으면 동일한 호스트 네임 내에서만 파드가 스케줄링되는가?
  2. topologyKey: kubernetes.io/hostname 으로 파드 안티 어피니티가 정의되어있으면 호스트 네임당 하나의 파드만 스케줄링하는가?
  3. requiredDuringSchedulingIgnoredDuringExecution로 정의되어 있는 파드 안티 어피니티로 파드가 스케줄된 상황에서 각 워커노드에 조건에 위배되는 파드가 이미 하나씩 있으면(topologyKey 조건을 만족하는 노드가 없으면) 추가적으로 생성되는 파드는 어떻게 스케줄링되는가?

 

 


1. topologyKey: kubernetes.io/hostname 으로 파드 어피니티가 정의되어 있으면
동일한 호스트 네임 내에서만 파드가 스케줄링되는가?

 

 

어떻게 보면 당연한 것 같지만 눈으로 확인하지 않고서는 이해를 못하는 성격이라 직접 실험을 해보았다.

각 노드의 레이블

 

node4과 node5의 hostname이 동일한 상황에서 topologyKey는 어떻게 동작하는지 보자.

먼저 node5에 security=S1이라는 레이블을 가진 파드를 하나 스케줄링하고 파드 어피니티가 정의된 파드를 하나 생성한다.

이후 추가로 파드를 몇개 더 생성하여 생성되는 파드들은 어디에 스케줄링되는지 확인해보자.

apiVersion: v1
kind: Pod
metadata:
  name: testpod
  labels:
    security: S1
spec:
  containers:
  - image: nginx:1.25
    name: nginx-container
    ports:
    - containerPort: 80
      protocol: TCP
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: kubernetes.io/hostname
            operator: In
            values:
            - node5
---
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
  labels:
    security: S1
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: registry.k8s.io/pause:2.0

node5에 둘 다 스케줄링되었다.

 

파드가 node5에 스케줄링되었다.

이번에는 security: S1이라는 레이블을 가진 파드를 세 개 생성해볼 것이다.

 

 

예상:

만약 topologyKey에 의해 동일한 호스트 네임 내에서만 파드가 스케줄링된다면 동일한 호스트 네임을 가진 node4와 node5에만 스케줄링될 것이다.

for NUM in $(seq 3); do kubectl run testpod-$NUM --image nginx:1.25 --labels="security=S1"; done

 

 

 

결과: 예상과 일치

node4와 node5에만 스케줄링되었다.

 

실제로 같은 레이블을 가진 노드에만 파드가 스케줄링되었다.

 

 

 


2. topologyKey: kubernetes.io/hostname 으로 파드 안티 어피니티가 정의되어 있으면
호스트 네임당 하나의 파드만 스케줄링하는가?

 

 

podAffinity를 podAntiAffinity로 바꾸고 실행한다.

apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
  labels:
    security: S1
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: kubernetes.io/hostname
  containers:
  - name: with-pod-affinity
    image: registry.k8s.io/pause:2.0

node5에 스케줄링되었다.

 

파드가 node5에 스케줄링되었다.

동일하게 security: S1이라는 레이블을 가진 파드를 세 개 생성해보자.

 

 

예상:

만약 topologyKey에 의해 호스트 네임당 1개의 파드만 스케줄링한다면 node5라는 호스트 네임을 가지지 않은 node1과 node2와 node3에 스케줄링될 것이다.

node5와 동일한 호스트 네임을 가진 node4에는 스케줄링되지 않아야 한다.

for NUM in $(seq 3); do kubectl run testpod-$NUM --image nginx:1.25 --labels="security=S1"; done

 

 

 

결과: 예상과 일치

node4에는 스케줄링되지 않았다.

 

실제로 node4에는 스케줄링되지 않았다.

 

 

 


3. requiredDuringSchedulingIgnoredDuringExecution로 정의되어 있는 파드 안티 어피니티로 파드가 스케줄된 상황에서 각 워커노드에 조건에 위배되는 파드가 이미 하나씩 있으면(topologyKey 조건을 만족하는 노드가 없으면) 추가적으로 생성되는 파드는 어떻게 스케줄링되는가?

 

 

 

2번 실험에서 이어서 진행할 것이다.

세 개의 파드를 더 실행한다.

 

 

예상:

만약 파드 안티 어피니티 조건과 일치하는 노드가 더이상 존재하지 않을 때 새로 생성되는 security=S1 레이블을 가진 파드는 pending상태에 머무를 것이다.

for NUM in $(seq 3); do kubectl run testpod--$NUM --image nginx:1.25 --labels="security=S1"; done

 

 

 

결과: 예상과 불일치

실행은 된다.

 

결과가 조금 이상하지만 node5와 같은 레이블을 가진 node4에는 더이상 파드가 스케줄되지는 않는다(node5도 마찬가지).

하지만 node1, node2, node3에는 각각 파드가 하나씩 더 생긴 형태를 볼 수 있다.

궁금하니 한번 더 실행해보자.

for NUM in $(seq 3); do kubectl run testpod---$NUM --image nginx:1.25 --labels="security=S1"; done

node4와 node5에는 절대 스케줄링되지 않는다.

 

이로써 어느정도 결과가 이해는 된다.

파드 안티 어피니티가 정의된 파드를 포함한 노드와 같은 호스트 네임을 가진 모든 노드에는 노드의 개수보다 파드의 개수가 초과하더라도 더이상 추가로 스케줄되지는 않지만 다른 호스트 네임을 가진 노드에는 스케줄 될 수 있다.

즉, topologyKey로 인해 파드가 같은 노드에 중첩되지 않게 스케줄되는 것은 보장하지만 파드가 많아질 경우 자신이 속한 노드를 제외한 모든 노드에 균등하게 스케줄하도록 만든다.

 

 

실제로 이렇게 활용하는 경우가 있을지는 모르겠으나(없을 거 같다) 파드 어피니티에 대한 궁금증은 어느 정도 해소가 된듯하다.

 

https://kubernetes.io/ko/docs/concepts/scheduling-eviction/topology-spread-constraints/

 

파드 토폴로지 분배 제약 조건

사용자는 토폴로지 분배 제약 조건 을 사용하여 지역(region), 존(zone), 노드 및 기타 사용자 정의 토폴로지 도메인과 같이 장애 도메인으로 설정된 클러스터에 걸쳐 파드가 분배되는 방식을 제어

kubernetes.io