쿠버네티스

Kubernetes : Scheduler

NickTop 2025. 2. 1. 17:51

Scheduler란?

Kubernetes Scheduler는 새로 생성된 Pod 중 Node에 할당되지 않은 Pod를 감지하고, 적절한 Node에 배포하는 역할을 담당합니다. 그 절차는 아래와 같습니다

Scheduling framework

스케줄링 프로세스

  • Scheduling Queue: Node에 올릴 Pod의 우선순위 정함
  • Filtering: 노드의 리소스, 이름, 스케줄링 가능 여부 등을 기준으로 필터링
  • Scoring: 필터링된 Node들에 점수를 매겨 최적의 Node 선택
  • Binding: 최종적으로 선택된 Node에 Pod를 바인딩

 

Taint & Toleration

  • Taint: 특정 Node에 제한을 걸어, 조건에 맞는 Pod만 스케줄링되도록 설정 (Node에 설정)
  • Toleration: Pod가 Node의 taint를 허용하여 해당 Node에 배치될 수 있도록 설정 (Pod 및 pod를 만드는 kind에 설정)

Taint의 종류

  • NoSchedule: 조건에 맞지 않는 Pod는 스케줄되지 않음 (기존 pod는 영향 없음)
  • PreferNoSchedule: 스케줄링을 피하려고 시도하지만, 절대적인 것은 아님
  • NoExecute: 조건에 맞지 않는 기존 Pod도 퇴출됨

Pod 설정 예시

tolerations:
  - key: "dedicated"
    operator: "Equal"
    value: "special"
    effect: "NoExecute"

이 설정은 dedicated=special 이라는 taint를 가진 Node를 허용(tolerate)합니다.

 

Node Affinity / NodeSelector

Taint는 Node가 어떤 Pod를 제외할지 결정하고 Node Affinity를 가진 Node는 pod 배포 시 다른 Node보다 먼저 배포된다 

  • nodeSelector: 단순한 key-value 매칭, OR 조건 불가능
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    disktype: ssd

위와 같이 node의 레이블에 disktype: ssd가 있는 노드에 할당된다

  • nodeAffinity: 더 복잡한 조건 설정 가능 (예: OR 조건 지원)
apiVersion: v1
kind: Pod
metadata:
  name: with-node-affinity
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - antarctica-east1
            - antarctica-west1
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 1
        preference:
          matchExpressions:
          - key: another-node-label-key
            operator: In
            values:
            - another-node-label-value
  containers:
  - name: with-node-affinity
    image: registry.k8s.io/pause:2.0

requiredDuringSchedulingIgnoredDuringExecution: 규칙에 맞지 않으면 스케줄링안함

preferredDuringSchedulingIgnoredDuringExecution: 규칙에 맞지 않더라도 해당되는 노드가 없으면 스케줄링함

weight: 우선순위 함수 점수에 더해짐

Pod Affinity / Pod AntiAffinity

노드에 할당되어있는 pod를 보고 스케줄링을 결정한다

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
  containers:
  - name: with-pod-affinity
    image: registry.k8s.io/pause:2.0

위 예시는 노드의 security=S1라는 레이블을 가진 파드가 있는 노드에 스케줄링한다

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-cache
spec:
  selector:
    matchLabels:
      app: store
  replicas: 3
  template:
    metadata:
      labels:
        app: store
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - store
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: redis-server
        image: redis:3.2-alpine

만약 위와같이 설정하면, pod가 모든 node에 한개씩만 할당된다

 

Resource 관리

Scheduler는 리소스가 충분한 Node를 선택합니다.

  • Request/Limit:
    • Request: Pod가 보장받는 최소 자원
    • Limit: 사용할 수 있는 최대 자원
    • CPU는 Limit을 초과해도 Throttling으로 조절하지만, 메모리는 Limit을 초과하면 OOM(Out of Memory) 발생
    • Request 없이 Limit만 설정하면, Request = Limit으로 자동 설정
  • LimitRange: Namespace 단위로 리소스 제한을 설정할 수 있음
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

 

Multiple Schedulers & Custom Scheduling

Kubernetes에서는 기본적으로 kube-scheduler라는 기본 스케줄러가 제공되지만, 필요에 따라 여러 개의 스케줄러를 동시에 사용할 수 있습니다. 또한, 특정 요구 사항에 맞게 커스텀 스케줄러를 만들어 특정 Pod를 지정된 로직에 따라 스케줄링할 수 있습니다. ConfigMap을 활용해 조건 설정이 가능합니다

 

 

 

Scheduling에 영향을 받지 않는 Pod

DaemonSet

모든 Node에 하나씩 Pod를 자동 배포하는 방식

  • 주요 사용 사례: 모니터링, 로그 수집
  • kube-proxy도 DaemonSet으로 배포
  • Kubernetes 스케줄러가 관리

Static Pod

Master Node 없이도 Pod 배포 가능

  • kubelet이 Node 내부의 YAML 파일을 지속적으로 감시하여 Pod를 실행 (yaml이 수정되면 pod도 수정됨)
  • 파일이 삭제되면 Pod도 삭제됨
  • ReplicaSet 같은 컨트롤러는 적용되지 않음
  • 설정 경로는 kubelet.service 파일에서 확인 가능
  • kubelet이 직접 관리

 

QoS classes

Pod는 Quality of Service를 가진다

종류는 Guaranteed > Burstable > BestEffort 가 있으며, 리소스가 부족해지면 BestEffort부터 없어진다

BestEffort : CPU/memory limit/request 없음

Burstable : CPU/memory limit/request 있고 limit/request가 다름

Guaranteed : CPU/memory limit/request있고 limit/request가 서로 같음

 

 

 

 

 

https://kubernetes.io/docs/concepts/scheduling-eviction/scheduling-framework/

https://kubernetes.io/docs/concepts/workloads/pods/pod-qos/

'쿠버네티스' 카테고리의 다른 글

Kubernetes : CRD  (0) 2025.03.09
Kubernetes : Kustomize  (0) 2025.03.05
Kubernetes : Helm  (0) 2025.03.04
Kubernetes : Network  (0) 2025.03.03
Kubernetes 구조 : Cluster, Node, Pod  (0) 2025.01.19