실전 과제 — 워크로드와 스케줄링
- HPA의 축소 안정화 창은 명령 옵션이 없다.
kubectl autoscale로 뼈대를 뽑고behavior를 YAML에 직접 넣는다. - 로그 사이드카는 두 컨테이너가 같은 볼륨을 같은 경로에 마운트해야 파일을 본다.
- 새 PriorityClass 값은
system-으로 시작하지 않는 클래스의 최댓값을 기준으로 정한다. - Pod별 requests는 노드 Allocatable에서 다른 Pod의 requests와 여유분을 뺀 뒤 나눈다.
개념 페이지가 “무엇이 일어나는가”를 설명한다면, 이 페이지는 지문을 받았을 때 무엇부터 치는가를 연습한다. 과제는 연습용으로 만든 시나리오이고 이름과 값은 예시다. 과제마다 조건 → 풀이 → 확인 → 함정 순서로 읽고, 원리는 링크한 개념 페이지에서 확인한다. 호스트 접속과 네임스페이스 확인은 문제마다 반복하는 3단계를 따른다.
준비 명령은 연습 클러스터에 같은 상황을 만들 때만 쓴다. 끝나면 만든 네임스페이스를 지우면 된다.
HPA에 축소 안정화 창 지정하기
섹션 제목: “HPA에 축소 안정화 창 지정하기”과제
- 네임스페이스
scale-lab의 Deploymentweb-api를 대상으로 같은 이름의 HPA를 만든다. - Pod당 평균 CPU 사용률 60%를 목표로 하고, Pod 수는 최소 2개·최대 6개다.
- 축소 안정화 창을 60초로 둔다.
준비
kubectl create namespace scale-labkubectl create deployment web-api -n scale-lab --image=nginx:1.28kubectl set resources deployment web-api -n scale-lab --requests=cpu=100m풀이
-
뼈대를 명령으로 뽑는다. 대상·최소·최대·목표 사용률은 옵션으로 채워진다.
터미널 창 kubectl autoscale deployment web-api -n scale-lab \--min=2 --max=6 --cpu=60% --dry-run=client -o yaml > hpa.yaml -
behavior를spec아래에 더한다. 안정화 창은 명령 옵션이 없다.spec:behavior:scaleDown:stabilizationWindowSeconds: 60 -
적용하고 값이 들어갔는지 본다.
터미널 창 kubectl apply -f hpa.yamlkubectl get hpa web-api -n scale-labkubectl get hpa web-api -n scale-lab \-o jsonpath='{.spec.behavior.scaleDown.stabilizationWindowSeconds}{"\n"}'# 60
안정화 창의 뜻과 기본값은 behavior — 확장·축소 속도 제어에 있다.
기존 Deployment에 로그 사이드카 추가하기
섹션 제목: “기존 Deployment에 로그 사이드카 추가하기”과제
- 네임스페이스
reports의 Deploymentreport-writer는/var/log/report.log에 로그를 쓴다. - 같은 Pod에
busybox:stable이미지의 컨테이너log-tail을 추가한다. log-tail은/bin/sh -c "tail -n+1 -f /var/log/report.log"를 실행한다.- 두 컨테이너가
/var/log에 마운트한 볼륨으로 로그 파일을 공유한다.
준비
kubectl create namespace reportskubectl create deployment report-writer -n reports --image=busybox:stable \ -- /bin/sh -c 'while true; do date >> /var/log/report.log; sleep 5; done'풀이
-
Pod 템플릿을 연다.
터미널 창 kubectl edit deployment report-writer -n reports -
세 곳을 고친다. 볼륨 정의, 기존 컨테이너의 마운트, 새 컨테이너다. 아래는 고친 부분만 보인 발췌다.
spec:template:spec:containers:- name: busybox # 기존 컨테이너volumeMounts: # 추가- name: logsmountPath: /var/log- name: log-tail # 추가image: busybox:stablecommand: ["/bin/sh", "-c", "tail -n+1 -f /var/log/report.log"]volumeMounts:- name: logsmountPath: /var/logvolumes: # 추가- name: logsemptyDir: {} -
새 Pod이 뜨고 사이드카가 로그를 읽는지 본다.
터미널 창 kubectl rollout status deployment report-writer -n reportskubectl get pods -n reports # 새 Pod이 READY 2/2kubectl logs <새-Pod-이름> -n reports -c log-tail --tail=3
볼륨이 Pod 안에서 공유되는 방식은 emptyDir에서 다룬다.
기존 값에 맞춰 PriorityClass 만들기
섹션 제목: “기존 값에 맞춰 PriorityClass 만들기”과제
- 사용자 워크로드용 PriorityClass
batch-high를 만든다. 값은 기존 사용자 정의 클래스의 최댓값보다 1 작게 한다. - 네임스페이스
tiered의 Deploymentlog-shipper가 이 클래스를 쓰게 하고, 롤아웃이 끝났는지 확인한다.
준비
kubectl create priorityclass team-low --value=1000kubectl create priorityclass team-top --value=500000kubectl create namespace tieredkubectl create deployment log-shipper -n tiered --image=busybox:stable -- sleep 3600풀이
-
기존 클래스를 값 순서로 본다.
system-으로 시작하는 두 개는 내장 클래스라 기준에서 뺀다.터미널 창 kubectl get priorityclass --sort-by=.value# NAME VALUE GLOBAL-DEFAULT AGE PREEMPTIONPOLICY# team-low 1000 false 1m PreemptLowerPriority# team-top 500000 false 1m PreemptLowerPriority# system-cluster-critical 2000000000 false 9d PreemptLowerPriority# system-node-critical 2000001000 false 9d PreemptLowerPriority -
최댓값에서 1을 뺀 값으로 만든다.
터미널 창 kubectl create priorityclass batch-high --value=499999 \--description="user workloads" -
Deployment의 Pod 템플릿에 클래스 이름을 넣는다.
터미널 창 kubectl patch deployment log-shipper -n tiered \-p '{"spec":{"template":{"spec":{"priorityClassName":"batch-high"}}}}' -
롤아웃과 실제 우선순위를 확인한다.
터미널 창 kubectl rollout status deployment log-shipper -n tieredkubectl get pods -n tiered \-o custom-columns='NAME:.metadata.name,CLASS:.spec.priorityClassName,PRIORITY:.spec.priority'
선점이 일어나는 순서는 PriorityClass와 선점에서 본다.
노드 자원을 Pod에 고르게 나누기
섹션 제목: “노드 자원을 Pod에 고르게 나누기”과제
- 네임스페이스
blog의 Deploymentblog는 replicas가 3인데 일부 Pod이Pending이다. - Pod마다 init 컨테이너 하나와 앱 컨테이너 하나가 있고, 워커 노드는 하나다.
- 세 Pod이 노드 자원을 고르게 나눠 쓰도록 requests를 고친다. 노드가 안정적으로 돌 여유를 남긴다.
- init 컨테이너와 앱 컨테이너의 requests는 같은 값으로 한다.
- 고치는 동안에는 replicas를 0으로 두고, 끝나면 3개가 모두 Running·Ready여야 한다.
이 과제는 노드 크기에 따라 값이 달라져 준비 명령을 두지 않는다. 연습할 때는 requests를 노드 Allocatable의 절반쯤으로 준 replicas 3짜리 Deployment를 만들면 같은 상황이 된다.
풀이
-
왜 Pending인지 확인한다.
Insufficient cpu나Insufficient memory가 보이면 requests 문제다.터미널 창 kubectl get pods -n blog -o widekubectl describe pod <Pending인-Pod> -n blog | grep -A5 Events -
replicas를 0으로 줄인다. 이 Deployment의 requests가 노드 집계에서 빠진다.
터미널 창 kubectl scale deployment blog -n blog --replicas=0 -
노드에서 나눌 수 있는 양을 읽는다.
터미널 창 kubectl get node <워커노드> \-o jsonpath='{.status.allocatable.cpu}{" "}{.status.allocatable.memory}{"\n"}'kubectl describe node <워커노드> | grep -A8 'Allocated resources' -
Pod 하나의 몫을 계산한다. 아래는 예시 수치다.
CPU 메모리 Allocatable 2000m 3800Mi 다른 Pod의 requests 합 350m 300Mi 나눌 수 있는 양 1650m 3500Mi 여유 15%를 남기고 3으로 나눈 값 467m 991Mi 내림해서 쓸 값 450m 950Mi -
init 컨테이너와 앱 컨테이너에 같은 값을 넣는다.
kubectl set resources는 컨테이너를 지정하지 않으면 init 컨테이너까지 전부 바꾼다. 두 쪽에 들어갔는지 바로 확인한다.터미널 창 kubectl set resources deployment blog -n blog --requests=cpu=450m,memory=950Mikubectl get deployment blog -n blog -o jsonpath='{.spec.template.spec.initContainers[*].resources.requests}{"\n"}{.spec.template.spec.containers[*].resources.requests}{"\n"}' -
다시 3개로 늘리고 확인한다.
터미널 창 kubectl scale deployment blog -n blog --replicas=3kubectl rollout status deployment blog -n blogkubectl get pods -n blog # 3개 모두 Running, READY 1/1
계산의 근거는 노드 용량에서 requests 정하기에 있다.