Pod Scheduling & Assignment

inuit·2025년 4월 13일

All about 쿠버네티스

목록 보기
9/21
post-thumbnail

최근 업데이트일 2024-11-09

실습 동영상 따라하며 배우는 쿠버네티스

Node마다 물리적 스펙이 다르기 때문에 Pod가 어디서 실행되어야 하는지를 통제해야 하며, 이를 위해서는 Label이 필수이다. Label에 따라 조정할 수 있도록 하는 Pod Scheduling 방식과 Node의 스케줄링을 제어하는 Taint & Toleration & Cordon & Drain에 대해서 알아보자.

1. Label & Annotations

Label

Kubernetes에서 리소스들을 식별하거나 분류하기 위한 Key-Value 형식의 메타데이터 쿠버네티스: Labels

  • Label은 주로 selector이나 배치 제어, 모니터링 등에 사용된다.
    • kubectl get pods -l [KEY]=[VALUE]: 해당 label을 가지는 Pod 조회
    • kubectl get pods --show-labels: Pod의 label까지 조회
    • kubectl delete pods --selector [KEY]=[VALUE]: 해당 label을 가지는 Pod 제거
    • kubectl label [TYPE] [NAME] [KEY]=[VALUE]: label 추가, --overwrite 설정으로 이미 있던 label 변경,
    • kubectl label [TYPE] [NAME] [KEY]-: label 삭제
    • kubectl label [TYPE] -L [KEYS]: 특정 키만 출력
  • Node의 Label을 설정해서 Node가 가지고 있는 Resource(SSD, GPU 등)에 맞게 Node 선택해서 Pod를 배치한다.
    • Pod의 spec.nodeSelector로 Node의 label을 선택해서 Node를 특정하고, 맞는 Node가 없으면 Pending 상태가 된다.
spec:
  nodeSelector:
    disktype: ssd

Annotation

Kubernetes 리소스에 대해 기계가 처리하는 메타데이터를 저장하는 방식, 주로 컨트롤러나 도구, 시스템이 사용하기 위해 존재하는 key-value 메타데이터

  • 쿠버네티스에게 특정 정보를 전달하거나, 필요한 정보를 기록할 때 사용한다.
  • label과 달리 selector로는 사용할 수 없다.
  • metadata.annotations로 기록, e.g. 버전 기록해서 롤링 업데이트하면 history로 남음
metadata:
  annotations:
    revision: "v2.1.3"
    contact: "dev@company.com"

matchExpressions

label selector를 정교하게 작성할 수 있게 해주는 구문

  • 단순한 key=value 형태인 matchLabels보다 더 복잡한 조건을 표현할 수 있다.
  - key: <레이블 키>
    operator: <연산자>
    values: [<값1>, <값2>, ...]  # 일부 연산자에서는 생략 가능
연산자의미예시
Inkey가 values 목록에 포함됨"zone" In ["us-west1", "us-east1"]
NotInkey가 values 목록에 포함되지 않음"disktype" NotIn ["hdd"]
Existskey가 존재하기만 하면 됨 (value는 필요 없음)"gpu" Exists
DoesNotExistkey가 존재하지 않아야 함"gpu" DoesNotExist

Pod 배포 전략

  • 블루 그린 업데이트
    • 두 개의 독립된 환경(Blue, Green)을 두고 전체 트래픽을 한 번에 전환
    • Blue 제품 다 내리고 Green 제품을 올린다.
    • 위험은 낮추지만 자원 소모가 많다.
  • 롤링 업데이트
    • 하나씩 버전 업데이트해서 버전 중단 없이 배포한다.
    • 기존 Pod를 순차적으로 교체한다.
    • 무중단 배포가 가능하지만, 롤백이 느리다.
  • 카나리 업데이트
    • 기존 버전 유지한 채 일부 버전만 신규 버전으로 올려서 오류를 확인한다.
    • e.g. label이 하나만 다른 블루 Deploy와 그린 Deploy를 Replicas 수를 조절하여 그린 제품으로 바꿔가면서 Service 배포
      • 이 때 해당 Pod의 Service의 Selector는 블루 그린의 겹치는 label만 Selector로 지정
    • 소수의 트래픽만 새 버전으로 전달해 문제를 탐지한다.
    • 안정성과 실험을 병행할 수 있다.

matchExpressions는 단순 분류 외에도 Pod가 어떤 Node에 배포될지 지정하는 데 필수적인 역할한다. 이러한 메타데이터가 스케줄링에 어떻게 사용되는지 알아보자.


2. Pod Scheduling

Pod를 배포할 때 어느 Node에 배포할지 혹은, Pod가 어느 Node를 선호하는지를 지정할 수 있다.

  1. Node Name: Node 이름을 지정해서 object(Pod or Pod Controller)를 배포하는 방식, template.spec.nodeName에 지정한다.
apiVersion: v1
kind: Pod
metadata:
  name: node-name-example
spec:
  nodeName: node-1  # node 이름을 직접 지정
  containers:
  - name: nginx
    image: nginx
  1. Node Selector: Node에 설정한 label을 기반으로 scheduling하는 방식, template.spec.nodeSelector에 label을 지정한다.
    • kubectl label node [NAME] [key]=[value] [—overwrite]: 실행 중인 Node의 label 추가 또는 변경
apiVersion: v1
kind: Pod
metadata:
  name: node-selector-example
