본문 바로가기
AWS Cloud School 8기/쿠버네티스

[쿠버네티스] Node Selector/ taints & tolerations/ Node Affinity

by YUNZEE 2025. 4. 25.
728x90

🔍 Node Selector

- 노드에 key:value 형태의 label을 붙여놓고 파드를 띄울 때 특정 라벨값을 정할 수 있음

- 쿠버네티스 파드는 워커 노드가 3대가 있다면 파드는 그중 아무 노드에나 랜덤으로 배치됨

❓이때, 이 파드는 반드시 워커1에만 배치가 됐으면 좋겠는데? 라든가

❓GPU 있는 노드에만 이 파드를 띄우고 싶은데 

라는 생각이 든다면 이때 NodeSelector를 사용함

더보기

- 노드 이름에 맞게 라벨 붙여주기

 

root@master:~# kubectl label nodes worker-1 gpu=false

- 임의로 내가 만든 노드 값 key=value형태

- gpu=false임의로 정한 값

vi selector.yml
- 아무 deployment를 복제후

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-dep
spec:
  replicas: 5
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: my-con
        image: 61.254.18.30:5000/ipnginx
      nodeSelector:
        gpu: "true"

- 레플리카를 5개로 해도 worker2에만 배치됨

🔍 Node Affinity

- 끌림, 노드 설렉터랑 비슷하지만 좀 더 세부적인 조건을 걸어 줄 수 있음

- NodeSeletor는 딱 하나의 조건만 정확히 일치할 때만 동작함

- 조건이 조금만 복잡해져도 못 활용함

 

이때 Node Affinity를 사용하는데

requiredDuringSchedulingIgnoredDuringExecution 꼭 이 조건을 만족해야만 파드가 배치됨 강제 조건 (NodeSelector처럼 동작)
preferredDuringSchedulingIgnoredDuringExecution 가능하면 이 조건을 만족하는 노드에 배치함, 안되면 다른 데도 가능 유연한 조건
requiredDuringSchedulingRequiredDuringExecution (거의 안 써) 실행 중에도 강제 조건 유지 알기만 해도 OK
더보기

vi affinity-required.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-dep
spec:
  replicas: 4
  selector:
    matchLabels:
      app: my-httpd
  template:
    metadata:
      labels:
        app: my-httpd
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution: #prefer은 되도록이면, required은 반드시
            nodeSelectorTerms:
            - matchExpressions:
              - key: gpu
                operator: In
                values:
                - "false"
      containers:
        - name: httpd-pod-con
          image: 61.254.18.30:5000/nginx

- worker-1에 배치가 잘 된 걸 확인할 수 있음

실습 1)

worker1은 disktype이 ssd이며, worker2는 disktype이 hdd 일 때. 간단한 deployment 파일을 작성하여 ssd-dep는 ssd가 설치된 노드에, hdd-dep는 hdd가 설치된 노드에 배치해 보세요.

 

nodeSelector와 nodeAffinity를 둘 다 사용해 보세요.

더보기

root@master:~/mani/selector# kubectl label node worker-1 disktype=ssd
node/worker-1 labeled
root@master:~/mani/selector# kubectl label node worker-2 disktype=hdd
node/worker-2 labeled

 

vi hdd.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hdd-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hdd
  template:
    metadata:
      labels:
        app: hdd
    spec:
      containers:
      - name: my-con
        image: 61.254.18.30:5000/ipnginx
      nodeSelector:
        disktype: hdd

vi sdd.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ssd-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ssd
  template:
    metadata:
      labels:
        app: ssd
    spec:
      containers:
      - name: my-con
        image: 61.254.18.30:5000/ipnginx
      nodeSelector:
        disktype: ssd

vi ssd-aff.yml

  selector:
    matchLabels:
      app: ssd
  template:
    metadata:
      labels:
        app: ssd
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disktype
                operator: In
                values:
                - ssd
      containers:
        - name: httpd-pod-con
          image: 61.254.18.30:5000/nginx

vi hdd-aff.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hdd-dep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hdd
  template:
    metadata:
      labels:
        app: hdd
    spec:
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: disktype
                operator: In
                values:
                - hdd
      containers:
        - name: httpd-pod-con
          image: 61.254.18.30:5000/nginx

root@master:~/mani/selector# kubectl apply -f hdd.yml
deployment.apps/hdd-dep created
root@master:~/mani/selector# kubectl apply -f ssd.yml
deployment.apps/ssd-dep created
root@master:~/mani/selector# kubectl apply -f ssd-aff.yml 
deployment.apps/ssd-dep configured
root@master:~/mani/selector# kubectl apply -f hdd-aff.yml 

 

root@master:~/mani/selector# kubectl get node --show-labels

🔍taints & tolerations

taints: 이 노드에 오지 마 = 금지

tolerations: 나는 괜찮아, 갈 수 있어 = 허용

 

이런 기능이 나온 이유는 기본적으로 쿠버네티스는 파드를 아무 노드나 적절히 골라서 배치를 해줌

- 이 노드는 GPU가 있어서 특별한 작업만 시켜야 함

- 이 노드는 운영 서비스 전용임. 테스트 파드는 오면 안 됨

-> 이럴 때 노드를 보호하는 기능이 필요함

더보기

kubectl taint node worker-1 team=dev:NoSchedule

- team=dev라는 toleration이 없다면, pod를 배치 안 하겠다.

 

kubectl taint node worker-2 team=ops:NoSchedule

- team=ops라는 toleration이 없다면, pod를 배치 안 하겠다.

 

root@master:~/mani/selector# cp ~/mani/dep.yml .
root@master:~/mani/selector# vi dep.yml 

 

vi dep.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-dep-tai
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: my-con
        image: public.ecr.aws/docker/library/nginx:alpine

root@master:~/mani/selector# kubectl apply -f dep.yml 

 

kubectl get pod -o wide --watch

 

root@master:~/mani/selector# kubectl describe pod my-dep-tai-76c7fd4d94-r55wb

- taint에 의해 pod를 배치할 수 있는 노드가 없는 걸 확인

 

cp dep.yml tol-dep.yml

# 톨러레이션 옵션을 줄 deployment

 

vi tol-dep.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: my-con
        image: 61.254.18.30:5000/ipnginx
      tolerations:
      - key: "team"
        operator: "Equal"
        value: "dev"
        effect: "NoSchedule"

- 톨러레이션에 해당하는 노드에 파드패치를 허용하겠음

root@master:~/mani/selector# kubectl taint node worker-2 team=ops:NoSchedule-
node/worker-2 untainted
root@master:~/mani/selector# kubectl taint node worker-1 team=dev:NoSchedule-
node/worker-1 untainted

- 테인트 삭제

 

root@master:~/mani/selector# kubectl label node worker-1 gpu-
node/worker-1 unlabeled
root@master:~/mani/selector# kubectl label node worker-2 gpu-
node/worker-2 unlabeled
root@master:~/mani/selector# kubectl label node worker-2 disktype-
node/worker-2 unlabeled
root@master:~/mani/selector# kubectl label node worker-1 disktype-
node/worker-1 unlabeled

- 라벨 삭제

 

728x90