3편 · 약 8분
Pod 스케줄링과 리소스
스케줄러가 하는 일
Pod를 만들면 곧바로 노드에서 실행되는 게 아니다. 먼저 kube-scheduler가 "이 Pod를 어느 노드에 둘지"를 결정한다. 스케줄러는 두 단계를 거친다.
- 필터링(Filtering): 이 Pod를 받을 수 있는 노드만 추린다. 자원이 부족하거나, 노드 셀렉터/taint 조건에 안 맞으면 탈락.
- 스코어링(Scoring): 통과한 노드들에 점수를 매겨 가장 좋은 노드를 고른다(자원 여유, 분산 정도 등).
결정이 끝나면 Pod의 nodeName이 채워지고, 그 노드의 kubelet이 실제로 컨테이너를 띄운다.
대기 중 PodPod (요청: CPU 0.5 / Mem 256Mi)
→
kube-scheduler
→
Node A · 여유 없음 ✕Node B · 적합 ✓Node C · taint ✕
배치Node B 에 실행
requests 와 limits
컨테이너마다 자원을 두 가지로 지정한다.
- requests: "최소 이만큼은 보장해줘." 스케줄러는 이 값으로 노드의 여유를 계산해 배치한다.
- limits: "이 이상은 못 쓴다." CPU는 초과 시 스로틀링(억제)되고, 메모리는 초과 시 컨테이너가 OOMKilled 된다.
resources:
requests:
cpu: "500m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"requests를 너무 낮게 잡으면 노드가 과밀해져 성능이 출렁이고, 너무 높게 잡으면 자원이 놀면서 비효율적이다. 운영의 핵심 튜닝 포인트다.
QoS 클래스
requests/limits를 어떻게 줬느냐에 따라 Pod는 세 등급으로 나뉘고, 노드가 메모리 부족에 몰리면 등급이 낮은 Pod부터 퇴출(evict)된다.
| QoS | 조건 | 퇴출 우선순위 |
|---|---|---|
| Guaranteed | 모든 컨테이너가 requests == limits | 가장 나중 |
| Burstable | requests < limits (일부만 설정 포함) | 중간 |
| BestEffort | requests/limits 둘 다 없음 | 가장 먼저 |
배치를 제어하는 도구
- nodeSelector / nodeAffinity: 특정 라벨을 가진 노드에만 배치(예:
disktype=ssd). - taint / toleration: 노드에 "오염"을 찍어 기본적으로 Pod를 거부하고, 그 taint를 견디는(toleration) Pod만 받게 한다. 전용 노드(GPU 등) 격리에 쓴다.
- podAffinity / podAntiAffinity: 다른 Pod와 같이/떨어져 배치. 가용성을 위해 복제본을 노드별로 흩뿌릴 때 antiAffinity를 쓴다.
References
- https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/
- https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
- https://kubernetes.io/docs/concepts/workloads/pods/pod-qos/