LabHub
배우기 러닝패스 코스

CKA — 쿠버네티스 관리자 · Kustomize, 리소스 사용량, CoreDNS · 이론

Kustomize 오버레이와 리소스 사용량 파이프라인

LabHub 에서 이어서 보기

한 줄 요약

Kustomize 는 원본 YAML 을 고치지 않고 환경별 차이를 덧씌우는 도구이고, kubectl top 은 metrics-server 가 각 노드의 kubelet 에서 모아 Metrics API 로 내놓은 값을 읽어 오는 명령입니다. 둘 다 "이 결과가 어디에서 만들어지는가" 를 알아야 시험장에서도 현장에서도 막히지 않습니다.

왜 이게 필요했나

같은 애플리케이션을 개발·운영 환경에 배포하다 보면 YAML 을 복사해서 이름과 복제본 수만 바꾼 사본이 늘어납니다. 사본이 셋을 넘으면 어느 것이 원본인지 아무도 모르게 되고, 한쪽만 고친 변경이 다른 쪽에 조용히 빠집니다. Helm 은 이 문제를 템플릿 언어로 풀지만, 템플릿을 배우는 비용이 있습니다. Kustomize 는 템플릿 없이 원본은 그대로 두고 그 위에 패치를 얹는 방식을 택했고, [Kustomize 로 쿠버네티스 오브젝트를 선언적으로 관리하기](https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/) 문서에 따르면 kubectl 1.14 부터는 별도 설치 없이 kubectl apply -k 로 쓸 수 있습니다.

