KCNA — 쿠버네티스·클라우드 네이티브 입문 · 배치 예산과 입장 정책을 실제 실패로 구분하기 · 실습
빈 CPU가 있어 보이는데 왜 입장할 수 없을까
목표
자원 요청에 따른 스케줄링 실패와 할당량에 따른 API 생성 거절을 실제 k3s에서 구별합니다.
왜 중요한가
현재 사용률이 낮아도 선언한 요청은 노드에 맞지 않을 수 있습니다. 입장이 허용돼도 실제 기동은 별도 단계입니다.
정책을 삭제하거나 남의 Pod를 회수해 통과시키지 않고, 기본값·합계·신원·실제 응답을 비교합니다.
실험은 개인 VM의 작은 대기 앱이며 CPU 포화·throttling·OOM 부하 실험이 아닙니다. 운영 kubeconfig나 실제 비밀을 가져오지 마세요.
50분 실습입니다. 필요하면 만료 전에 연장하고, 세션 종료 시 VM과 파일이 회수된다는 점을 기억하세요.
준비된 환경과 도우미
kcna-capacity는 실험 공간, kcna-capacity-control/control은 정상 비교군입니다. 두 공간 모두 restricted/v1.36 정책입니다.
앱은 digest 고정·Always pull·non-root·cap drop ALL·RuntimeDefault·읽기 전용 루트·ServiceAccount 토큰 미마운트입니다.
노드와 비교군을 변경하지 마세요. 학생의 모든 파일은 /root/kcna-resources 아래에 둡니다.
입력 파일은 학생이 작성하고, 관측 파일은 실제 API·Pod 상태를 읽은 capture가 만듭니다. 성공·UID·이벤트를 직접 꾸며 쓰지 마세요.
도우미는 python3 /opt/fixtures/kcna_resources_lab.py 뒤에 act·capture·grade·prepare와 단계 번호를 붙입니다.
observe는 현재 상태를 읽기만 합니다. grade도 학생 파일이나 Kubernetes 객체를 변경하지 않습니다.
act의 API 응답은 /opt/fixtures/kcna-resource-action-N.json에 보존합니다. 같은 요청을 반복해 과거의 403·201을 다시 만들지 않습니다.
단계
1. capture 1로 /root/kcna-resources/baseline.json을 저장하세요. Node의 실제 allocatable CPU·UID, 빈 kcna-capacity 네임스페이스와 kcna-capacity-control/control의 UID·컨테이너 ID·Ready·재시작 횟수를 조사합니다.
2. oversized-resources.json에 requests와 limits 객체를 작성하세요. 두 cpu 값은 실제 노드 allocatable보다 CPU 1 큰 값을 m 단위 문자열로 적고 memory는 각각 32Mi·64Mi입니다. act 2·capture 2로 unschedulable.json을 저장합니다. oversized Pod는 존재하지만 미배치 Pending이며, 해당 UID의 Unschedulable 조건·Insufficient cpu 이벤트가 있어야 합니다.
3. fit-resources.json에 requests={cpu:50m,memory:32Mi}, limits={cpu:200m,memory:64Mi}를 JSON으로 작성하세요. act 3은 조사한 oversized UID만 회수하고 작은 fit Pod를 만듭니다. capture 3으로 fitted.json을 저장하고 다른 Pod UID·정상 기동을 확인하세요.
4. defaults-policy.json에 type=Container, defaultRequest={cpu:100m,memory:32Mi}, default={cpu:200m,memory:64Mi}를 작성하세요. act 4·capture 4로 defaults.json을 저장합니다. 자원을 생략한 defaulted의 실제 요청 100m와 기존 fit의 50m 보존을 비교합니다.
5. quota.json에 requests.cpu=200m, requests.memory=128Mi, limits.cpu=1, limits.memory=256Mi, pods=4를 모두 문자열로 작성하세요. act 5는 team-budget을 만든 뒤 자원 생략 extra 생성을 요청합니다. capture 5로 quota_denied.json을 저장합니다. 사용량 150m에서 추가 100m가 실제 할당량 HTTP 403으로 거절되고 extra가 없어야 합니다.
6. increase.json에 requests.cpu=300m를 작성하세요. act 6·capture 6으로 quota_admitted.json을 저장합니다. 같은 extra 생성 요청의 실제 HTTP 201과 새 Pod UID·Ready, 사용량 250m를 확인합니다. 다른 할당량 축과 기존 Pod는 바꾸지 않습니다.
7. lower.json에 requests.cpu=100m를 작성하세요. act 7·capture 7로 quota_lowered.json을 저장합니다. 사용량 250m인 기존 Pod는 같은 UID·컨테이너로 유지되고, 새 10m small 요청은 실제 HTTP 403으로 거절돼야 합니다. 정책 축소를 기존 Pod의 자동 종료로 해석하지 마세요.
8. recover.json에 remove=extra, requests.cpu=200m, replacement={requests:{cpu:50m,memory:32Mi},limits:{cpu:200m,memory:64Mi}}를 작성하세요. act 8은 조사한 extra만 회수하고 사용량 감소 후 예산을 조정해 small을 만듭니다. capture 8로 budget_restored.json을 저장합니다. 실제 HTTP 201·Ready·최종 요청 합계 200m와 비교군 보존을 입증하세요.
참고
본문의 cpu:50m 같은 표기는 필드와 값을 설명한 것입니다. 저장하는 파일은 예시처럼 키와 문자열을 따옴표로 감싼 올바른 JSON이어야 합니다.
CPU 1은 1000m입니다. 2단계는 이 VM의 실제 allocatable을 먼저 읽어 계산하며 특정 VM의 값을 외우지 않습니다.
완료한 입력과 관측은 보존합니다. 진행 중 입력을 잘못 썼다면 오류 원인을 읽고 고치되, 저장한 과거 관측은 다시 쓰지 않습니다.
준비는 없는 이전 단계만 채웁니다. 현재 과제의 입력·관측을 만들거나 잘못 작성한 기존 입력을 덮지 않습니다.
채점은 60초, 단계 준비는 90초 제한입니다. 예산·사용량은 수렴을 확인하며 고정 sleep만으로 성공을 가정하지 않습니다.
중단 직후 객체가 생겼는데 신원 기록이 없는 경우 임의의 객체를 인수하지 않고 실패합니다. 자동 초기화로 학습 기록을 지우지 않습니다.
기록 해시는 실수 방지이며 root의 악의적 변경을 막는 원격 증명 장치가 아닙니다.
공식 근거: [자원 관리](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) ·
[기본값 정책](https://kubernetes.io/docs/concepts/policy/limit-range/) · [할당량](https://kubernetes.io/docs/concepts/policy/resource-quotas/).
단계 8개
- 배치 예산과 정상 비교군 조사
- 한가해 보여도 들어갈 수 없는 요청
- 맞는 크기의 요청으로 기동
- 생략한 자원에 기본값 적용
- Pod 생성 자체가 거절되는 할당량
- 입장 수락과 실제 실행을 구분
- 상한을 낮춰도 기존 Pod는 남는다
- 조사한 요청만 회수하고 예산 복구