๐Ÿ› ๏ธ ๋‚˜๋งŒ์˜ Helm Chart ๋งŒ๋“ค๊ธฐ – ์„ค๊ณ„๋ถ€ํ„ฐ ํŒจํ‚ค์ง•๊นŒ์ง€

์ง€๋‚œ ๊ธ€์—์„œ๋Š” 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 ํ•˜๋‚˜๋กœ ๋ฐฐํฌ๊ฐ€ ์™„์„ฑ๋˜๋Š”” ์ž๋™ํ™”๋ฅผ ์™„์„ฑํ•ฉ๋‹ˆ๋‹ค.