์ง๋ ๊ธ์์๋ Bitnami๊ฐ ๋ง๋ Chart๋ฅผ ๊ฐ์ ธ๋ค ์ฐ๋ “์๋น์” ์ญํ ์ ํ์ต๋๋ค. ์ด๋ฒ์ ์ง์ Chart๋ฅผ ๋ง๋๋ “์์ฐ์” ์ญํ ๋ก ์ ํํฉ๋๋ค. Custom Chart๋ฅผ ๋ง๋ค๋ฉด ์ฐ๋ฆฌ ํ์ ๋ฐฐํฌ ํ์ค์ ์ฝ๋๋ก ์ ์ํ๊ณ , ์ด๋ค ํ๊ฒฝ์์๋ (dev/staging/prod) ๋์ผํ ๋ฐฉ์์ผ๋ก ๋ฐฐํฌํ ์ ์์ต๋๋ค.
๐๏ธ Step 1 โ Chart ๋ผ๋ ์์ฑ (Scaffolding)
helm create ๋ช
๋ น์ด ํ๋๋ก ํ์ค ๋๋ ํ ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์๋์ผ๋ก ๋ง๋ค์ด์ค๋๋ค.
helm create mywebapp
ls -R mywebapp
mywebapp/
โโโ Chart.yaml # ์ฐจํธ ๋ฉํ๋ฐ์ดํฐ (์ด๋ฆ, ๋ฒ์ )
โโโ values.yaml # ๊ธฐ๋ณธ ์ค์ ๊ฐ (๋ณ์๋ค)
โโโ charts/ # ์์กด ์ฐจํธ๋ค
โโโ templates/ # ์ค์ K8s YAML ํ
ํ๋ฆฟ๋ค
โโโ deployment.yaml
โโโ service.yaml
โโโ ingress.yaml
โโโ _helpers.tpl # ์ฌ์ฌ์ฉ ๊ฐ๋ฅํ ํ
ํ๋ฆฟ ์กฐ๊ฐ
โโโ ...
3๊ฐ์ง ํต์ฌ ํ์ผ๋ง ์๋ฉด ๋ฉ๋๋ค:
Chart.yamlโ ์ด ์ฐจํธ์ ์ด๋ฆ/๋ฒ์ ๋ช ์ฐฐvalues.yamlโ ์ฌ์ฉ์๊ฐ ๋ฐ๊ฟ ์ ์๋ ์ค์ ๊ฐ๋คtemplates/โ ๋ณ์({{ }})๊ฐ ๋ซ๋ ค ์๋ K8s YAML ํ์ผ๋ค
๐จ Step 2 โ Go Template ๋ฌธ๋ฒ ์ดํด
Helm์ ํต์ฌ์ **”๋ฐ์ดํฐ์ ๋ก์ง์ ๋ถ๋ฆฌ”**์ ๋๋ค.
values.yaml (๋ฐ์ดํฐ) + templates/*.yaml (ํ) = ์์ฑ๋ K8s YAML
templates/deployment.yaml์ ๋ณด๋ฉด ์ด๋ฐ ๋ถ๋ถ์ด ์์ต๋๋ค:
# templates/deployment.yaml (์ผ๋ถ)
spec:
replicas: {{ .Values.replicaCount }} # โ ์ฌ๊ธฐ๊ฐ ๋ณ์!
values.yaml์๋:
# values.yaml
replicaCount: 1 # โ ์ด ๊ฐ์ด ์ ๋ณ์ ์๋ฆฌ์ ๋ค์ด๊ฐ
์ฆ, {{ .Values.replicaCount }} = values.yaml์ replicaCount ๊ฐ.
๐ ํด๋ฌ์คํฐ ๋ฐฐํฌ ์์ด ๋ ๋๋ง ๋ฏธ๋ฆฌ ๋ณด๊ธฐ (Dry Run)
์ค์ ๋ก ํด๋ฌ์คํฐ์ ๋ฐฐํฌํ๊ธฐ ์ ์ ์ต์ข YAML์ด ์ด๋ป๊ฒ ๋ง๋ค์ด์ง๋์ง ํ์ธํฉ๋๋ค. ๊ฐ๋ฐ ์ค ์ค์๋ฅผ ์ก๋ ํต์ฌ ๋๊ตฌ์ ๋๋ค.
helm template debug-release ./mywebapp
ํ๋ฉด์ ์์์ง๋ YAML์ด ์ค์ ๋ก ๋ฐฐํฌ๋ ๋ด์ฉ์
๋๋ค. kind: Deployment, kind: Service ๊ฐ์ ๋ด์ฉ์ด ๋ณด์ด๋ฉด ์ ์์
๋๋ค.
๐ ๏ธ Step 3 โ ์ค์ ์ปค์คํฐ๋ง์ด์ง
๊ธฐ๋ณธ๊ฐ ๋ณ๊ฒฝ โ replicaCount 2๊ฐ๋ก ๊ณ ์
# values.yaml์์ 1์ 2๋ก ๋ณ๊ฒฝ
sed -i 's/replicaCount: 1/replicaCount: 2/' mywebapp/values.yaml
# ๋ณ๊ฒฝ ํ์ธ
grep "replicaCount" mywebapp/values.yaml
# replicaCount: 2 โ ์ฑ๊ณต!
# ๋ ๋๋ง ๊ฒฐ๊ณผ์์ replicas ๊ฐ ํ์ธ
helm template debug ./mywebapp | grep "replicas:"
# replicas: 2 โ ๋ณ์๊ฐ ์ ์ฐ๊ฒฐ๋จ
์กฐ๊ฑด๋ฌธ์ผ๋ก ๋ฆฌ์์ค ์ผ๊ณ ๋๊ธฐ
values.yaml์ ingress.enabled ๊ฐ์ผ๋ก Ingress ์์ฑ์ ์ ์ดํฉ๋๋ค.
# values.yaml์์
ingress:
enabled: false # true๋ก ๋ฐ๊พธ๋ฉด Ingress๊ฐ ์์ฑ๋จ
templates/ingress.yaml ๋ด๋ถ:
{{- if .Values.ingress.enabled -}} # โ ์ด ์กฐ๊ฑด์ด true์ผ ๋๋ง ๋ ๋๋ง
apiVersion: networking.k8s.io/v1
kind: Ingress
...
{{- end }}
# enabled: false โ true๋ก ๋ณ๊ฒฝ ํ ๋ ๋๋ง ํ์ธ
helm template debug ./mywebapp | grep "kind: Ingress"
# kind: Ingress โ ์ด์ Ingress๊ฐ ํฌํจ๋จ!
๐ฆ Step 4 โ ํจํค์ง ๋ฐ ๋ฒ์ ๊ด๋ฆฌ
๋ถ๋ ๊ฒ์ฌ (Lint)
๋ฐฐํฌ ์ ์ ๋ฌธ๋ฒ ์ค๋ฅ๋ฅผ ๋ฏธ๋ฆฌ ์ก์ต๋๋ค.
helm lint ./mywebapp
# 1 chart(s) linted, 0 chart(s) failed โ ํต๊ณผ!
ํจํค์ง
helm package ./mywebapp
# mywebapp-0.1.0.tgz ์์ฑ!
ls -l *.tgz
# -rw-r--r-- 1 ... mywebapp-0.1.0.tgz
ํ์ผ๋ช
๊ท์น: {์ฐจํธ์ด๋ฆ}-{๋ฒ์ }.tgz์
๋๋ค. ๋ฒ์ ์ Chart.yaml์ version ํ๋๋ฅผ ๋ฐ๋ผ๊ฐ๋๋ค.
๋ฒ์ ์ ๊ทธ๋ ์ด๋ ์๋ฎฌ๋ ์ด์
# Chart.yaml์์ ๋ฒ์ ์ฌ๋ฆฌ๊ธฐ
sed -i 's/version: 0.1.0/version: 0.2.0/' mywebapp/Chart.yaml
# ์ฌํจํค์ง
helm package ./mywebapp
# ์ด์ ๋ ๋ฒ์ ์ด ๊ณต์กด
ls -l *.tgz
# mywebapp-0.1.0.tgz
# mywebapp-0.2.0.tgz โ ์ ๋ฒ์ !
๐ก ์ Chart๋ฅผ ์ง์ ๋ง๋ค์ด์ผ ํ๋๊ฐ?
Bitnami ๊ฐ์ ๊ณต๊ฐ Chart๋ ๋ฒ์ฉ์ ์ผ๋ก ๋ง๋ค์ด์ ธ์ ์ต์ ์ด ์๋ฐฑ ๊ฐ์ ๋๋ค. ์ฐ๋ฆฌ ํ์ ๋ฑ ๋ง๋ ์ค์ ์ ์ง์ ๋ง๋๋ ๊ฒ ๋ซ์ต๋๋ค.
Custom Chart๋ฅผ ์ฐ๋ฉด ์ด๋ฐ ๊ฒ ๊ฐ๋ฅํฉ๋๋ค:
# dev ํ๊ฒฝ ๋ฐฐํฌ
helm install myapp ./mywebapp -f values-dev.yaml
# production ํ๊ฒฝ ๋ฐฐํฌ (๊ฐ์ Chart, ๋ค๋ฅธ values)
helm install myapp ./mywebapp -f values-prod.yaml
ํ๋์ Chart ์์ค๋ก ์ฌ๋ฌ ํ๊ฒฝ์ ์ฐ์ด๋ผ ์ ์์ต๋๋ค. CI/CD ํ์ดํ๋ผ์ธ์ ๋ฃ๊ธฐ๋ ๋ฑ ์ข์ต๋๋ค.
๐ Chart ๊ฐ๋ฐ ํต์ฌ ๋ช ๋ น์ด
| ๊ตฌ๋ถ | ๋ช ๋ น์ด | ์ค๋ช |
|---|---|---|
| ์์ฑ | helm create [์ด๋ฆ] | ์ ์ฐจํธ ๋๋ ํ ๋ฆฌ ์์ฑ |
| ๊ฒ์ฆ | helm template [๋ฆด๋ฆฌ์ฆ] [๊ฒฝ๋ก] | ๋ ๋๋ง ๊ฒฐ๊ณผ ๋ฏธ๋ฆฌ๋ณด๊ธฐ |
helm lint [๊ฒฝ๋ก] | ๋ฌธ๋ฒ ์ค๋ฅ ๊ฒ์ฌ | |
| ํจํค์ง | helm package [๊ฒฝ๋ก] | .tgz ์์ถ ํ์ผ ์์ฑ |
ls -l *.tgz | ์์ฑ๋ ํจํค์ง ํ์ธ |
โ Helm ์๋ฆฌ์ฆ ์ ๋ฆฌ
- Step 1: ๋จ์ Chart ์ฐ๊ธฐ (์ค์น, ์ ๊ทธ๋ ์ด๋, ๋กค๋ฐฑ) โ Helm์ ์๋น์
- Step 2 (์ด๋ฒ ๊ธ): ๋ด Chart ๋ง๋ค๊ธฐ (๋ผ๋ ์์ฑ, ํ ํ๋ฆฟ, ํจํค์ง) โ Helm์ ์์ฐ์
์ด์ ๋ค์ ๋จ๊ณ์ธ GitOps์ ๋๋ค. ์ด Chart๋ฅผ Git์ ์ฌ๋ฆฌ๊ณ , ArgoCD๊ฐ ์๋์ผ๋ก ๊ฐ์ ธ๊ฐ์ ํด๋ฌ์คํฐ์ ๋ฐฐํฌํ๊ฒ ๋ง๋ค ์ฐจ๋ก์ ๋๋ค.
๋ค์ ๊ธ์์๋ ArgoCD๋ก GitOps ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ๊ณ , “Git Push ํ๋๋ก ๋ฐฐํฌ๊ฐ ์์ฑ๋๋” ์๋ํ๋ฅผ ์์ฑํฉ๋๋ค.