이번 글에서는 쿠버네티스 스케줄러가 백엔드에서 실제로 어떻게 동작하는지를 먼저 이해하고, 스케줄러가 없거나(혹은 쓰지 않고) 파드를 특정 노드에 직접 배치해야 할 때 사용할 수 있는 대표적인 수동 스케줄링 방법 2가지를 정리합니다.
1) 스케줄러는 파드를 어떻게 “노드에 붙이는가”
파드에는 기본적으로 nodeName 필드가 있다
파드 스펙에는 spec.nodeName이라는 필드가 있습니다.
일반적으로 우리가 파드 매니페스트를 작성할 때는 이 값을 직접 쓰지 않습니다. 이유는 간단합니다:
- 처음 파드가 생성될 때는
spec.nodeName이 비어 있음 - 스케줄러가 이 필드를 채워서 노드를 확정함
스케줄러가 보는 “스케줄링 후보”는 무엇인가
스케줄러는 클러스터 내 파드들을 계속 관찰하면서:
spec.nodeName이 설정되지 않은 파드를 찾습니다.- 이 파드들이 바로 스케줄링 대상(후보) 입니다.
스케줄러가 하는 핵심 작업 흐름
스케줄러는 대략 이런 흐름으로 동작합니다.
spec.nodeName이 비어 있는 파드를 찾는다 (Pending 상태로 남아 있는 경우가 많음)- 스케줄링 알고리즘을 실행해서 “가장 적절한 노드”를 고른다
- 선택한 노드를 파드에 확정하기 위해 Binding 작업을 수행한다
- 이 과정에서 결과적으로 파드의
spec.nodeName이 특정 노드 이름으로 채워집니다.
- 이 과정에서 결과적으로 파드의
정리하면, 스케줄러가 “노드 선정 + 바인딩”을 해주기 때문에 우리는 보통 nodeName을 건드릴 일이 없습니다.
2) 스케줄러가 없다면 파드는 어떻게 되나?
클러스터에 스케줄러가 없거나, 스케줄러가 파드를 바인딩하지 못하는 상황이라면:
- 파드는 계속 Pending(보류) 상태로 남습니다.
- 이유는 단순합니다: 누가
spec.nodeName을 채워줄지 아무도 없기 때문입니다.
이럴 때 필요한 게 바로 “수동 스케줄링”입니다.
3) 수동 스케줄링 방법 1: 파드 생성 시 spec.nodeName을 지정
가장 쉬운 방법은 파드를 만들 때부터 노드를 딱 지정하는 것입니다.
예시: 특정 노드로 파드 고정 배치
apiVersion: v1
kind: Pod
metadata:
name: manual-pod
spec:
nodeName: worker-1 # <- 여기
containers:
- name: nginx
image: nginx:1.27
이렇게 생성하면 쿠버네티스는 스케줄러를 거치지 않고 worker-1에 파드를 붙입니다.
중요한 제약
nodeName은 생성 시점에만 지정하는 것이 일반적입니다.- 이미 생성된 파드에 대해
nodeName을 “수정해서” 다른 노드로 보내는 건 허용되지 않습니다.
즉, “생성 후에 노드를 바꾸는” 방식으로는 수동 스케줄링이 안 됩니다.
따라서, yaml파일을 수정한 후 기존에 존재하던 pod를 내리고 새롭게 띄우는 방식을 아래와 같이 하면 적용 가능합니다.
kubectl replace --force -f nginx.yaml
4) 수동 스케줄링 방법 2: Binding 오브젝트로 스케줄러의 바인딩을 “모방”하기
이미 파드가 생성된 상태인데도 특정 노드에 붙여야 한다면, 스케줄러가 하는 일을 흉내 내야 합니다.
핵심 아이디어는 이겁니다:
- 스케줄러는 내부적으로 Binding 오브젝트를 만들어
- Pods Binding API로 바인딩 요청을 보내서
- 파드의
spec.nodeName을 확정합니다.
우리도 똑같이 할 수 있습니다.
바인딩 요청에 필요한 핵심 정보
- 대상 파드 이름
- 대상 노드 이름
- Binding 오브젝트(JSON)
이 과정에서 강의가 강조하는 포인트가 하나 있습니다:
- Binding은 보통 API 요청 바디가 JSON 형식이므로
YAML로 작성했다면 동등한 JSON 형식으로 변환해서 POST 해야 합니다.
예시: Pods Binding API로 직접 바인딩하기 (JSON)
아래는 “파드 manual-pod를 worker-1에 바인딩”하는 전형적인 형태입니다.
kubectl proxy &
curl -X POST \
-H "Content-Type: application/json" \
--data '{
"apiVersion": "v1",
"kind": "Binding",
"metadata": { "name": "manual-pod" },
"target": { "apiVersion": "v1", "kind": "Node", "name": "worker-1" }
}' \
http://127.0.0.1:8001/api/v1/namespaces/default/pods/manual-pod/binding
metadata.name: 바인딩할 파드 이름target.name: 붙일 노드 이름- 호출 URL:
.../pods/<pod-name>/binding
이 방식은 본질적으로 스케줄러가 하는 바인딩 작업을 API로 직접 수행하는 것입니다.
5) 언제 수동 스케줄링이 유용한가
- 학습/실습 환경에서 스케줄러 없이 동작을 이해하고 싶을 때
- 특정 테스트를 위해 “반드시 이 노드에서만” 실행해야 할 때
- 스케줄러가 비정상인 상황에서 임시로 파드를 살려야 할 때
다만 운영 환경에서는 보통:
nodeName직접 지정은 “하드 고정”이라 유연성이 떨어지고- Binding API 직접 호출은 “자동화/관리 난이도”가 높기 때문에
대부분은 스케줄러 + (nodeSelector / affinity / taints&tolerations 같은 정책)으로 해결하는 편이 일반적입니다.
(이 글은 강의 범위가 “수동 스케줄링”이므로 정책 기반 스케줄링은 다음 글에서 다루는 구성이 좋습니다.)
6) 정리
- 파드에는
spec.nodeName필드가 있으며, 보통은 비어 있다. - 스케줄러는
nodeName이 비어 있는 파드를 찾아 알고리즘을 돌리고,
Binding 작업을 통해 파드의nodeName을 확정한다. - 스케줄러가 없으면 파드는 Pending 상태로 남는다.
- 수동 스케줄링 방법은 대표적으로 2가지:
- 생성 시
spec.nodeName지정 - Binding 오브젝트 + Pods Binding API로 바인딩
- 생성 시
Practice Test: https://uklabs.kodekloud.com/topic/practice-test-manual-scheduling-2/
'CKA' 카테고리의 다른 글
| Scheduling - Taint & Toleration (0) | 2025.12.29 |
|---|---|
| Scheduling- Label & Selector (0) | 2025.12.29 |
| Core concepts - 총 정리 (1) | 2025.12.29 |
| Core Concepts - apply 커맨드 실행시 발생하는 비교 로직 (0) | 2025.12.28 |
| Core Concepts - 명령어 정리 (0) | 2025.12.28 |