[Kubernetes] Helm Chart Template 정리
안녕하세요? 정리하는 개발자 워니즈입니다. 이번시간에는 헬름 차트의 템플릿에 대해서 정리해보도록 하겠습니다. 필자의 프로젝트에서는 k8s를 활용하여 서비스를 하고자 진행중입니다.POD, SVC, ALB
를 모두 만들어서 연결은 해두었느데, CI/CD를 어떻게 할지 고민중이였습니다. 그러던 중, Helm을 알게되었고, 제가 작성해둔 Yaml 파일들을 Helm Chart로 작성을 해두고 배포시에 install을 하는 개념으로 진행하기로했습니다.
지난 글들은 아래를 참고 해주시면 됩니다.
- 쿠버네티스 1편 : 설치 가이드
- 쿠버네티스 2편 : pod
- 쿠버네티스 3편 : service
- 쿠버네티스 4편 : deployment
- 쿠버네티스 5편 : pod 설정
- 쿠버네티스 6편 : 배포 전략
- 쿠버네티스 7편 : volume
- 쿠버네티스 8편 : daemonset
- 쿠버네티스 9편 : 테라폼을 통한 클러스터 구성
- 쿠버네티스 10편 : eks에서 volume 사용하기
- 쿠버네티스 11편 : helm
- 쿠버네티스 12편 : helm chart template
- 쿠버네티스 13편 : helm deploy
- 쿠버네티스 14편 : fluentd를 통한 log수집
- 쿠버네티스 15편 : chartmuseum
- 쿠버네티스 16편 : 배포툴(ArgoCD 설치방법/사용법)
- 쿠버네티스 17편 : 배포툴(ArgoCD 구성/알람)
- 쿠버네티스 18편 : 쿠버네티스 Autoscailing
- 쿠버네티스 19편 : 쿠버네티스 로깅 아키텍처
1. Chart Template 시작하기
# mkdir /lab/helm/chart
# cd /lab/helm/chart
# helm create mychart
Creating mychart
# tree
.
└── mychart
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
위의 예제에서 중요한 부분은 templates
하위의 파일들입니다. 이부분을 커스터마이징 하기 위해 삭제 합니다.
# rm -rf mychart/templates/*
2. 첫번째 Template
간단한 Kubernetes configmap Object를 하나 생성해 배포해보도록하겠습니다.
# gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mychart-configmap
data:
myvalue: "Hello World"
helm install로 클러스터에 배포합니다.
# helm install ./mychart
NAME: alliterating-eel
LAST DEPLOYED: Wed Mar 20 13:15:12 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
mychart-configmap 1
배포된 실제 차트를 확인하기 위해서는 get명령어로 manifest를 조회하면 됩니다.
# helm get manifest alliterating-eel
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mychart-configmap
data:
myvalue: "Hello World"
2-1. 단순 template 호출
위의 예제에서 하드코딩된 name값을 헬름 내장 객체 release name으로 변경해보겠습니다.
TIP: name:
필드는 DNS의 제한때문에 63 character로 제한됩니다. 이에 대응해 release name은 53 character로 제한됩니다.
configmap.yaml
을 아래와 같이 수정한 후 다시 install을 진행하겠습니다.
# gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
# helm install ./mychart
NAME: good-abalone
LAST DEPLOYED: Wed Mar 20 14:02:57 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
good-abalone-configmap 1
Helm에서는 위와 같이 편집중인 차트를 미리 확인 하기 위한 모드를 제공하고 있습니다. install명령어에 아래와 같이 옵션을 주면 실제로 install은 되지 않고 템플릿이 어떻게 랜더링되는지 확인 할 수 있습니다.
# helm install --debug --dry-run ./mychart
[debug] Created tunnel using local port: '33941'
[debug] SERVER: "127.0.0.1:33941"
[debug] Original chart version: ""
[debug] CHART PATH: /lab/helm/chart/mychart
NAME: invisible-abalone
REVISION: 1
RELEASED: Wed Mar 20 14:12:30 2019
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
affinity: {}
fullnameOverride: ""
image:
pullPolicy: IfNotPresent
repository: nginx
tag: stable
ingress:
annotations: {}
enabled: false
hosts:
- host: chart-example.local
paths: []
tls: []
nameOverride: ""
nodeSelector: {}
replicaCount: 1
resources: {}
service:
port: 80
type: ClusterIP
tolerations: []
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: invisible-abalone-configmap
data:
myvalue: "Hello World"
3. Values Files
이번에는 Values 파일을 활용하여 템플릿을 변경해보도록 하겠습니다.
참고로 Values File은 아래와 같은 특징을 가지고 있습니다.
- 차트안에
values.yaml
파일명으로 생성된 파일입니다. - 상위 차트의
values.yaml
에 의해 재정의 될 수 있습니다. helm install
orhelm upgrade
시 -f 옵션으로 변경될 수 있습니다.(helm install -f myvals.yaml ./mychart
)- 개별적인 속성 값은
--set
옵션으로 변경할 수 있습니다. (such ashelm install --set foo=bar ./mychart
)
위의 예제에서 mychart/values.yaml
을 변경해 ConfigMap template에 반영해봅시다.
# gedit /lab/helm/chart/mychart/values.yaml
favoriteDrink: coffee
그리고 template 폴더안의 configmap.yaml파일에 해당내용을 반영합니다.
# gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favoriteDrink }}
렌더링해서 결과를 확인해 봅니다.
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: kneeling-puffin-configmap
data:
myvalue: "Hello World"
drink: coffee
values.yaml
파일에 정의한 coffee
가 템플릿에 반영된 것을 확인 할 수 있습니다.
이렇게 Values로 정의 된 속성은 위에서 언급했지만 install 명령어시 –set 옵션으로 아래와 같이 오버라이딩 될 수 있습니다.
# helm install --dry-run --debug --set favoriteDrink=slurm ./mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: dusty-nightingale-configmap
data:
myvalue: "Hello World"
drink: slurm
4. Template Functions and Pipelines
이번에는 Template 파일들 안에서 사용할 수 있는 함수와 Pipeline에 대해 살펴보겠습니다.
ConfigMap 객체에 문자열을 삽입할 때 quote 함수를 사용할 수 있습니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ quote .Values.favorite.drink }}
food: {{ quote .Values.favorite.food }}
Template 함수들은 functionName arg1 arg2...
. 와 같은 신텍스를 가집니다.
Helm은 60개 이상의 함수들을 사용할 수 있습니다. 해당내용은 Go template language , Sprig template library에서 확인 할 수 있습니다.
4-1. Pipelines
UNIX의 개념과 동일
gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | quote }}
food: {{ .Values.favorite.food | upper | quote }}
위의 예제는 아래와 같이 렌더링됩니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: trendsetting-p-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
4-2. default function
default
함수는 비교적 자주사용되는 함수로 Value값이 생략 된 경우 템플릿 내부에 기본값을 지정할 수 있게합니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
5. Flow Control
Flow Control로 템플릿 구조의 흐름을 제어할 수 있습니다.
if
/else
조건 블록 생성with
범위 지정range
, “for each”-style loop
In addition to these, it provides a few actions for declaring and using named template segments:
define
declares a new named template inside of your templatetemplate
imports a named templateblock
declares a special kind of fillable template area
5-1. IF/Else
{{ if PIPELINE }}
# Do something
{{ else if OTHER PIPELINE }}
# Do something else
{{ else }}
# Default case
{{ end }}
파이프라인은 value가 아래와 같을 때 false로 인식합니다.
- a boolean false
- a numeric zero
- an empty string
- a
nil
(empty or null) - an empty collection (
map
,slice
,tuple
,dict
,array
)
gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{ if and .Values.favorite.drink (eq .Values.favorite.drink "coffee") }}mug: true{{ end }}
helm install --dry-run --debug ./mychart
apiVersion: v1
kind: ConfigMap
metadata:
name: eyewitness-elk-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
mug: true
5-2. with
{{ with PIPELINE }}
# restricted scope
{{ end }}
gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
helm install --dry-run --debug ./mychart
5-3. ragne
foreach
loop와 동일한 성격의 제어문으로 예제를 아래와 같이 수정하겠습니다.
gedit /lab/helm/chart/mychart/values.yaml
favorite:
drink: coffee
food: pizza
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
gedit /lab/helm/chart/mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
toppings: |-
{{- range .Values.pizzaToppings }}
- {{ . | title | quote }}
{{- end }}
helm install --dry-run --debug ./mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: edgy-dragonfly-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
toppings: |-
- "Mushrooms"
- "Cheese"
- "Peppers"
- "Onions"
6. Variables
다른 프로그램언어와 마찬가지로 변수를 생성해 활용할 수 있습니다.
위의 예제를 아래와 같이 수정하면 에러가 발생하는데 원인은 .Release.Name은 with블럭 안에서는 사용될 수 없기 때문입니다. 이런 경우에 변수를 생성하여 활용할 수 있습니다.
gedit /lab/helm/chart/mychart/templates/configmap.yaml
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
release: {{ .Release.Name }}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- $relname := .Release.Name -}}
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
release: {{ $relname }}
{{- end }}
helm install --dry-run --debug ./mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: viable-badger-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
release: viable-badger
이러한 변수를 range 문과 같이 사용하면 효과적일 수 있습니다.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end}}
helm install --dry-run --debug ./mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: eager-rabbit-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
7. ETC
- .helmignore
.helmignore
파일은 gitignore와 dockeriignore파일과 마찬가지로 헬름차트안에 포함되지 않을 파일들을 명세하는 파일입니다.
# comment
.git
*/temp*
*/*/temp*
temp?
- NOTES.txt
gedit /lab/helm/chart/mychart/templates/NOTES.txt
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
To learn more about the release, try:
$ helm status {{ .Release.Name }}
$ helm get {{ .Release.Name }}
helm install ./mychart
RESOURCES:
==> v1/Secret
NAME TYPE DATA AGE
rude-cardinal-secret Opaque 1 0s
==> v1/ConfigMap
NAME DATA AGE
rude-cardinal-configmap 3 0s
NOTES:
Thank you for installing mychart.
Your release is named rude-cardinal.
To learn more about the release, try:
$ helm status rude-cardinal
$ helm get rude-cardinal
8. 마치며..
이번시간에는 helm template에 대한 기본 사용버베 대해서 알아보는 시간을 갖었습니다. 헬름은 필자가 느끼기에는 패키징 셋트 같습니다. 여러개의 resource들을 하나의 묶음으로 만들어서 install 하게되면 k8s 의 리소스들이 하나씩 모두 올라오게 됩니다. helm을 통한 배포 관리에 대한 내용으로 다음시간에 정리해보도록 하겠습니다.