[Kubernetes] HPA, kubeadm, Helm, Kustomize
지금까지는 k create deployment web --replicas=3 명령어로 replicas 개수를 직접 설정해줬다.
트래픽이 변하니 수동으로 조작하지 말고 부하를 보고 Pod 동적으로 조절하는게 필요함. 이 때 HPA를 사용한다. (Horizontal Pod Autoscaler)
AWS Auto Scaling Group이 EC2 인스턴스 수를 조절하듯 쿠버의 HPA는 Pod 수를 조절한다.
설정 방식도 똑같다. CPU 점유율 기준, min/max 인스턴스 기준
HPA가 제대로 동작하려면 CPU 사용률을 측정할 수 있어야 함. 이 때는 metrics-server를 사용한다.
metrics-server가 없으면 HPA가 CPU를 확인하지 못해서 제대로 작동하지 않는다.
Ingress가 Controller를 필요로 하듯.. HPA는 metrics-server를 필요로 함.
k autoscale deployment web --min=2 --max=10 --cpu-percent=50 -n ts
YAML로 설정할 수 있지만 명령어를 사용하는게 편하다.
다만 대상 Deployment에 resources.requests가 설정되어 있어야 작동할 수 있음.
웹서버처럼 계속 실행되지 않고 한 번 돌고 끝나야 하는 작업을 다룰 때는 Job을 사용한다.
Deployment는 계속 도는 작업을 수행하고 죽으면 재시작하지만 Job은 완료되면 Completed 상태로 변함.
13months@13monthsBook k8s % k create job my-job --image=busybox \
> -n ts -- echo "hello job"
job.batch/my-job created
13months@13monthsBook k8s % k get job -n ts
NAME STATUS COMPLETIONS DURATION AGE
my-job Running 0/1 5s 5s
13months@13monthsBook k8s % k get pod -n ts
NAME READY STATUS RESTARTS AGE
my-job-f5jc8 0/1 Completed 0 9s
Deployment와 Job은 모두 Pod를 만들고 관리하는 컨트롤러로 같은 추상화 수준을 제공한다.
다만 Deployment는 ReplicaSet을 통해 Pod를 다루지만 Job은 바로 Pod을 관리함.
Deployment와 Job 말고도 StatefulSet DaemonSet CronJob 등등 Pod을 관리하는 컨트롤러는 여러 가지 있음.
CronJob은 Job을 관리하고 Job은 Pod를 관리함.
kubeadm은 쿠버네티스 클러스터를 만드는 공식 도구임.
지금까지는 minikube로 클러스터를 만들었는데 이거는 공부용이고 실제 운영 클러스터는 kubeadm으로 만든다.
비어있는 리눅스 서버들을 쿠버네티스 클러스터로 묶어줌.
api-server, etcd, scheduler, controller-manager이 static Pod으로 뜨는데 이걸 만들어주는게 kubeadm이다.
얘가 인증서를 만들고 static Pod manifest를 설치하고 클러스터를 부팅함.
kubeadm init --pod-network-cidr=10.244.0.0/16
kubeadm join 192.168.1.10:6443 --token abc... --discovery-token-ca-cert-hash sha256:…
init으로 인증서 생성, pod manifest 생성, etcd 시작, kubeconfig 생성을 모두 처리한다.
init이 알려준 명령을 워커에서 실행하면 클러스터에 합류한다.
init -> join 이후 CNI를 따로 설치해야 노드가 Ready 상태가 된다.
# 1. kubeadm 자체를 먼저 업그레이드
apt-mark unhold kubeadm
apt-get update && apt-get install -y kubeadm=1.32.0-*
apt-mark hold kubeadm
# 2. 업그레이드 계획 확인
kubeadm upgrade plan
# 3. 클러스터 컴포넌트 업그레이드 (control plane은 apply!)
kubeadm upgrade apply v1.32.0
# 4. 노드 비우기
kubectl drain <노드이름> --ignore-daemonsets
# 5. kubelet, kubectl 업그레이드
apt-mark unhold kubelet kubectl
apt-get install -y kubelet=1.32.0-* kubectl=1.32.0-*
apt-mark hold kubelet kubectl
# 6. kubelet 재시작
systemctl daemon-reload
systemctl restart kubelet
# 7. 노드 복구
kubectl uncordon <노드이름>
클러스터 버전을 업그레이드 할 때도 kubeadm을 사용함.
Control Plane을 가장 먼저 다루고 Worker Node를 제일 마지막에 다룬다.
한 번 업데이트에서는 마이너 버전 하나씩 올려야 함.
노드에는 두 개의 층이 있다.
1. 리눅스 머신에 apt-get으로 설치된 프로그램 (kubeadm, kubelet, kubectl)
2. 클러스터에서 작동하는 것들 (api-server, etcd, scheduler)
업그레이드는 두 층을 모두 올려야 하고, 그러니 명령어가 두 종류로 나뉜다.
kubeadm upgrade apply v1.32.0 으로 static Pod YAML을 새 버전으로 모두 작성하면 kubelet이 감지해서 알아서 Pod를 재시작.
kubelet을 재시작하면 그 노드의 Pod이 불안정해지니 drain으로 미리 Pod을 다른 노드로 피신시킨다.
워커의 kubelet 버전은 api-server보다 낮아도 되지만 높으면 안된다.
그러니 api-server를 먼저 올려야 워커를 올려도 워커가 더 높아지는 상황이 발생하지 않음. 그래서 Control Plane을 먼저 올린다.
Control Plane을 업그레이드 할 때는 apply와 버전을 명시하는데, 노드는 이미 정해진 버전을 따라가는 쪽이라 버전이 필요하지 않다.
앱 하나를 배포하려고 YAML을 너무 많이 만든다.
실제 앱은 이것보다 훨씬 더 복잡하다. Prometheus 하나 설치하려면 Deployment와 Service 여러 개와 수많은 ConfigMap을 작성해야 하니 YAML도 수십개 작성하게 된다.
매번 이걸 하고 있을수는 없으니 Helm을 사용해 쿠버네티스 앱을 패키지화한다.
apt로 프로그램을 설치하는 것 처럼 Helm으로 쿠버 앱을 설치한다. 이제 YAML 하나하나 만들지 않아도 됨.
핵심 개념 몇 가지를 정리하자.
1. Chart
패키지로 쿠버 앱 하나를 배포하는데 필요한 YAML 템플릿을 묶는다.
npm의 패키지 gradle.build 같은 것으로 Deployment Service ConfigMap 템플릿이 들어있다.
2. Release
Chart를 클러스터에 설치하면 Release된다.
같은 Chart로 여러 Release를 구축할 수 있다. 도커 이미지 느낌
3. Values
Chart는 템플릿이라 빈칸이 있다. 이 빈칸을 채우는게 values.
Chart는 같지만 values를 다르게 설정해서 다른 환경을 구축한다.
스프링부트로 치면 yml으로 환경별로 설정 바꾸는것과 유사함.
Helm은 설치한 내용을 버전으로 기록하니 업그레이드 후 문제 발생 시 이전 버전으로 되돌릴 수 있다.
git revert처럼 되돌리는 커밋을 쌓는 느낌임.
YAML 하나도 안 쓰고 앱을 띄울 수 있긴 한데 내가 안 쓸 뿐이지 누군가는 YAML을 다 썼다.
나만의 앱을 Helm으로 다루고 싶다면 Chart를 직접 만들어야 한다.
Deployment 템플릿 Service 템플릿 PVC 템플릿 등등 모두 만든 후에는 Helm으로 날먹 가능.
그러니 Prometheus, Redis, Nginx처럼 유명한거 설치할 때는 Helm으로 편하게 설치하고 내가 만든거 배포할 때는 YAML 직접 쳐야함.
helm create로 내꺼 만들거나 남이 만든 Chart 받고 수정하는 식으로 작성해도 되지만 템플릿이 너무 복잡하니 스스로 하는게 낫다.
blog 앱을 개발/운영 두 환경에 배포할 때 진짜 거의 비슷한데 몇 군데만 다르다. namespace랑 이미지 정도..
이러면 YAML을 복사해서 두 군데 만드는 방법이 있는데 너무 귀찮고, Helm 템플릿을 쓰는 방법도 있는데 Helm 문법을 또 배워야 함.
이 때 Kustomize를 사용한다. YAML은 그대로 두고 차이점만 따로 적어서 적용하는 방식임.
Kustomize의 기본은 순수 YAML이고 overlay로 환경별 차이점만 추가한다.
base/ ← 공통 (순수 YAML)
deployment.yaml
service.yaml
kustomization.yaml
overlays/
dev/ ← 개발용 차이점만
kustomization.yaml (replicas 1로)
prod/ ← 운영용 차이점만
kustomization.yaml (replicas 5로)
1. base/kustomization.yaml
resources:
- deployment.yaml
- service.yaml
2. overlays/prod/kustomization.yaml
resources:
- ../../base # base를 가져와서
namespace: prod # namespace를 prod로 바꿔라
replicas:
- name: blog-app
count: 5 # replicas를 5로 바꿔라
images:
- name: nginx
newTag: 1.29 # 이미지 태그를 1.29로 바꿔라
Kustomize는 kubectl에 내장되어있으니 설치할 필요도 없다.
YAML이 순수하게 유지되니 그냥 apply -f 로 사용할 수 있음.
base의 deployment.yaml은 손도 안댄다.
namespace: prod # 모든 리소스의 namespace 변경
namePrefix: prod- # 이름 앞에 붙이기 (prod-blog-app)
nameSuffix: -v2 # 이름 뒤에 붙이기
commonLabels: # 모든 리소스에 라벨 추가
env: production
replicas: # replicas 변경
- name: blog-app
count: 5
images: # 이미지 변경
- name: nginx
newTag: 1.29
kustomization.yaml 에서는 보통 저런걸 많이함. 복잡한 patch 보다는..
kubectl kustomize overlays/prod
kubectl apply -k <디렉토리>
kustomization.yaml이 있는 디렉토리를 적용한다. -k 옵션에 주의.
kustomize는 최종 YAML이 어떻게 나오는지 보기만 한다.
'DevOps > Docker && Kubernetes' 카테고리의 다른 글
| [Kubernetes] Certified Kubernetes Administrator 연습 (2) (0) | 2026.08.04 |
|---|---|
| [Kubernetes] CRD, Controller (0) | 2026.07.28 |
| [Kubernetes] NetworkPolicy, Ingress (0) | 2026.07.28 |
| [Kubernetes] Probe, Resource Limits (0) | 2026.07.27 |
| [Kubernetes] Certified Kubernetes Administrator 연습 (1) (0) | 2026.07.27 |
댓글
이 글 공유하기
다른 글
-
[Kubernetes] Certified Kubernetes Administrator 연습 (2)
[Kubernetes] Certified Kubernetes Administrator 연습 (2)
2026.08.04 -
[Kubernetes] CRD, Controller
[Kubernetes] CRD, Controller
2026.07.28 -
[Kubernetes] NetworkPolicy, Ingress
[Kubernetes] NetworkPolicy, Ingress
2026.07.28 -
[Kubernetes] Probe, Resource Limits
[Kubernetes] Probe, Resource Limits
2026.07.27