본문 바로가기

CKA

[k8s] 스케줄링 기본기: nodeSelector / nodeAffinity / podAntiAffinity로 Pod 배치 제어하기 (실습 포함)

728x90
반응형

1. nodeSelector: 가장 단순한 "노드 라벨 매칭"

nodeSelector는 Pod가 특정 노드 라벨을 만족할 때만 스케줄되도록 강제한다.

  • 특징
    • 라벨 key: value를 정확히 매칭
    • 조건은 사실상 AND만 가능(표현력이 제한적)
  • 언제 유용한가?
    • "이 Pod는 SSD 노드에서만"처럼 단순한 강제 배치

예시

apiVersion: v1
kind: Pod
metadata:
  name: ns-pod
spec:
  nodeSelector:
    disktype: ssd
  containers:
  - name: app
    image: nginx:1.27

 

확인 커맨드

kubectl get pod ns-pod -o wide
kubectl describe pod ns-pod

2. nodeAffinity: nodeSelector의 확장판 (조건식 + 선호도)

nodeAffinity는 nodeSelector보다 훨씬 유연하게 노드를 선택할 수 있다.

핵심은 2가지 모드다.

2-1) requiredDuringSchedulingIgnoredDuringExecution (강제 규칙)

  • 의미: 스케줄링 시점에 조건을 만족하지 못하면 절대 배치되지 않음(Pending 가능)
  • "필수 조건"을 걸 때 사용하는 패턴
apiVersion: v1
kind: Pod
metadata:
  name: na-required
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: env
            operator: In
            values: ["prod"]
  containers:
  - name: app
    image: nginx:1.27

 

2-2) preferredDuringSchedulingIgnoredDuringExecution (선호 규칙)

  • 의미: 가능하면 조건을 만족하는 노드로 배치하려고 "점수(가중치)"를 줌
  • 조건을 못 맞춰도 다른 노드로 갈 수 있음
apiVersion: v1
kind: Pod
metadata:
  name: na-preferred
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: env
            operator: In
            values: ["prod"]
  containers:
  - name: app
    image: nginx:1.27

 

matchExpression 연산자 정리

  • In, NotIn, Exists, DoesNotExist, Gt, Lt

nodelSelectorTerms 논리 정리

  • 같은 term 안의 matchExpressions는 AND
  • nodelSelectorTerms가 여러 개면 OR
    → "이 조건 세트 또는 저 조건 세트 중 하나만 만족해도 된다" 느낌

3. podAntiAffinity: "Pod끼리 떨어뜨려 배치하기" (분산)

nodeSelector/nodeAffinity가 "노드 라벨 기반"이라면,
podAffinity/antiAffinity는 "다른 Pod가 어디 있는지"를 기준으로 배치한다.

 

가장 자주 쓰는 건 podAntiAffinity다.

  • 대표 목적
    • 같은 앱 replica가 한 노드에 몰리지 않도록 분산
  • 핵심 키워드
    • topologyKey: kubernetes.io/hostname
      → "같은 노드(호스트)엔 같이 두지 마"

예시: Deployment 2개 replica를 서로 다른 노드로 분산

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-anti
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web-anti
  template:
    metadata:
      labels:
        app: web-anti
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchLabels:
                app: web-anti
            topologyKey: kubernetes.io/hostname
      containers:
      - name: app
        image: nginx:1.27

 

확인 커맨드

kubectl get pod -l app=web-anti -o wide
kubectl describe pod -l app=web-anti
노드가 1개뿐이면 anti-affinity 때문에 2번째가 Pod가 Pending이 될 수 있다.
(강제(required) 규칙이라서 "같은 노드에 같이 둘 수 없음")

4. 실습을 위한 준비: 멀티 노드(kind) 만들기

kind 기본은 노드가 1개인 경우가 많아서, 스케줄링 실습이 제한된다.

아래처럼 worker 2개 포함된 클러스터를 만들면 실습히 훨씬 깔끔하다.

 

kind-3nodes.yaml

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
  - role: worker
kind delete cluster
kind create cluster --config kind-3nodes.yaml
kubectl get nodes

5.  디버깅 루틴: Pending이면 무조건 describe 부터

스케줄링 문제는 보통 Events에 답이 있다.

kubectl describe pod <pod-name>
  • 자주 나오는 원인
    • 라벨이 없는 노드(조건 미충족)
    • 노드가 1개뿐인데 anti-affinity 강제
    • 리소스 부족(CPU/Memory)
728x90
반응형