리소스 사용량 쪽의 문제는 다릅니다. 새로 만든 클러스터에서 kubectl top nodes 를 치면 "Metrics API not available" 이라는 답이 돌아옵니다. kubelet 은 자기 노드의 사용량만 알고 있고, 그것을 클러스터 전체로 모아 API 로 내어 주는 구성요소가 기본 설치에는 없기 때문입니다. [리소스 메트릭 파이프라인](https://kubernetes.io/docs/tasks/debug/debug-cluster/resource-metrics-pipeline/) 문서는 "Metrics API 에 접근하려면 metrics-server 또는 그것을 대신하는 어댑터를 반드시 배포해야 한다" 고 못 박습니다. 그러니 kubectl top 이 안 된다는 것은 명령이 고장 난 것이 아니라 파이프라인의 한 조각이 빠진 것입니다.

어떻게 동작하나

Kustomize — base 와 overlay

base 는 kustomization.yaml 과 리소스 파일이 들어 있는 디렉터리입니다. overlay 는 다른 kustomization 디렉터리를 resources 로 참조하는 디렉터리이고, 참조한 리소스 위에 자기 변경을 얹습니다. 문서가 강조하는 성질은 하나입니다 — base 는 overlay 의 존재를 모른다. 그래서 base 하나를 여러 overlay 가 함께 쓸 수 있습니다.

# base/kustomization.yamlresources:  - deployment.yaml  - service.yaml# overlays/dev/kustomization.yamlresources:  - ../../basenamePrefix: dev-patches:  - path: replicas.yaml

패치는 patches 필드에 적습니다. 문서에 따르면 Kustomize 는 StrategicMergeJson6902 두 가지 패치 방식을 지원하고, 패치는 파일이어도 되고 인라인 문자열이어도 되며, 적힌 순서대로 적용됩니다. 패치 대상은 group·version·kind·name·namespace·labelSelector·annotationSelector 로 고릅니다. 문서는 "한 가지 일만 하는 작은 패치" 를 권합니다 — 복제본 수를 올리는 패치와 메모리 제한을 거는 패치를 따로 두라는 뜻입니다. StrategicMerge 패치는 원본과 같은 모양의 YAML 조각을 겹쳐 쓰는 방식이라 읽기 쉽고, Json6902 패치는 경로를 지정해 add·replace·remove 를 하는 방식이라 목록 안의 특정 항목처럼 겹쳐 쓰기로는 표현하기 어려운 곳에 씁니다.

패치 말고도 자주 쓰는 필드가 있습니다. images 는 패치 없이 이미지 이름·태그·다이제스트만 바꾸고, namePrefix·nameSuffix 는 모든 리소스 이름 앞뒤에 문자열을 붙이며, configMapGenerator·secretGenerator 는 파일이나 리터럴에서 ConfigMap·Secret 을 만들어 냅니다. 생성기가 만든 오브젝트에는 내용 해시가 이름 뒤에 붙습니다. 내용이 바뀌면 이름이 바뀌고, 그것을 참조하는 Deployment 의 스펙도 바뀌므로 롤아웃이 저절로 일어납니다. 이 동작을 끄려면 generatorOptionsdisableNameSuffixHash 를 씁니다.

적용 전에 결과를 보려면 kubectl kustomize <디렉터리> 로 렌더링된 YAML 을 출력해 보고, 확인이 끝나면 kubectl apply -k <디렉터리> 로 적용합니다. kubectl diff -k·kubectl delete -k 도 같은 방식입니다. -k 는 파일이 아니라 kustomization.yaml 이 있는 디렉터리를 가리켜야 합니다.

리소스 사용량 — 메트릭이 지나는 길

[리소스 메트릭 파이프라인](https://kubernetes.io/docs/tasks/debug/debug-cluster/resource-metrics-pipeline/) 문서가 그린 흐름은 이렇습니다.

| 단계 | 구성요소 | 하는 일 |
| --- | --- | --- |
| 1 | cAdvisor | kubelet 에 포함된 데몬. 컨테이너 메트릭을 수집·집계·노출 |
| 2 | kubelet | /metrics/resource/stats 엔드포인트로 노드 단위 요약 제공 |
| 3 | metrics-server | 각 kubelet 에서 메트릭을 끌어와 집계하는 클러스터 애드온 |
| 4 | Metrics API | metrics.k8s.io 그룹. API 서버가 확장 API 로 서비스 |
| 5 | 소비자 | HPA·VPA, 그리고 kubectl top |

metrics-server 는 Metrics API 의 참조 구현입니다. API 서버에 붙으려면 aggregation layer 가 켜져 있어야 하고 metrics.k8s.io 에 대한 APIService 가 등록되어야 합니다. [metrics-server 저장소](https://github.com/kubernetes-sigs/metrics-server) 는 요구사항을 더 적어 둡니다 — 노드의 kubelet 에 Webhook 인증·인가가 켜져 있을 것, kubelet 인증서가 클러스터 CA 로 서명되어 있을 것(아니면 --kubelet-insecure-tls 로 검증을 끌 것), 컨트롤 플레인이 metrics-server 파드에 닿을 것, metrics-server 가 모든 노드의 kubelet 포트에 닿을 것. 수집 주기는 15초이고, metrics-server v0.6.0 이상은 kubelet 의 /metrics/resource 를 읽습니다.

값의 뜻도 알아 두어야 합니다. CPU 는 커널이 제공하는 누적 카운터의 변화율로 계산한 평균 코어 사용량이고, 계산 구간은 Metrics API 응답의 window 필드에 나옵니다. 메모리는 수집 시점의 working set 으로, 메모리 압박 아래에서도 해제할 수 없는 사용 중인 메모리입니다. 그래서 kubectl top pod 의 메모리 값은 RSS 와도 다르고 캐시를 전부 포함한 값과도 다릅니다.

저장소 문서에는 주의 문구가 하나 있습니다. metrics-server 는 오토스케일링 전용이며, 모니터링 시스템의 데이터 원천으로 쓰지 말라는 것입니다. 정확한 사용량 기록이 필요하면 Prometheus 같은 모니터링 도구가 kubelet 의 /metrics/resource 를 직접 긁게 하라고 안내합니다.

현장에서 만나는 모습

오버레이를 적용했는데 오브젝트가 안 보인다. overlay 에 namePrefix: dev- 를 두면 생성되는 Deployment 이름은 my-nginx 가 아니라 dev-my-nginx 입니다. kubectl get deploy my-nginx 로 찾으면 없다고 나옵니다. 문서의 예시 출력도 deployment.apps/dev-my-nginx created 입니다. 적용 전에 kubectl kustomize 로 렌더링 결과를 한 번 보는 습관이 이 혼란을 없앱니다.

metrics-server 를 배포했는데 kubectl top 이 계속 실패한다. kubeadm 으로 만든 클러스터에서 자주 봅니다. [kubeadm 인증서 관리](https://kubernetes.io/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/) 문서에 따르면 kubeadm 이 배포하는 kubelet serving 인증서는 기본이 자체 서명이라, metrics-server 같은 외부 서비스가 kubelet 에 TLS 로 붙을 때 검증에 실패합니다. 실습용 클러스터에서는 --kubelet-insecure-tls 로 넘기고, 운영 클러스터에서는 같은 문서의 "서명된 kubelet serving 인증서 켜기" 절차를 따라 클러스터 CA 가 서명한 인증서를 받게 합니다.

다음 이론에서 볼 것

다음 읽기에서는 이름 해석을 다룹니다. 파드가 my-svc 라고 부르면 어느 서버가 어떤 순서로 답하는지, CoreDNS 의 Corefile 은 어떤 구조인지, 그리고 해석이 막혔을 때 어디부터 보는지를 공식 디버깅 절차를 따라 익힙니다.