CRD 와 오퍼레이터 · 레플리카를 늘렸는데 아무 일도 없었다 · 실습
레플리카를 늘렸는데 아무 일도 없었다 — scale 하위 리소스의 계약
목표
CRD 의 subresources.scale 을 세 경로로 제대로 맺고, 셀렉터 경로를 빠뜨렸을 때와 경로에 오타가 있을 때 각각 어떤 침묵이 생기는지 직접 만들어 본 뒤, 그 침묵을 잡아내는 점검 스크립트를 만든다.
왜 중요한가
kubectl scale 과 HPA 는 대상의 종류를 모른다. 이 둘이 아는 것은 오직 scale 하위 리소스라는 공통 창 하나뿐이고, CRD 는 그 창을 세 개의 JSONPath 로 열어 준다. 그래서 오퍼레이터를 만드는 사람이 이 세 줄을 제대로 쓰면 자기 타입이 쿠버네티스의 기존 자동 확장 도구 전부와 공짜로 이어지고, 잘못 쓰면 그 도구들이 오류 없이 아무 일도 하지 않는다. 이 침묵이 이 모듈의 주제다. 경로에 오타가 있으면 kubectl scale 은 성공했다고 답하면서 값을 바꾸지 않고, 셀렉터 경로가 없으면 HPA 는 대상을 읽는 데 성공한 채로 영원히 조정하지 않는다. 둘 다 사람이 화면을 들여다보기 전에는 드러나지 않으므로, 배포 파이프라인에 넣을 수 있는 점검 방법을 함께 갖춰야 한다.
단계
1. /root/op-scale/shard-crd.yaml 에 CRD shards.scale.labhub.io 를 쓰세요 — 그룹 scale.labhub.io, 종류 Shard, 복수형 shards, 버전 v1 하나(served·storage 모두 참), spec.replicas(integer)·status.replicas(integer)·status.selector(string) 를 스키마에 두고, subresources 에 status: {} 와 scale 을 켭니다. scale 의 세 경로는 각각 .spec.replicas·.status.replicas·.status.selector 입니다. 적용한 뒤 클러스터에 등록된 세 경로를 /root/op-scale/scale-paths.txt 에 <이름>=<값> 세 줄로 저장하세요(specReplicasPath=..., statusReplicasPath=..., labelSelectorPath=...).
2. 네임스페이스 op-scale 를 만들고 /root/op-scale/shard-a.yaml 에 Shard a 를 쓰세요 — spec.replicas 는 2 입니다. 적용한 뒤 kubectl -n op-scale get shard a --subresource=scale -o yaml 의 출력을 그대로 /root/op-scale/scale-initial.yaml 에 저장하세요.
3. kubectl -n op-scale scale shard a --replicas=5 로 Shard a 의 원하는 수를 5 로 올리세요. 그다음 scale 하위 리소스에서 두 숫자를 꺼내 /root/op-scale/after-scale.txt 에 spec.replicas=5 와 status.replicas=0 두 줄로 저장하세요.
4. 컨트롤러가 할 일을 대신해 status 를 쓰세요 — kubectl -n op-scale patch shard a --subresource=status 로 status.replicas 를 5 로, status.selector 를 app=shard-a 로 채웁니다. 그다음 scale 하위 리소스 출력을 /root/op-scale/scale-ready.yaml 에 저장하세요.
5. /root/op-scale/shard-hpa.yaml 에 autoscaling/v2 HPA shard-a-hpa 를 쓰세요 — scaleTargetRef 는 apiVersion scale.labhub.io/v1, kind Shard, name a 이고 minReplicas 2, maxReplicas 10, 지표는 Resource cpu 의 Utilization 70 입니다. 적용하고 조건이 채워질 때까지 기다린 뒤 /root/op-scale/hpa-status.txt 에 두 줄로 저장하세요 — AbleToScale=<상태>/<이유> 와 REFERENCE=<kubectl get hpa 의 REFERENCE 칸>.
6. /root/op-scale/block-crd.yaml 에 CRD blocks.scale.labhub.io(종류 Block, 복수형 blocks)를 쓰되 scale 에 labelSelectorPath 를 넣지 않습니다. /root/op-scale/block-b.yaml 로 Block b(spec.replicas 3)를, /root/op-scale/block-hpa.yaml 로 HPA block-b-hpa(minReplicas 1, maxReplicas 6, cpu 70)를 만들어 적용하고, 조건이 채워지면 /root/op-scale/noselector.txt 에 ScalingActive=<상태>/<이유> 와 MESSAGE=<조건 메시지> 두 줄로 저장하세요.
7. /root/op-scale/relay-crd.yaml 에 CRD relays.scale.labhub.io(종류 Relay, 복수형 relays)를 쓰되 specReplicasPath 를 일부러 .spec.replica(끝의 s 를 뺀 오타)로 적습니다. /root/op-scale/relay-r.yaml 로 Relay r(spec.replicas 2)을 만들어 적용하고, kubectl -n op-scale scale relay r --replicas=4 와 kubectl -n op-scale get relay r --subresource=scale -o yaml 을 차례로 실행해 그 결과를 /root/op-scale/typo-report.txt 에 모으세요 — scale-rc=<종료 코드>, spec.replicas=<명령 뒤 실제 값>, 그리고 두 번째 명령의 오류 문장을 그대로 담은 줄이 있어야 합니다.
8. /root/op-scale/scale-audit.tsv 에 <CRD 이름><탭><기대 분류> 세 줄을 적으세요 — shards.scale.labhub.io 는 ok, blocks.scale.labhub.io 는 nosel, relays.scale.labhub.io 는 ok 입니다. /root/op-scale/scale-audit.sh 는 이 표를 읽어 CRD 를 ok·nosel·broken 으로 분류하고 맞으면 OK …, 틀리면 MISMATCH … 를 표준출력에만 찍으며 한 줄이라도 틀리면 0 이 아닌 코드로 끝나야 합니다. 먼저 고치기 전에 한 번 돌려 /root/op-scale/scale-audit-before.txt 에 남기고, 그다음 /root/op-scale/relay-crd-fixed.yaml 로 오타를 고쳐 적용한 뒤 kubectl -n op-scale scale relay r --replicas=4 가 이번에는 실제로 값을 바꾸는지 확인하고, 다시 돌린 출력을 /root/op-scale/scale-audit.txt 에 저장하세요.
참고
- 세 경로는
specReplicasPath·statusReplicasPath·labelSelectorPath이고 값은 점으로 시작합니다. - status 를 쓰려면
kubectl patch … --subresource=status가 필요합니다. - HPA 의 판정은
status.conditions의AbleToScale·ScalingActive두 조건에 남습니다. - 이 환경에는 지표 서버가 없어 HPA 의 TARGETS 는 계속 알 수 없음으로 남습니다 — 정상입니다.
- 흔한 실수: 셀렉터 경로를 빠뜨리고 HPA 가 붙었다고 안심한다.
- 흔한 실수:
kubectl scale의 종료 코드만 보고 값이 바뀌었다고 믿는다. - 참고: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/
- 참고: https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
단계 8개
- 세 경로로 계약을 맺는다
- scale 하위 리소스는 무엇으로 보이나
- kubectl scale 이 무엇을 바꾸는가
- 컨트롤러 자리를 손으로 채운다
- HPA 를 커스텀 리소스에 건다
- 셀렉터 경로를 빼면 HPA 가 조용히 멈춘다
- 성공했다고 답하면서 아무것도 안 한다
- 조용한 고장을 잡아내는 점검표를 만든다