KCNA — 쿠버네티스·클라우드 네이티브 입문 · 배치 예산과 입장 정책을 실제 실패로 구분하기 · 이론
낮은 사용률과 비어 있는 배치 예산은 다르다
한 줄 요약
requests는 자리를 고르는 약속이고, limits는 실행 중 사용할 수 있는 양을 제한하는 설정입니다. CPU 사용률이 낮다는 사실만으로 새 Pod가 들어갈 자리가 있다고 판단하지 않습니다.
왜 이게 필요했나
강의실에 사람이 다섯 명만 앉아 있는데 새 수강생이 입장하지 못합니다. 자리가 비어 보이지만 나머지 의자는 오후 수업을 위해 예약되어 있습니다. 지금 앉아 있는 인원과 예약된 좌석은 다른 장부입니다. Kubernetes에서도 현재 사용량과 스케줄링에 사용하는 자원 요청량은 다릅니다. 예약 비유는 배치 판단을 이해하기 위한 것이며, CPU 코어 하나를 특정 컨테이너에 물리적으로 전용 할당한다는 뜻은 아닙니다.
팀에서 작은 Python 앱을 배포했는데 Pod가 Pending에 머문다고 해 봅시다. 코드는 잠들어 있을 뿐이므로 CPU를 거의 쓰지 않습니다. 그런데 매니페스트에는 실수로 requests.cpu가 8이라고 적혀 있고 모든 노드는 그보다 작습니다. 앱이 얼마나 한가한지는 이 문제를 해결하지 못합니다. 앱이 시작하기 전에 선언된 요청이 이미 배치 가능한 노드의 크기를 넘어섰기 때문입니다.
어떻게 동작하나
먼저 네 가지 숫자를 구분합니다.
| 숫자 | 어떤 질문에 답하나 | 확인할 자리 |
| --- | --- | --- |
| capacity | 노드가 보고하는 자원 총량은 얼마인가 | Node.status.capacity |
| allocatable | Pod 배치에 사용할 수 있는 자원량은 얼마인가 | Node.status.allocatable |
| requests | 이 Pod를 배치할 때 계산할 요청량은 얼마인가 | 컨테이너 resources.requests |
| 실제 사용량 | 특정 관측 구간에서 얼마나 썼는가 | 자원 메트릭 API·모니터링 |
이 레슨은 일반 컨테이너의 CPU·메모리 요청에 집중합니다. init 컨테이너, Pod 오버헤드, Pod 수준 자원 설정, 확장 자원 등이 있으면 계산 규칙을 추가로 확인해야 합니다. 단순한 한 컨테이너의 산수를 모든 워크로드에 그대로 적용하지 않습니다.
예를 들어 한 노드의 allocatable CPU가 2이고 이미 배치된 요청 합계가 1.4라면, 새 요청 800m를 더한 합계는 2.2입니다. CPU 조건만으로도 맞지 않습니다. 실제 사용량이 200m로 관측되어도 요청 합계는 저절로 줄지 않습니다. 반대로 요청 합계가 맞는다고 배치 성공이 보장되지는 않습니다. 메모리, 노드 선택 조건, taint, 볼륨 등 다른 조건도 만족해야 합니다.
CPU 1은 한 CPU 단위이고 1000m와 같습니다. 250m는 0.25 CPU이며 노드 전체의 250퍼센트가 아닙니다. 메모리의 Mi와 M도 같지 않습니다. 64Mi는 64×1024×1024바이트이고, 64M는 64×1000×1000바이트입니다. 자원 문제를 읽을 때 단위를 생략하면 서로 다른 장부를 같은 숫자로 비교하게 됩니다.
limits는 다른 축입니다. CPU 제한은 실행 시간을 제한하는 throttling으로, 메모리 제한은 상황에 따라 OOM 종료로 나타날 수 있습니다. requests를 넘었다고 곧바로 종료되는 것은 아닙니다. 요청량은 낮게 쓰고 제한량을 높게 쓰면 여유가 있을 때 더 사용할 수도 있습니다. 그렇다고 요청을 무조건 낮추는 것이 해법은 아닙니다. 과소 요청은 너무 많은 작업을 같은 노드로 보내 성능 경쟁과 압박을 만들 수 있습니다.
현장에서 만나는 모습
실패 지점을 좁히는 순서를 연습합니다.
kubectl -n kcna-capacity get pod oversized -o jsonkubectl -n kcna-capacity describe pod oversizedkubectl get nodes -o json첫째, Pod 객체가 실제로 존재하는지 봅니다. 둘째, spec.nodeName이 있는지와 PodScheduled 조건을 봅니다. 셋째, 그 Pod UID에 해당하는 FailedScheduling 이벤트를 읽습니다. 이름이 같은 과거 Pod의 이벤트를 가져오면 교체 전 오류를 현재 원인으로 오해할 수 있습니다. Pending은 이미지 다운로드 등 다른 준비 과정도 포함하므로 그 한 단어만으로 CPU 부족이라고 결론 내리지 않습니다.
여기서 Insufficient cpu가 확인되면 선언한 요청과 노드 allocatable 및 기존 요청을 대조합니다. 요청이 진짜 필요한 크기라면 더 큰 노드, 작업 분할, 불필요한 예약의 정리 같은 선택지를 검토합니다. 오타라면 근거를 갖고 고칩니다. 운영 중인 다른 팀의 Pod를 지우거나 노드 상태를 고쳐 숫자만 맞추는 것은 진단이 아닙니다.
뒤의 실습에서 할 것
개인 k3s의 실제 allocatable보다 큰 CPU 요청을 선언하되, CPU를 태우는 부하 프로그램은 실행하지 않습니다. API에 저장된 Pod가 배치되지 않는 증거를 수집한 뒤, 그 UID의 시험 Pod만 회수하고 50m 요청의 작은 Pod가 기동하는지 비교합니다. 별도 네임스페이스의 정상 비교군은 끝까지 유지합니다. 이 실험은 CPU 포화·throttling·OOM을 직접 측정하는 실험과 다릅니다.
공식 근거
- [컨테이너 자원 관리](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/)
- [Kubernetes 스케줄러](https://kubernetes.io/docs/concepts/scheduling-eviction/kube-scheduler/)
- [자원 메트릭 파이프라인](https://kubernetes.io/docs/tasks/debug/debug-cluster/resource-metrics-pipeline/)