스케줄링, 선점 및 축출 퀴즈
이 퀴즈는 Kubernetes의 스케줄링, 선점 및 축출 관련 개념에 대한 이해도를 테스트합니다. 포드 스케줄링 알고리즘, 노드 선택, 어피니티, 테인트, 톨러레이션, 선점, 축출 등의 주제를 다룹니다.
객관식 문제
- 노드 후보를 평가하는 필터링·스코어링·바인딩 중 먼저 수행되는 단계는 무엇인가요?
- A) 노드에 점수 매기기
- B) 노드 필터링
- C) 포드 우선순위 결정
- D) 바인딩 작업 수행
정답 보기
정답: B) 노드 필터링
설명: Kubernetes 스케줄러는 포드를 노드에 할당할 때 다음과 같은 단계를 거칩니다:
- 노드 필터링: 포드를 실행할 수 있는 노드를 식별합니다. 이 단계에서는 리소스 요구 사항, 노드 선택기, 어피니티, 테인트 및 톨러레이션 등을 고려합니다.
- 노드 점수 매기기: 필터링된 노드에 점수를 할당합니다.
- 최적의 노드 선택: 가장 높은 점수를 받은 노드를 선택합니다.
- 바인딩: 선택된 노드에 포드를 할당합니다.
따라서 첫 번째 단계는 노드 필터링입니다.
- 노드 어피니티(Node Affinity)와 포드 어피니티(Pod Affinity)의 주요 차이점은 무엇인가요?
- A) 노드 어피니티는 하드 제약 조건만 지원하고, 포드 어피니티는 소프트 제약 조건만 지원한다
- B) 노드 어피니티는 노드 레이블을 기반으로 하고, 포드 어피니티는 포드 레이블을 기반으로 한다
- C) 노드 어피니티는 클러스터 수준에서 적용되고, 포드 어피니티는 네임스페이스 수준에서 적용된다
- D) 노드 어피니티는 스케줄링 시에만 적용되고, 포드 어피니티는 런타임에도 적용된다
정답 보기
정답: B) 노드 어피니티는 노드 레이블을 기반으로 하고, 포드 어피니티는 포드 레이블을 기반으로 한다
설명: 노드 어피니티(Node Affinity)는 노드의 레이블을 기반으로 포드가 특정 노드에 스케줄링되도록 제약 조건을 설정합니다. 예를 들어, GPU가 있는 노드나 특정 가용 영역의 노드에 포드를 배치할 수 있습니다.
포드 어피니티(Pod Affinity)는 이미 실행 중인 다른 포드의 레이블을 기반으로 포드가 스케줄링되도록 제약 조건을 설정합니다. 예를 들어, 프론트엔드 포드를 백엔드 포드와 같은 노드나 같은 가용 영역에 배치할 수 있습니다.
두 가지 모두 requiredDuringSchedulingIgnoredDuringExecution(하드 제약 조건)과 preferredDuringSchedulingIgnoredDuringExecution(소프트 제약 조건)을 지원합니다.
- 테인트(Taint)와 톨러레이션(Toleration)의 주요 목적은 무엇인가요?
- A) 특정 포드가 특정 노드에만 스케줄링되도록 보장
- B) 노드가 특정 포드를 거부하도록 하고, 포드가 이를 허용할 수 있게 함
- C) 포드 간의 어피니티 규칙 설정
- D) 클러스터의 리소스 사용량 최적화
정답 보기
정답: B) 노드가 특정 포드를 거부하도록 하고, 포드가 이를 허용할 수 있게 함
설명: 테인트(Taint)는 노드에 적용되어 특정 포드가 해당 노드에 스케줄링되지 않도록 합니다. 톨러레이션(Toleration)은 포드에 적용되어 특정 테인트가 있는 노드에도 스케줄링될 수 있도록 합니다.
이 메커니즘은 특정 노드를 특정 워크로드 전용으로 예약하거나, 특정 하드웨어를 필요로 하는 워크로드를 적절한 노드에 배치하는 데 유용합니다. 예를 들어, GPU 노드에 테인트를 적용하고 GPU를 필요로 하는 포드에만 해당 톨러레이션을 부여할 수 있습니다.
테인트와 톨러레이션은 노드 어피니티와 반대 방향으로 작동합니다. 노드 어피니티는 포드가 특정 노드에 끌리도록 하는 반면, 테인트와 톨러레이션은 포드가 특정 노드를 피하도록 합니다(톨러레이션이 없는 경우).
- 포드 우선순위(Pod Priority)와 선점(Preemption)의 관계는 무엇인가요?
- A) 우선순위가 높은 포드는 스케줄링 시 우선순위가 낮은 포드를 선점할 수 있다
- B) 우선순위는 포드의 CPU 및 메모리 할당량을 결정한다
- C) 선점은 노드 유지 보수 중에만 발생한다
- D) 우선순위와 선점은 서로 관련이 없다
정답 보기
정답: A) 우선순위가 높은 포드는 스케줄링 시 우선순위가 낮은 포드를 선점할 수 있다
설명: 포드 우선순위(Pod Priority)는 포드의 중요도를 나타내는 값입니다. PriorityClass 리소스를 통해 정의되며, 포드 스펙에서 참조됩니다.
선점(Preemption)은 우선순위가 높은 포드가 스케줄링될 때 리소스가 부족한 경우, 스케줄러가 우선순위가 낮은 포드를 종료하여 리소스를 확보하는 프로세스입니다.
이 메커니즘은 중요한 워크로드의 배치 가능성을 높이지만 제약 조건·용량 부족이 남으면 스케줄링을 보장하지 못합니다. 예를 들어, 프로덕션 워크로드에 높은 우선순위를 부여하고 개발/테스트 워크로드에 낮은 우선순위를 부여하면, 리소스 경합 시 프로덕션 워크로드가 우선적으로 실행됩니다.
- 노드 셀렉터(Node Selector)와 노드 어피니티(Node Affinity)의 주요 차이점은 무엇인가요?
- A) 노드 셀렉터는 하드 제약 조건만 지원하고, 노드 어피니티는 하드 및 소프트 제약 조건을 모두 지원한다
- B) 노드 셀렉터는 여러 레이블을 지원하지 않지만, 노드 어피니티는 지원한다
- C) 노드 셀렉터는 클러스터 수준에서 적용되고, 노드 어피니티는 네임스페이스 수준에서 적용된다
- D) 노드 셀렉터는 레이블 키만 지정할 수 있고, 노드 어피니티는 키와 값을 모두 지정할 수 있다
정답 보기
정답: A) 노드 셀렉터는 하드 제약 조건만 지원하고, 노드 어피니티는 하드 및 소프트 제약 조건을 모두 지원한다
설명: 노드 셀렉터(Node Selector)는 포드 스펙에서 nodeSelector 필드를 사용하여 특정 레이블이 있는 노드에만 포드를 스케줄링하는 간단한 방법입니다. 이는 항상 하드 제약 조건으로 작동합니다. 즉, 조건을 만족하는 노드가 없으면 포드는 스케줄링되지 않습니다.
노드 어피니티(Node Affinity)는 더 표현력이 풍부한 언어를 제공하며, 두 가지 유형의 제약 조건을 지원합니다:
requiredDuringSchedulingIgnoredDuringExecution: 하드 제약 조건으로, 조건을 만족하는 노드가 없으면 포드는 스케줄링되지 않습니다.preferredDuringSchedulingIgnoredDuringExecution: 소프트 제약 조건으로, 조건을 만족하는 노드가 선호되지만, 없는 경우에도 다른 노드에 스케줄링될 수 있습니다.
또한 노드 어피니티는 In, NotIn, Exists, DoesNotExist, Gt, Lt 등의 연산자를 사용하여 더 복잡한 조건을 표현할 수 있습니다.
- Kubernetes에서 노드 압력 축출(Node-pressure Eviction)을 발생시키는 주요 원인은 무엇인가요?
- A) 포드의 우선순위가 낮을 때
- B) 노드의 리소스(메모리, 디스크 등)가 부족할 때
- C) 포드가 너무 오래 실행되었을 때
- D) 포드의 레플리카 수가 너무 많을 때
정답 보기
정답: B) 노드의 리소스(메모리, 디스크 등)가 부족할 때
설명: Kubernetes에서 포드 축출(Pod Eviction)은 주로 노드의 리소스가 부족할 때 발생합니다. kubelet은 노드의 메모리, 디스크 공간, PID 등의 리소스 사용량을 모니터링하고, 특정 임계값을 초과하면 포드 축출을 시작합니다.
축출 대상은 요청 초과 사용 여부, 파드 우선순위, 요청 대비 사용량으로 정합니다. QoS 클래스만으로 고정된 순서를 정하지 않으며 디스크·PID 압력도 고려해야 합니다.
노드 유지 보수, 노드 풀 크기 조정, 노드 장애 등의 이유로도 포드 축출이 발생할 수 있습니다.
- Kubernetes에서 DaemonSet 포드의 스케줄링 특성은 무엇인가요?
- A) 실행 조건을 만족하는 대상 노드마다 하나씩 스케줄링된다
- B) 특정 레이블이 있는 노드에만 스케줄링된다
- C) 기본 스케줄러를 사용하지 않고 직접 노드에 배치된다
- D) 항상 마스터 노드에 스케줄링된다
정답 보기
정답: A) 실행 조건을 만족하는 대상 노드마다 하나씩 스케줄링된다
설명: DaemonSet은 클러스터의 모든 노드(또는 노드 셀렉터를 사용하는 경우 선택된 노드)에 포드의 복사본을 하나씩 실행하도록 설계된 워크로드 리소스입니다. 새 노드가 클러스터에 추가되면 DaemonSet 컨트롤러는 자동으로 해당 노드에 포드를 배치합니다.
DaemonSet은 일반적으로 로깅 에이전트, 모니터링 에이전트, 네트워크 플러그인 등 모든 노드에서 실행해야 하는 백그라운드 서비스에 사용됩니다.
Kubernetes 1.12 이전에는 DaemonSet 컨트롤러가 기본 스케줄러를 우회하고 직접 노드에 포드를 배치했습니다(옵션 C). 그러나 1.12 이후에는 기본 스케줄러를 사용하여 DaemonSet 포드를 스케줄링합니다.
- 파드 수준 리소스 설정 없이 모든 컨테이너의 CPU·메모리 요청이 각각 제한과 같은 경우 QoS 클래스는 무엇인가요?
- A) BestEffort
- B) Burstable
- C) Guaranteed
- D) Critical
정답 보기
정답: C) Guaranteed
설명: Guaranteed는 모든 컨테이너의 CPU·메모리 요청과 제한이 각각 같은 경우입니다. CPU·메모리 요청·제한이 전혀 없으면 BestEffort이고 그 사이의 구성은 Burstable입니다. 파드 수준 리소스를 사용하는 경우에는 별도의 QoS 기준도 적용됩니다. QoS는 PriorityClass가 아니며 Guaranteed도 장애·축출에서 무조건 보호되지 않습니다.
- 노드에
node-role.kubernetes.io/control-plane:NoSchedule테인트가 적용되어 있을 때, 이 노드에 포드를 스케줄링하기 위해 필요한 것은 무엇인가요?- A) 노드 어피니티 규칙
- B) 포드 어피니티 규칙
- C) 해당 테인트에 대한 톨러레이션
- D) 높은 우선순위 클래스
정답 보기
정답: C) 해당 테인트에 대한 톨러레이션
설명: 노드에 node-role.kubernetes.io/control-plane:NoSchedule 테인트가 적용되어 있으면, 기본적으로 포드는 해당 노드에 스케줄링되지 않습니다. 이 노드에 포드를 스케줄링하려면, 포드에 해당 테인트에 대한 톨러레이션을 추가해야 합니다.
예를 들어, 다음과 같은 톨러레이션을 포드 스펙에 추가할 수 있습니다:
tolerations:
- key: "node-role.kubernetes.io/control-plane"
operator: "Exists"
effect: "NoSchedule"이 톨러레이션은 포드가 마스터 노드의 테인트를 허용하도록 하여, 마스터 노드에도 스케줄링될 수 있게 합니다. 이는 클러스터 관리 도구나 모니터링 도구와 같이 마스터 노드에서 실행해야 하는 특정 워크로드에 유용합니다.
- Kubernetes에서 포드 중단 예산(PodDisruptionBudget)의 주요 목적은 무엇인가요?
- A) 포드의 리소스 사용량 제한
- B) Eviction API를 통한 자발적 축출 수 제한
- C) 포드 스케줄링 우선순위 설정
- D) 포드 재시작 정책 정의
정답 보기
정답: B) Eviction API를 통한 자발적 축출 수 제한
설명: PodDisruptionBudget(PDB)은 노드 드레인, 클러스터 업그레이드 등 자발적 중단(voluntary disruption) 상황에서 동시에 사용 불가능해질 수 있는 포드 수를 제한하여 애플리케이션의 최소 가용성을 유지하도록 Eviction API 요청을 제한합니다. 직접 파드 삭제·컨트롤러 롤아웃·노드 압력 축출은 이 검사를 우회합니다.
주관식 문제
- Kubernetes 스케줄러의 필터링 단계에서 사용되는 주요 필터(predicates)를 세 가지 이상 설명하세요.
정답 보기
정답: Kubernetes 스케줄러의 필터링 단계에서 사용되는 주요 필터(predicates)는 다음과 같습니다:
NodeResourcesFit: 포드의 리소스 요청(CPU, 메모리 등)을 충족할 수 있는 노드를 필터링합니다. 노드의 할당 가능한 리소스가 포드의 요청보다 적으면 해당 노드는 필터링됩니다.
NodeName: 포드 스펙에
nodeName필드가 지정된 경우, 해당 이름의 노드만 선택합니다. 일반적인spec.nodeName직접 지정은 스케줄러를 우회하므로 필터 우선순위로 설명하면 안 됩니다.NodeUnschedulable:
Unschedulable플래그가 설정된 노드(예: 유지 보수 모드의 노드)를 필터링합니다.NodeAffinity: 포드의 노드 어피니티 규칙을 충족하는 노드만 선택합니다.
InterPodAffinity: 파드 어피니티·안티-어피니티를 함께 검사합니다.
PodTopologySpread: 토폴로지 분산 제약을 검사합니다.
TaintToleration: 포드가 톨러레이션하지 않는 테인트가 있는 노드를 필터링합니다.
NodePorts: 포드가 요청하는 포트가 이미 노드에서 사용 중인 경우 해당 노드를 필터링합니다.
VolumeBinding: PVC 바인딩과 볼륨 토폴로지 제약을 검사합니다.
NodeVolumeLimits: CSI 드라이버가 보고한 노드별 볼륨 연결 한도를 검사합니다.
(위 중 세 가지 이상만 설명하면 됩니다)
- Kubernetes에서 노드 어피니티(Node Affinity)와 테인트/톨러레이션(Taints/Tolerations)을 함께 사용하는 방법과 그 이점을 설명하세요.
정답 보기
정답: 노드 어피니티와 테인트/톨러레이션은 서로 보완적인 기능으로, 함께 사용하면 포드 배치에 대한 더 세밀한 제어가 가능합니다.
함께 사용하는 방법:
노드 어피니티로 후보 노드 선택: 노드 어피니티를 사용하여 포드가 스케줄링될 수 있는 노드 집합을 정의합니다.
yamlaffinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: gpu-type operator: In values: ["nvidia-tesla-v100"]테인트로 다른 포드 제외: 특수 하드웨어가 있는 노드에 테인트를 적용하여 일반 포드가 해당 노드에 스케줄링되지 않도록 합니다.
bashkubectl taint nodes node1 gpu=true:NoSchedule톨러레이션으로 선택된 포드만 허용: 특정 워크로드에만 톨러레이션을 추가하여 테인트가 있는 노드에 스케줄링될 수 있도록 합니다.
yamltolerations: - key: "gpu" operator: "Equal" value: "true" effect: "NoSchedule"
이점:
양방향 제어:
- 노드 어피니티는 "포드가 특정 노드에 끌리도록" 하는 반면(포드 → 노드)
- 테인트/톨러레이션은 "노드가 특정 포드를 거부하도록" 합니다(노드 → 포드)
- 이 두 가지를 함께 사용하면 양방향에서 포드 배치를 제어할 수 있습니다.
리소스 격리 강화:
- 특수 하드웨어(GPU, FPGA 등)가 있는 노드를 해당 하드웨어를 필요로 하는 워크로드 전용으로 예약할 수 있습니다.
- 테인트로 일반 워크로드를 제외하고, 노드 어피니티로 특정 워크로드를 해당 노드로 유도합니다.
복잡한 배치 시나리오 지원:
- 예: "고성능 GPU가 있는 노드 중에서도 특정 가용 영역에 있는 노드에만 배치"와 같은 복잡한 요구 사항을 구현할 수 있습니다.
리소스 낭비 방지:
- 비싼 리소스(예: GPU)가 있는 노드에 일반 워크로드가 스케줄링되는 것을 방지하여 리소스 낭비를 줄일 수 있습니다.
보안 및 격리:
- 특정 보안 요구 사항이 있는 워크로드를 격리된 노드에 배치할 수 있습니다.
예시 시나리오: GPU 워크로드를 위한 전용 노드 풀을 구성하는 경우:
- GPU 노드에
dedicated=gpu:NoSchedule테인트 적용 - GPU 워크로드에 해당 테인트에 대한 톨러레이션 추가
- GPU 워크로드에
gpu-type=nvidia노드 어피니티 추가
이렇게 하면 GPU 워크로드는 GPU가 있는 노드에만 스케줄링되고, 다른 워크로드는 GPU 노드에 스케줄링되지 않습니다.
- Kubernetes에서 포드 우선순위(Pod Priority)와 선점(Preemption) 메커니즘이 작동하는 방식을 설명하세요.
정답 보기
정답: Kubernetes에서 포드 우선순위와 선점 메커니즘은 다음과 같이 작동합니다:
1. 우선순위 클래스 정의: 먼저 PriorityClass 리소스를 생성하여 다양한 우선순위 레벨을 정의합니다.
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
description: "This priority class should be used for critical production workloads."2. 포드에 우선순위 할당: 포드 스펙에서 priorityClassName 필드를 사용하여 우선순위 클래스를 참조합니다.
apiVersion: v1
kind: Pod
metadata:
name: critical-pod
spec:
priorityClassName: high-priority
containers:
- name: web-server
image: nginx3. 스케줄링 큐 정렬: 포드가 생성되면 스케줄러의 큐에 추가되며, 큐는 우선순위에 따라 정렬됩니다. 우선순위가 높은 포드가 먼저 스케줄링됩니다.
4. 선점 프로세스: 우선순위가 높은 포드가 스케줄링될 때 적합한 노드가 없으면 선점 프로세스가 시작됩니다:
a. 스케줄러는 각 노드를 평가하여 우선순위가 낮은 포드를 선점(제거)했을 때 새 포드를 스케줄링할 수 있는지 확인합니다.
b. 가장 적합한 노드를 선택합니다(선점으로 인한 영향이 최소화되는 노드).
c. API를 통해 선택된 노드의 낮은 우선순위 파드 삭제를 요청하며 kubelet·런타임이 종료합니다. 이때 여러 포드를 선점해야 할 수도 있습니다.
d. 선점된 포드가 정상적으로 종료되고 리소스가 확보되면, 우선순위가 높은 포드가 해당 노드에 스케줄링됩니다.
5. 종료 유예 기간: 선점된 포드는 즉시 강제 종료되지 않고, 포드의 terminationGracePeriodSeconds 설정(기본값: 30초)에 따라 정상적으로 종료됩니다. 이 기간 동안 포드는 정리 작업을 수행할 수 있습니다.
6. 선점 제한 사항:
- 우선순위가 같거나 높은 포드는 선점되지 않습니다.
- 시스템 PriorityClass는 사용자 정의 클래스보다 높은 값으로 보호하지만 kube-system 네임스페이스 자체가 선점 면제를 의미하지는 않습니다.
- PodDisruptionBudget은 best-effort로 고려되며 위반을 피할 수 없는 경우에도 선점할 수 있습니다.
7. 이벤트 기록: 선점이 발생하면 이벤트가 기록되어 어떤 포드가 왜 선점되었는지 추적할 수 있습니다.
주요 사용 사례:
- 중요한 프로덕션 워크로드에 높은 우선순위 부여
- 클러스터 자동 확장 전에 덜 중요한 워크로드 선점
- 리소스 경합 시 중요한 서비스의 가용성 보장
- 배치 작업과 서비스 워크로드 간의 리소스 균형 조정
모범 사례:
- 우선순위 클래스를 너무 많이 만들지 않기
- 시스템 우선순위 클래스(system-cluster-critical, system-node-critical)보다 낮은 값 사용
- 우선순위와 QoS 클래스를 함께 고려하여 리소스 관리 전략 수립
- Kubernetes에서 포드 축출(Pod Eviction)의 종류와 각각의 발생 조건을 설명하세요.
정답 보기
정답: Kubernetes에서 포드 축출(Pod Eviction)은 크게 두 가지 유형으로 나눌 수 있습니다: 노드 수준 축출과 API 서버 수준 축출입니다.
1. 노드 수준 축출 (Node-level Eviction)
kubelet에 의해 관리되며, 노드의 리소스 부족 상황에 대응하기 위해 발생합니다.
발생 조건:
- 메모리 부족: 노드의 사용 가능한 메모리가 임계값 아래로 떨어질 때
memory.available < 100Mi(기본값)
- 디스크 공간 부족: 노드의 디스크 공간이 임계값 아래로 떨어질 때
nodefs.available < 10%(기본값)nodefs.inodesFree < 5%(기본값)imagefs.available < 15%(기본값)
- PID 부족: 사용 가능한 프로세스 ID가 임계값 아래로 떨어질 때
- PID 임계값은 명시적으로 설정해야 하며 기본 10% 임계값은 없습니다.
심각도 수준:
- 소프트 축출(Soft Eviction): 유예 기간이 있으며, 임계값을 초과한 후 명시한 유예 시간 동안 지속되면 축출이 시작됩니다. 소프트 임계값·유예 기간은 기본 5분으로 제공되지 않습니다.
- 예:
evictionSoftGracePeriod: {memory.available: "1m30s"}
- 예:
- 하드 축출(Hard Eviction): 즉시 축출이 시작됩니다.
- 예:
eviction-hard=memory.available<100Mi
- 예:
축출 대상 선택: 요청 초과 사용 여부, 파드 우선순위, 요청 대비 사용량을 기준으로 선택합니다. QoS만으로 BestEffort → Burstable → Guaranteed 순서를 강제하지 않습니다. 위 memory/nodefs 기본값은 Linux 기준이며 Windows의 기본 메모리 임계값은 다릅니다. 하드 임계값은 유예 없이 종료할 수 있고 소프트 종료 유예는 evictionMaxPodGracePeriod에도 영향을 받습니다.
2. API 서버 수준 축출 (API Server-level Eviction)
클러스터 관리자나 자동화 도구에 의해 의도적으로 발생하는 축출입니다.
발생 조건:
- 노드 드레이닝(Node Draining): 노드 유지 보수, 업그레이드, 삭제 등을 위해 노드의 모든 포드를 축출
kubectl drain <node-name>
- 테인트 기반 축출: 노드에
NoExecute효과가 있는 테인트를 추가하고, 해당 테인트를 톨러레이션하지 않는 포드 축출 - Eviction API 호출:
policy/v1Eviction 하위 리소스를 사용합니다. 일반 Pod DELETE와 구분되며 직접 삭제는 PDB를 검사하지 않습니다.
제약 조건:
- PodDisruptionBudget(PDB): 자발적 중단 중에도 애플리케이션의 가용성을 보장하기 위한 제약 조건
minAvailable: 중단 중에도 항상 사용 가능해야 하는 최소 포드 수 또는 비율maxUnavailable: 중단 중에 사용할 수 없게 될 수 있는 최대 포드 수 또는 비율
- PDB는 Eviction API 요청을 제한합니다. 직접 Pod DELETE, NoExecute 테인트 축출, 노드 압력 축출은 이 게이트를 우회합니다.
3. 기타 축출 시나리오
- 노드 자동 확장 축소: 클러스터 자동 확장기가 노드를 제거할 때 포드 축출
- 선점(Preemption): 우선순위가 높은 포드를 위해 우선순위가 낮은 포드 축출
- 노드 장애: 노드가 실패하면 컨트롤 플레인이 해당 노드의 포드를 축출로 표시
축출 영향 최소화 전략:
- 적절한 QoS 클래스 설정(중요한 워크로드에 Guaranteed QoS 사용)
- PodDisruptionBudget 구성
- 적절한 리소스 요청 및 제한 설정
- 다중 가용 영역에 워크로드 분산
- 노드 리소스 모니터링 및 경고 설정
- Kubernetes에서 DaemonSet의 스케줄링 동작과 일반 포드의 스케줄링 동작의 차이점을 설명하세요.
정답 보기
정답: 현재 DaemonSet 컨트롤러는 대상 노드에 맞는 어피니티를 가진 파드를 생성하고 기본 스케줄러가 이를 바인딩하므로, 클러스터의 모든(또는 노드 셀렉터로 지정된) 노드에 자동으로 포드가 생성됩니다. 노드가 추가되면 자동으로 새 포드가 스케줄링되고, 노드가 제거되면 해당 포드도 함께 정리됩니다. 반면 일반 포드(Deployment 등)는 스케줄러가 리소스 요청, 어피니티, 테인트/톨러레이션 등을 평가하여 지정된 replica 수만큼 적절한 노드를 선택해 배치하며, 노드 수와 포드 수가 1:1로 고정되지 않습니다.
실습 문제
- 다음 요구 사항에 맞는 노드 어피니티(Node Affinity) 설정을 포함한 포드 매니페스트를 작성하세요:
- 포드 이름: web-server
- 이미지: nginx:1.30.4
- 가용 영역(zone)이 "us-east-1a" 또는 "us-east-1b"인 노드에만 스케줄링
- 인스턴스 타입(instance-type)이 "m5.large"인 노드 선호
정답 보기
정답:
apiVersion: v1
kind: Pod
metadata:
name: web-server
spec:
containers:
- name: nginx
image: nginx:1.30.4
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
- us-east-1b
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: node.kubernetes.io/instance-type
operator: In
values:
- m5.large이 포드 매니페스트는 다음과 같은 노드 어피니티 규칙을 설정합니다:
requiredDuringSchedulingIgnoredDuringExecution: 포드는 반드시 "us-east-1a" 또는 "us-east-1b" 가용 영역에 있는 노드에만 스케줄링됩니다. 이 조건을 만족하는 노드가 없으면 포드는 스케줄링되지 않습니다.preferredDuringSchedulingIgnoredDuringExecution: 가능하다면 "m5.large" 인스턴스 타입의 노드에 스케줄링됩니다. 이러한 노드가 없어도 포드는 다른 적합한 노드에 스케줄링될 수 있습니다.
topology.kubernetes.io/zone과 node.kubernetes.io/instance-type은 표준 노드 레이블이며 EKS 같은 클라우드 통합이 값을 설정합니다. 모든 자체 관리형 노드에 자동으로 존재한다고 가정하지 말고 확인하세요.
- 다음 요구 사항에 맞는 테인트(Taint)와 톨러레이션(Toleration) 설정을 작성하세요:
- 노드 이름: worker-1
- 테인트: dedicated=database:NoSchedule
- 데이터베이스 포드(이름: postgres-db, 이미지: postgres:17)에 적절한 톨러레이션 추가
정답 보기
정답:
노드에 테인트 적용:
kubectl taint nodes worker-1 dedicated=database:NoSchedule데이터베이스 포드 매니페스트(같은 네임스페이스에 password 키를 가진 postgres-credentials Secret을 먼저 생성하세요. 이 예시는 배치 설명용이며 영구 DB에는 PVC가 필요합니다):
apiVersion: v1
kind: Pod
metadata:
name: postgres-db
spec:
containers:
- name: postgres
image: postgres:17
env:
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-credentials
key: password
tolerations:
- key: "dedicated"
operator: "Equal"
value: "database"
effect: "NoSchedule"이 설정은 다음과 같이 작동합니다:
worker-1노드에dedicated=database:NoSchedule테인트를 적용하여, 이 테인트를 톨러레이션하지 않는 포드는 이 노드에 스케줄링되지 않습니다.postgres-db포드에는 이 테인트에 대한 톨러레이션을 추가하여, 이 노드에 스케줄링될 수 있도록 합니다.
톨러레이션의 각 필드 의미:
key: 테인트의 키와 일치해야 합니다 ("dedicated").operator: "Equal"은 값이 정확히 일치해야 함을 의미합니다. "Exists"를 사용하면 값을 지정하지 않아도 됩니다.value: 테인트의 값과 일치해야 합니다 ("database").effect: 테인트의 효과와 일치해야 합니다 ("NoSchedule").
- 다음 요구 사항에 맞는 포드 어피니티(Pod Affinity) 및 안티-어피니티(Anti-Affinity) 설정을 포함한 디플로이먼트 매니페스트를 작성하세요:
- 디플로이먼트 이름: web-frontend
- 이미지: nginx:1.30.4
- 레플리카: 3
- app=cache 레이블이 있는 포드와 같은 노드에 배치(어피니티)
- 같은 디플로이먼트의 다른 포드와는 다른 노드에 배치(안티-어피니티)
정답 보기
정답:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-frontend
spec:
replicas: 3
selector:
matchLabels:
app: web-frontend
template:
metadata:
labels:
app: web-frontend
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: "kubernetes.io/hostname"
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-frontend
topologyKey: "kubernetes.io/hostname"
containers:
- name: nginx
image: nginx:1.30.4이 디플로이먼트 매니페스트는 다음과 같은 어피니티 규칙을 설정합니다:
포드 어피니티(Pod Affinity):
app=cache레이블이 있는 포드와 같은 노드에 배치됩니다.topologyKey: "kubernetes.io/hostname"은 같은 호스트(노드)에 배치되어야 함을 의미합니다.requiredDuringSchedulingIgnoredDuringExecution은 이 조건이 반드시 충족되어야 함을 의미합니다.
포드 안티-어피니티(Pod Anti-Affinity):
app=web-frontend레이블이 있는 다른 포드와는 다른 노드에 배치됩니다.topologyKey: "kubernetes.io/hostname"은 다른 호스트(노드)에 배치되어야 함을 의미합니다.requiredDuringSchedulingIgnoredDuringExecution은 이 조건이 반드시 충족되어야 함을 의미합니다.
이 설정을 통해 각 web-frontend 포드는 cache 포드가 있는 노드에 배치되지만, 다른 web-frontend 포드와는 다른 노드에 배치됩니다. 세 복제본을 모두 배치하려면 같은 네임스페이스의 cache 파드가 적격 노드 최소 3개에 있어야 합니다. 그렇지 않으면 일부 파드가 Pending에 남습니다.
- 다음 요구 사항에 맞는 PriorityClass와 이를 사용하는 포드 매니페스트를 작성하세요:
- PriorityClass 이름: high-priority
- 우선순위 값: 100000
- 포드 이름: critical-service
- 이미지: nginx:1.30.4
- QoS 클래스: Guaranteed (CPU 요청 및 제한: 500m, 메모리 요청 및 제한: 512Mi)
정답 보기
정답:
PriorityClass 매니페스트:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 100000
globalDefault: false
description: "This priority class is for critical services that should be scheduled first."포드 매니페스트:
apiVersion: v1
kind: Pod
metadata:
name: critical-service
spec:
priorityClassName: high-priority
containers:
- name: nginx
image: nginx:1.30.4
resources:
requests:
cpu: 500m
memory: 512Mi
limits:
cpu: 500m
memory: 512Mi이 설정은 다음과 같이 작동합니다:
high-priorityPriorityClass는 100000의 우선순위 값을 가집니다. 이 값이 클수록 우선순위가 높습니다.critical-service포드는 이 PriorityClass를 참조하여 높은 우선순위를 가집니다.- 리소스 요청과 제한이 동일하게 설정되어 있어 Guaranteed QoS 클래스에 속합니다.
Guaranteed QoS 클래스는 다음 조건을 만족해야 합니다:
- 모든 컨테이너가 CPU와 메모리에 대한 요청과 제한을 모두 지정해야 합니다.
- 각 컨테이너의 CPU 요청과 CPU 제한이 동일해야 합니다.
- 각 컨테이너의 메모리 요청과 메모리 제한이 동일해야 합니다.
스케줄링에서 높은 우선순위가 고려되지만 축출 면제는 아닙니다. 실제 축출은 노드 압력, 요청 대비 사용량과 우선순위에 따라 달라집니다.
- 다음 요구 사항에 맞는 PodDisruptionBudget 매니페스트를 작성하세요:
- 이름: web-pdb
- 대상 포드 셀렉터: app=web-server
- 정상적인 Eviction API 축출을 최소 2개 Available 조건으로 제한
정답 보기
정답:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: web-server이 PodDisruptionBudget(PDB)은 다음과 같이 작동합니다:
app=web-server레이블이 있는 포드에 적용됩니다.minAvailable: 2는 자발적 중단(예: 노드 드레이닝, 클러스터 업그레이드) 중에 Available 수를 최소 2개로 유지하도록 Eviction API를 제한합니다. 가용성을 직접 생성·보장하는 설정은 아닙니다.
원하는 복제본이 3개인 워크로드에서는 다음 maxUnavailable: 1이 같은 효과를 낼 수 있습니다:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: web-pdb
spec:
maxUnavailable: 1 # 최대 1개의 포드만 사용 불가능할 수 있음
selector:
matchLabels:
app: web-serverPDB는 다음과 같은 상황에서 유용합니다:
- 클러스터 업그레이드 중 서비스 가용성 보장
- 노드 드레이닝 중 애플리케이션 중단 최소화
- 자동 확장 축소 중 서비스 연속성 유지
PDB는 비자발적 중단(예: 노드 장애, 하드웨어 장애)에는 영향을 미치지 않습니다.
고급 주제
커스텀 스케줄러 구현: Kubernetes에서는 기본 스케줄러 외에도 커스텀 스케줄러를 구현하여 특정 워크로드에 대한 스케줄링 요구 사항을 충족시킬 수 있습니다. 다음 중 커스텀 스케줄러를 구현하는 방법으로 올바른 것은 무엇인가요?
- A) 기존 kube-scheduler를 수정하여 새로운 스케줄링 알고리즘 추가
- B) 별도의 스케줄러 포드를 배포하고
schedulerName필드를 사용하여 포드 연결 - C) 모든 포드에 특정 어노테이션을 추가하여 스케줄링 동작 변경
- D) kubelet 설정을 수정하여 로컬 스케줄링 활성화
정답 보기
정답: B) 별도의 스케줄러 포드를 배포하고 schedulerName 필드를 사용하여 포드 연결
설명: Kubernetes에서 커스텀 스케줄러를 구현하는 가장 일반적인 방법은 별도의 스케줄러 포드를 배포하고, 포드 스펙의 schedulerName 필드를 사용하여 해당 스케줄러가 특정 포드를 스케줄링하도록 지정하는 것입니다.
예를 들어:
apiVersion: v1
kind: Pod
metadata:
name: custom-scheduled-pod
spec:
schedulerName: my-custom-scheduler # 커스텀 스케줄러 이름
containers:
- name: container
image: nginx커스텀 스케줄러는 Kubernetes API 서버와 통신하여 포드 및 노드 정보를 가져오고, 자체 알고리즘을 사용하여 포드를 노드에 할당합니다. 이를 통해 특정 워크로드에 대한 특별한 스케줄링 요구 사항(예: GPU 워크로드 최적화, 데이터 지역성 고려, 특수 하드웨어 활용 등)을 충족시킬 수 있습니다.
기존 kube-scheduler를 수정하는 것은 가능하지만 유지 관리가 어렵고, 어노테이션만으로는 완전한 스케줄링 동작을 변경할 수 없으며, kubelet은 스케줄링 결정을 담당하지 않습니다.
Descheduler: Kubernetes Descheduler는 이미 실행 중인 포드를 재스케줄링하여 클러스터 리소스 사용을 최적화하는 도구입니다. 다음 중 Descheduler의 주요 정책이 아닌 것은 무엇인가요?
- A) LowNodeUtilization - 노드 간 리소스 사용률 불균형 해소
- B) RemoveDuplicates - 동일한 노드에 있는 동일한 ReplicaSet의 포드 제거
- C) PodLifeTimeExtension - 오래 실행된 포드의 수명 연장
- D) RemovePodsViolatingInterPodAntiAffinity - 포드 안티-어피니티 규칙을 위반하는 포드 제거
정답 보기
정답: C) PodLifeTimeExtension - 오래 실행된 포드의 수명 연장
설명: Kubernetes Descheduler는 클러스터의 포드 배치를 최적화하기 위해 다양한 정책을 제공합니다. 그러나 "PodLifeTimeExtension"은 실제 Descheduler 정책이 아닙니다. 오히려 Descheduler에는 "PodLifeTime"이라는 정책이 있는데, 이는 오래 실행된 포드를 제거하여 새로운 노드에 재스케줄링하도록 합니다.
Descheduler의 실제 주요 정책은 다음과 같습니다:
LowNodeUtilization: 노드 간 리소스 사용률 불균형을 해소합니다. 일부 노드가 과소 활용되고 다른 노드가 과다 활용되는 경우, 과다 활용된 노드에서 포드를 제거하여 과소 활용된 노드로 재스케줄링합니다.
RemoveDuplicates: 동일한 노드에 있는 동일한 ReplicaSet, StatefulSet 또는 Job의 복제본 포드를 제거합니다. 이는 고가용성을 향상시키기 위해 복제본을 다른 노드로 분산시키는 데 도움이 됩니다.
RemovePodsViolatingInterPodAntiAffinity: 포드 안티-어피니티 규칙을 위반하는 포드를 제거합니다. 이는 노드 추가 후 안티-어피니티 규칙이 위반될 수 있는 경우에 유용합니다.
RemovePodsViolatingNodeAffinity: 노드 어피니티 규칙을 위반하는 포드를 제거합니다. 노드 레이블이 변경되어 기존 포드가 노드 어피니티 규칙을 더 이상 만족하지 않는 경우에 유용합니다.
PodLifeTime: 지정된 기간보다 오래 실행된 포드를 제거합니다.
RemovePodsHavingTooManyRestarts: 너무 많은 재시작을 한 포드를 제거합니다.
RemovePodsViolatingTopologySpreadConstraint: 토폴로지 분산 제약 조건을 위반하는 포드를 제거합니다.
Descheduler는 클러스터 관리자가 설정한 정책에 따라 주기적으로 실행되며, 제거된 포드는 해당 컨트롤러(예: Deployment 컨트롤러)에 의해 다시 생성되어 더 나은 배치를 얻을 수 있습니다.
노드 테인트 기반 축출(Taint-Based Evictions): Kubernetes는 노드 상태에 따라 자동으로 테인트를 적용하여 포드를 축출할 수 있습니다. 다음 중 노드 상태에 따른 테인트가 아닌 것은 무엇인가요?
- A)
node.kubernetes.io/not-ready- 노드가 준비되지 않은 상태 - B)
node.kubernetes.io/unreachable- 노드가 도달할 수 없는 상태 - C)
node.kubernetes.io/unschedulable- 노드의 스케줄링 비활성화 - D)
node.kubernetes.io/high-load- 노드의 부하가 높은 상태
- A)
정답 보기
정답: D) node.kubernetes.io/high-load - 노드의 부하가 높은 상태
설명: Kubernetes는 노드의 상태에 따라 자동으로 테인트를 적용하여 새로운 포드가 스케줄링되는 것을 방지하고, 경우에 따라 기존 포드를 축출할 수 있습니다. 그러나 node.kubernetes.io/high-load는 Kubernetes에서 자동으로 적용하는 테인트가 아닙니다.
Kubernetes에서 자동으로 적용하는 노드 상태 테인트는 다음과 같습니다:
node.kubernetes.io/not-ready: 노드가 준비되지 않은 상태일 때 적용됩니다. 노드가 상태 점검에 실패하거나 kubelet이 API 서버에 보고하지 않는 경우 발생합니다.node.kubernetes.io/unreachable: 노드 컨트롤러가 노드에 연결할 수 없을 때 적용됩니다. 네트워크 문제나 노드 장애로 인해 발생할 수 있습니다.node.kubernetes.io/unschedulable: 노드가 스케줄 불가로 표시된 상태와 관련됩니다. 레거시out-of-disk는 현재 자동 테인트가 아닙니다.node.kubernetes.io/memory-pressure: 노드의 메모리 압박이 있을 때 적용됩니다.node.kubernetes.io/disk-pressure: 노드의 디스크 압박이 있을 때 적용됩니다.node.kubernetes.io/pid-pressure: 노드의 PID 압박이 있을 때 적용됩니다(너무 많은 프로세스가 실행 중).node.kubernetes.io/network-unavailable: 노드의 네트워크가 올바르게 구성되지 않았을 때 적용됩니다.
not-ready·unreachable에는 NoExecute 기반 축출과 기본 300초 톨러레이션이 관련됩니다. memory/disk/pid-pressure 같은 압력 테인트는 일반적으로 NoSchedule이며 기존 파드의 압력 축출은 kubelet의 별도 메커니즘입니다. 포드는 tolerationSeconds 필드를 사용하여 이러한 상태가 일시적인 경우 일정 시간 동안 노드에 남아있을 수 있습니다.
중요한 시스템 포드는 이러한 테인트에 대한 톨러레이션을 기본적으로 가지고 있어 노드 문제 시에도 계속 실행될 수 있습니다.
토폴로지 분산 제약 조건(Topology Spread Constraints): Kubernetes 1.19부터 토폴로지 분산 제약 조건을 사용하여 포드를 다양한 토폴로지 도메인에 분산시킬 수 있습니다. 다음 중 토폴로지 분산 제약 조건에 대한 설명으로 올바르지 않은 것은 무엇인가요?
- A) 가용 영역, 노드, 랙 등 다양한 토폴로지 도메인에 포드를 분산시킬 수 있다
- B)
maxSkew필드는 토폴로지 도메인 간 포드 수의 최대 차이를 지정한다 - C)
whenUnsatisfiable: DoNotSchedule은 제약 조건을 만족할 수 없을 때 포드를 스케줄링하지 않는다 - D) 토폴로지 분산 제약 조건은 기존 포드에 자동으로 적용되어 재배치한다
정답 보기
정답: D) 토폴로지 분산 제약 조건은 기존 포드에 자동으로 적용되어 재배치한다
설명: 토폴로지 분산 제약 조건(Topology Spread Constraints)은 포드를 다양한 토폴로지 도메인(예: 가용 영역, 노드, 랙 등)에 균등하게 분산시키는 기능을 제공합니다. 그러나 이 기능은 새로 생성되는 포드에만 적용되며, 기존 포드를 자동으로 재배치하지 않습니다.
토폴로지 분산 제약 조건의 주요 특징은 다음과 같습니다:
토폴로지 도메인:
topologyKey필드를 사용하여 포드를 분산시킬 토폴로지 도메인을 지정합니다. 예를 들어,topology.kubernetes.io/zone은 가용 영역 간에 포드를 분산시킵니다.최대 편차(maxSkew): 토폴로지 도메인 간 포드 수의 최대 허용 차이를 지정합니다. DoNotSchedule에서는 대상 도메인의 일치 파드 수와 전역 최소값의 차이를 제한합니다. 적격 도메인이 minDomains 미만이면 최소값을 0으로 계산하며 ScheduleAnyway에서는 선호 점수로 작동합니다.
불만족 시 동작(whenUnsatisfiable): 제약 조건을 만족할 수 없을 때의 동작을 지정합니다:
DoNotSchedule: 제약 조건을 만족할 수 없으면 포드를 스케줄링하지 않습니다.ScheduleAnyway: 제약 조건을 만족할 수 없어도 최대한 균등하게 분산시키려고 시도합니다.
레이블 셀렉터(labelSelector): 어떤 포드를 계산에 포함할지 지정합니다.
예시:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
labels:
app: web-server
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: DoNotSchedule
labelSelector:
matchLabels:
app: web-server
containers:
- name: nginx
image: nginx이 예시에서는 app=web-server 레이블이 있는 포드가 가용 영역 간에 최대 1의 차이로 분산되도록 합니다.
기존 포드의 재배치가 필요한 경우, Descheduler의 RemovePodsViolatingTopologySpreadConstraint 정책을 사용하여 제약 조건을 위반하는 포드를 제거하고 재스케줄링할 수 있습니다.
리소스 할당 및 QoS: Kubernetes에서 포드의 QoS(Quality of Service) 클래스는 리소스 부족 시 축출 우선순위에 영향을 미칩니다. 다음 중 QoS 클래스에 대한 설명으로 올바르지 않은 것은 무엇인가요?
- A) Guaranteed QoS 클래스는 모든 컨테이너의 리소스 요청과 제한이 동일할 때 할당된다
- B) Burstable QoS 클래스는 적어도 하나의 컨테이너가 리소스 요청을 지정했지만 Guaranteed 조건을 만족하지 않을 때 할당된다
- C) BestEffort QoS 클래스는 모든 컨테이너가 리소스 요청과 제한을 지정하지 않았을 때 할당된다
- D) 리소스 부족 시 Guaranteed QoS 클래스의 포드가 가장 먼저 축출된다
정답 보기
정답: D) 리소스 부족 시 Guaranteed QoS 클래스의 포드가 가장 먼저 축출된다
설명: Kubernetes에서 QoS(Quality of Service) 클래스는 리소스 부족 상황에서 포드의 축출 우선순위를 결정하는 중요한 요소입니다. 그러나 리소스 부족 시 Guaranteed QoS 클래스의 포드가 가장 먼저 축출된다는 설명은 잘못되었습니다. 실제로는 정반대입니다.
BestEffort는 CPU·메모리 요청·제한이 없고, Guaranteed는 컨테이너 수준 구성에서 모든 CPU·메모리 요청이 각각 제한과 같습니다. 나머지는 Burstable이며 파드 수준 리소스에는 별도 기준이 있습니다.
kubelet은 QoS 자체로 순서를 정하지 않고 요청 초과 사용 여부, 파드 우선순위, 요청 대비 사용량을 평가합니다. 특히 디스크 압력에는 CPU·메모리 QoS만으로 예상할 수 없는 조건이 있습니다. Guaranteed도 시스템 데몬의 과다 사용이나 노드 장애에서 생존을 보장하지 않습니다.
QoS 클래스는 포드의 리소스 요청과 제한 설정에 따라 자동으로 할당되며, 포드 스펙에서 직접 지정할 수 없습니다.
NodeResourcesFit 스코어링 전략: 배치(batch) Job 워크로드가 Karpenter/Cluster Autoscaler와 함께 실행되며, 완전히 비어서 통합(consolidation) 대상이 될 수 있는 노드 수를 최대화하고자 합니다. 어떤
NodeResourcesFit스코어링 전략이 가장 적합하며, 그 이유는 무엇인가요?- A)
LeastAllocated— 모든 노드의 CPU/메모리 사용률을 균등하게 맞추기 때문 - B)
MostAllocated— 이미 가장 바쁜 노드부터 새 포드를 채우고 다른 노드는 비워두기 때문 - C)
LeastAllocated와 동일한 선형 곡선의RequestedToCapacityRatio - D) EKS는 기본 스케줄러 설정을 직접 수정할 수 있으므로 전략 선택이 중요하지 않다
- A)
정답 보기
정답: B) MostAllocated — 이미 가장 바쁜 노드부터 새 포드를 채우고 다른 노드는 비워두기 때문
설명: 워커 노드 3개짜리 임시 kind 클러스터에서 CPU 사용률을 75%/37%/0%로 불균등하게 만든 뒤 검증했습니다. 기본 LeastAllocated 스케줄러는 새 포드 6개를 가장 비어 있던 노드로 몰아 최종 사용률이 75%/37%/37%가 되어 세 노드 모두 사용 중이 되었고(스케일 다운 불가), scoringStrategy.type: MostAllocated로 설정한 두 번째 스케줄러는 동일한 6개 포드를 가장 바쁜 두 노드로 보내 93%/56%/0%가 되어 유휴 노드를 그대로 유지했습니다(통합 대상 가능). Amazon EKS는 컨트롤 플레인이 관리형이므로, MostAllocated를 적용하려면 기본 스케줄러를 수정하는 대신 추가 스케줄러 Deployment를 배포하고 schedulerName으로 대상 포드를 지정해야 합니다.