본문 바로가기

카테고리 없음

K8s manifest management tool

manifest는 K8s 리소스를 정의하는 파일입니다.

선언형 커맨드(e.g. kubectl apply)로 K8s 리소스를 생성할 때 작성했던 명세죠.

대개 yaml 예시를 보게 되지만 json 포맷도 가능합니다.

controlplane에 있는 api에 리소스 생성을 요청할 때 이 내용이 들어갑니다.

 

환경별로 설정을 약간씩 다르게 주거나 여러 사람이 인프라에 손을 대면 곧 재사용 욕구와 탬플릿 및 버전 관리의 필요성을 느끼게 됩니다.

이 필요성을 이런저런 이유로 덮어두고 살다간 오타부터 한쪽만 바꾼 설정값 등 다양한 원인을 가진 문제가 발생합니다.

api 개발시 어딘가에 노출되는 부분만 약간 다르게 반환해달라 하는 요청을 받았을 때 있던 함수를 복사해놓고 살짝 바꿔 쓰다간 나중에 피를 보게 되는 것처럼요.

그래서 인프라 관리 편의와 안정성을 위해 manifest 관리 도구를 사용합니다.

 

Helm

Helm은 가장 많이 사용되는 manifest 관리 도구입니다.

create 명령어로 helm의 기본 구조를 갖춘 디렉토리를 생성할 수 있습니다.

$ helm create mychart
Creating mychart

$ tree .
.
└── mychart
    ├── Chart.yaml
    ├── charts
    ├── templates
    │   ├── _helpers.tpl
    │   ├── deployment.yaml
    │   ├── hpa.yaml
    │   ├── ingress.yaml
    │   ├── NOTES.txt
    │   ├── service.yaml
    │   ├── serviceaccount.yaml
    │   └── tests
    │       └── test-connection.yaml
    └── values.yaml

5 directories, 10 files

만들어진 helm chart 한 덩이는 하나의 패키지 같은 형태를 띠고 있습니다. (공식 문서에서도 그냥 chart = helm package 라고 부름)

- charts : 이 chart가 의존하는 chart들

- templates : 재사용될 K8s 리소스 별 yaml 파일이 들어있는 디렉토리

 

이렇게 직접 로컬에 만든 chart 뿐만 아니라 커뮤니티에 공유된 chart를 검색하고 이 chart들을 사용할 수도 있습니다.

$ helm search hub nginx
URL                                               	CHART VERSION	APP VERSION                                     	DESCRIPTION
https://artifacthub.io/packages/helm/ashu-nginx...	0.1.0        	1.16.0                                          	A Helm chart for Kubernetes
https://artifacthub.io/packages/helm/krakazyabr...	1.0.0        	1.19.0                                          	Nginx Helm chart for Kubernetes
https://artifacthub.io/packages/helm/zrepo-test...	5.1.5        	1.16.1                                          	Chart for the nginx server
https://artifacthub.io/packages/helm/wiremind/n...	2.1.1        	                                                	An NGINX HTTP server
(이하 생략)

위와 같이 찾아볼 수 있는 공개 repository도 존재하고, harbor와 같은 private repo도 있습니다.

이런 chart는 app을 구동하는데 필요한 K8s 리소스 정의를 담고 있습니다.

 

패키지를 설치하는 명령어로 로컬에 만들어둔 chart를 실행시킬 수 있습니다.

helm install {생성하고자 하는 release명} {Chart.yaml 파일이 존재하는 경로}

$ cd mychart
$ helm install myapp .
NAME: myapp
LAST DEPLOYED: Sun May 18 17:04:01 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=myapp" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  echo "Visit http://127.0.0.1:8080 to use your application"
  kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

NOTES: 아래의 내용은 templates/NOTES.txt에 있는 내용입니다. (README 역할)

 

chart를 install하면 새 release object가 생성됩니다.

release는 하나의 namespace에 종속이 되기 때문에 여러 namespace에 걸친 리소스들을 한번의 helm package 실행으로 생성하고 싶다면 별도의 방법을 사용해야 됩니다. (e.g. helmfile)

$ helm list
NAME 	NAMESPACE	REVISION	UPDATED                             	STATUS  	CHART        	APP VERSION
myapp	default  	1       	2025-05-18 17:04:01.846175 +0900 KST	deployed	mychart-0.1.0	1.16.0

$ kubectl get po,deploy,svc,sa
NAME                                 READY   STATUS    RESTARTS   AGE
pod/myapp-mychart-84df9ccfdf-8fkvb   1/1     Running   0          2m30s

NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/myapp-mychart   1/1     1            1           2m30s

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1      <none>        443/TCP   2m41s
service/myapp-mychart   ClusterIP   10.96.77.112   <none>        80/TCP    2m30s

NAME                           SECRETS   AGE
serviceaccount/default         0         2m33s
serviceaccount/myapp-mychart   0         2m30s

별도의 커스텀 없이 생성한 chart의 배포를 통해 생성한 K8s 리소스는 위와 같습니다.

templates에 들어있는 파일 하나를 보면 아래와 같이 .Values로 시작하는 변수들이 있습니다.

$ cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "mychart.fullname" . }}
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
spec:
  {{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}
  selector:
    matchLabels:
      {{- include "mychart.selectorLabels" . | nindent 6 }}
(이하 생략)

이 값들은 values.yaml 파일에 설정되어 있습니다.

$ cat values.yaml| grep replicaCount
replicaCount: 1

values.yaml 은 template 파일 내의 변수를 바인딩합니다.

환경별로 다른 값을 적용하는데 유용하고, 이를 수정하고 업데이트할 수 있습니다.

helm install시 values.yaml 파일을 지정할 수도 있기 때문에 하나의 차트로 여러개의 환경별 release를 생성할 수 있습니다.

마찬가지로 override하여 롤백하는 것도 가능합니다.

 

helm delete 명령어로 관련 리소스를 한꺼번에 내릴 수 있습니다.

$ helm delete myapp
release "myapp" uninstalled

$ kubectl get po,deploy,svc,sa
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   139m

NAME                     SECRETS   AGE
serviceaccount/default   0         139m

 

 

Kustomize

K8s를 아주 매우 겉핥기로만 알고 있었을 땐 Helm 밖에 못 들어봤는데요,

Kustomize는 K8s 1.14 버전(2019년 초)부터 기본 내장 되어있었나봅니다.

디렉토리 구조를 직접 만들어서 구성해야 되고,

환경을 values.yaml 파일이 아닌 리소스 yaml을 담은 환경별 폴더로 나누어서 적용합니다.

 

참고

https://helm.sh/docs/intro/using_helm/

https://kubernetes.io/docs/concepts/overview/working-with-objects/#describing-a-kubernetes-object

https://helm.sh/docs/helm/helm_create/

https://etloveguitar.tistory.com/141

https://www.inflearn.com/blogs/5626