본문 바로가기
IT/Kubernetes

K8S Node 선택 컨트롤러

by rapker 2023. 4. 12.
반응형

 

참고

요약

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를 사용하는 것이 좋은 선택이 될 수 있습니다.

 

728x90

 

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를 설정하는 것도 좋은 방법일 것 같습니다.

아~ 주 좋습니다.

오늘은 여기까지 정리만 하고 마무~~ 리!

 

 

반응형
LIST