spec:
  nodeSelector:
    disktype: ssd  # 해당 label을 가진 노드에서만 실행됨
  containers:
  - name: nginx
    image: nginx
  1. Node Affinity: 선호하는 Node를 설정해서 할당하는 방식
    • label Selector 기능 제공 (matchExpressions 등 label selector를 지원)
    • template.spec.affinity.nodeAffinity에서 Hard 방식과 Soft 방식 중 하나를 선택한다.
    • requiredDuringSchedulingIgnoredDuringExecution: 스케쥴링 되는 워크로드에는 필수 조건이고 실행 중인 워크로드에는 조건을 무시한다. (Hard)
      • nodeSelectorTerm에서 matchExpressions를 적용한다.
    • preferredDuringSchedulingIgnoredDuringExecution: 스케쥴링 되는 워크로드에는 선호 조건이고 실행 중인 워크로드에는 조건을 무시한다. (Soft)
      • weight가 존재하여 여러 soft 조건이 있을 때, 어떤 조건을 더 우선시할지를 weight에서 지정 후 preference에서 matchExpressions를 적용한다.
# Hard
apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-hard-example
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: disktype
            operator: In
            values:
            - ssd
  containers:
  - name: nginx
    image: nginx
    
# Soft
apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-soft-example
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - zone-a
  containers:
  - name: nginx
    image: nginx
  1. Pod Affinity: 특정 파드가 있는 노드를 선호하여 해당 노드에 함께 스케줄링되도록 설정, node Affinity와 사용법은 거의 동일하다.
    • Topology Key: Affinity가 적용될 스케쥴링 범위를 결정하는 키이며, 이는 노드에 붙은 label을 기준으로 작동한다.
    • affinity.podAffinity.topologyKey에 Node · Zone · Region 중 하나를 선택해서 그 범위 안에서 Label Selector를 수행해 노드를 선택한다.
    • Zone이나 Region은 클라우드 플랫폼에서 자동으로 붙여주는 Node의 label이다.
apiVersion: v1
kind: Pod
metadata:
  name: pod-affinity-example
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - frontend
        topologyKey: topology.kubernetes.io/zone  # 같은 zone에 붙이기
  containers:
  - name: nginx
    image: nginx
  1. Node Antiaffinity · Pod Antiaffinity: 스케줄링 시 피하고 싶은 Node나 Pod를 지정하는 방식
apiVersion: v1
kind: Pod
metadata:
  name: pod-anti-affinity-example
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - frontend
        topologyKey: "kubernetes.io/hostname"  # 같은 노드에 배치하지 않음
  containers:
  - name: nginx
    image: nginx

Pod의 Node 할당 정책을 살펴보았다. 이제 Node의 Pod 할당 정책을 살펴보자.


3. Taint & Toleration / Cordon & Drain

쿠버네티스에서는 Node에 Pod가 임의로 스케줄링되는 것을 제어하기 위한 두 가지 주요 메커니즘이 있다.

  1. Taint & Toleration: Pod가 특정 조건을 수용할 수 있는지 여부를 기준으로 스케줄링 허용 여부를 결정
  2. Cordon & Drain: 노드 자체를 스케줄링 대상에서 제외하거나, 기존 Pod를 강제 퇴출시키는 기능

  • Taint: Node가 특정 조건을 갖지 않는 Pod의 스케줄링을 거부하거나 제한하도록 설정
  • Toleration: Pod가 해당 Taint를 수용(tolerate) 하도록 하여, 스케줄링 가능하게 만듦
    • Taint는 Key Value 형식에 추가적으로 Effect 파라미터를 가진다.
    • Effect: Taint가 주는 스케줄링 제한 효과
      • NoSchedule: Taint Node에 Pod 스케줄링 금지 (기존 Pod는 유지)
      • NoExecute: Taint Node에 기존 Pod도 축출, 새 Pod도 스케줄링 불가
      • PreferNoSchedule: Taint Node에 가능하면 스케줄링하지 않음 (soft) → 기존 실행 중인 Pod는 두고 앞으로 생성될 Pod에 대해서만 적용하지만 어쩔 수 없다면 허용한다.
    • kubectl taint node [NAME] [key]=[value]:{NoSchedule, NoExecute, PreferNoSchedule}
  • template.spec.tolerationskey, value, effect, operator 등을 설정하여 특정 Taint를 수용할 수 있도록 Pod를 구성한다.
  • DaemonSet은 모든 노드에 Pod를 배치해야 하므로, 일반적으로 모든 Taint를 수용하도록 toleration을 설정한다.

  • Cordon: 특정 Node를 스케줄링 대상에서 제외시켜 Pod가 할당되지 않도록 한다.
    • 기존 노드에 배포된 Pod는 유지되고 새로운 Pod는 배포될 수 없다.
    • kubectl cordon [NODE_NAME]kubectl uncordon [NODE_NAME]
  • Drain: 노드를 비우는 작업
    • 특정 Node를 스케쥴러에서 제외시켜 Pod가 할당되지 않도록 하고 기존에 배포된 Pod를 다른 Node로 이동시킨다,
    • 보통 노드를 업데이트할 때 사용한다.
    • kubectl drain [NODE_NAME] [--ignore-daemonsets] [--force]kubectl uncordon [NODE_NAME]
profile
It’s always white night here.

0개의 댓글