Helm Chart의 핵심은 단순한 YAML 파일이 아니라, Go Template을 기반으로 한 동적 렌더링 로직에 있다. 조건문, 반복문, 변수 치환, 함수 호출 등 Go Template 문법을 이해하지 못하면 Chart가 커질수록 유지보수가 어려워진다.
Go Template의 기본 문법을 알아보자.
1. 기본 표현식 구문
템플릿 블록
{% raw %}
{{ EXPRESSION }}
{% endraw %}
{``{}``}내부만 템플릿 엔진이 평가- YAML/문자열 어디든 삽입 가능
공백 제어
{% raw %}
{{- EXP }} # 왼쪽 공백 제거
{{ EXP -}} # 오른쪽 공백 제거
{{- EXP -}} # 양쪽 제거
{% endraw %}
2. 값 참조 (Value Access)
기본 경로 접근
.Values.key
.Values.parent.child
YAML map → dot(.)으로 접근
dot(.) 의미
.= 현재 scope 객체- 기본 root = Helm context
.Values
.Chart
.Release
.Capabilities
.Files
3. 조건문 (if / else / else if)
if
{% raw %}
{{ if CONDITION }}
...
{{ end }}
{% endraw %}
if / else
{% raw %}
{{ if CONDITION }}
...
{{ else }}
...
{{ end }}
{% endraw %}
else if
{% raw %}
{{ if CONDITION1 }}
...
{{ else if CONDITION2 }}
...
{{ end }}
{% endraw %}
조건 평가 규칙 (trythy / falsy)
| 값 | 평가 |
|---|---|
| true | true |
| false | false |
| "" | false |
| nil | false |
| 0 | false |
| 비어있지 않은 문자열 | true |
4. 논리 함수
and
and A B C
- 좌 → 우 평가
- 하나라도 false → false
or
or A B
- 하나라도 true → true
not
not A
- 반드시 함수 호출 형태
5. 비교 함수
eq A B # ==
ne A B # !=
lt A B # <
le A B # <=
gt A B # >
ge A B # >=
예시:
{% raw %}
{{ if eq .Values.type "NodePort" }}
{% endraw %}
6. default / required
default
default DEFAULT_VALUE VALUE
- VALUE falsy → DEFAULT 반환
예시:
{% raw %}
{{ default "latest" .Values.image.tag }}
{% endraw %}
required
required "error message" VALUE
- VALUE false → Helm 에러 발생
7. with (스코프 변경)
{% raw %}
{{ with .Values.persistence }}
size: {{ .size }}
enabled: {{ .enabled }}
{{ end }}
{% endraw %}
.가 with 대상 객체로 변경- 대상이 nil/false → 블록 미실행
8. range (반복문)
리스트 반복
{% raw %}
{{ range .Values.ports }}
- containerPort: {{ . }}
{{ end }}
{% endraw %}
map
{% raw %}
{{ range $key, $value := .Values.env }}
{{ $key }}: {{ $value }}
{{ end }}
{% endraw %}
range + else
{% raw %}
{{ range .Values.items }}
...
{{ else }}
# items empty
{{ end }}
{% endraw %}
9. 변수 선언
{% raw %}
{{- $name := "my-app" }}
{% endraw %}
$접두어 → 변수- 스코프 내부에서 유효
루트 컨텍스트 접근
{% raw %}
{{ $.Values.image.tag }}
{% endraw %}
Note
range, with 안에서는 $ 없으면 root 접근 불가
10. include / template
include
{% raw %}
{{ include "chart.fullname" }}
{% endraw %}
- 문자열 반환
- 파이프라인(
|)과 함께 사용 가능
template
{% raw %}
{{ template "chart.fullname" . }}
{% endraw %}
- 직접 출력
- 파이프라인 사용 불가
11. 파이프라인(|)
{% raw %}
{{ .Values.name | upper | quote }}
{% endraw %}
- 왼쪽 결과를 오른쪽 함수 인자로 전달
12. 문자열/타입 함수 (Sprig)
문자열 함수
quote VALUE
upper VALUE
lower VALUE
trim VALUE
replace OLD NEW STRING
printf "%s-%s" A B
숫자 / 타입 함수
int VALUE
float64 VALUE
toString VALUE
13. 들여쓰기 제어
{% raw %}
{{ toYaml .Values.resources | nindent 8 }}
{% endraw %}
| 함수 | 의미 |
|---|---|
| indent | 줄 앞에 공백 추가 |
| nindent | 개행 + 공백 |
14. 파일 처리
단일 파일
{% raw %}
{{ .Files.Get "config/app.conf" }}
{% endraw %}
{% raw %}
{{ .Files.Get "file.yaml" | indent 2 }}
{% endraw %}
Glob
{% raw %}
{{ (.Files.Glob "files/*").AsConfig }}
{% endraw %}
15. 주석
{% raw %}
{{/* 템플릿 주석 */}}
{% endraw %}
- 렌더링 결과에 포함되지 않음
16. lookup
lookup API KIND NAMESPACE NAME
{% raw %}
{{ lookup "v1" "Secret" .Release.Namespace "my-secret" }}
{% endraw %}
- 존재하면 object
- 없으면 nil
17. Capabilities
.Capabilities.KubeVersion.Version
.Capabilities.APIVersions.Has "apps/v1"
18. define (함수 정의)
{% raw %}
{{- define "chart.fullname" -}}
{{ printf "%s-%s" .Release.Name .Chart.Name }}
{{- end }}
{% endraw %}
19. fail
{% raw %}
{{ fail "error message" }}
{% endraw %}
- 즉시 helm 실패
20. empty / hasKey / kindIs
empty
empty VALUE
VALUE가 비어있으면 true
판정 기준
nil/ 미정의 값false""(빈 문자열)0(정수/실수)[](길이 0인 리스트){}(길이 0인 map)
{% raw %}
{{ empty "" }} => true
{{ empty "abc" }} => false
{{ empty 0 }} => true
{{ empty 1 }} => false
{{ empty (list) }} => true
{{ empty (dict) }} => true
{% endraw %}
사용 시 주의 점
empty .Values.foo는.Values.foo가 정의되지 않은 경우에도 true로 평가되는 경우가 많음- 다만 “값이 0인데 유효한 설정” 같은 경우(예: 포트 0, replica 0 허용)에는
empty가 true로 나옴
hasKey MAP “key”
hasKey MAP "key"
- MAP에
key키 값이 존재하는지 확인
사용 시 주의 점
hasKey는 키 존재 여부만 확인
예를 들어,
values.yaml가
env:
FOO: ""
라면,
template에서
{% raw %}
{{ hasKey .Values.env "FOO" }} => true
{{ empty (index .Values.env "FOO") }} => true
{% endraw %}
- 키는 존재하지만 값은 빈 문자열
- MAP이 map이 아닐 때
hasKey의 첫 번째 인자는 map 타입이어야 함- MAP이
nil이거나 map이 아닌 경우 에러
{% raw %}
{{- $m := (default dict .Values.env) -}}
{{- if hasKey $m "FOO" -}}
...
{{- end -}}
{% endraw %}
dict는 빈 map을 만드는 Sprig 함수 {: .prompt-info }
- 키에 하이픈/점 이 있을 때
values key가
foo-bar와 같이 dot 접근이 어려우면index사용
{% raw %}
{{- if hasKey .Values "foo-bar" -}}
{{- end -}}
{% endraw %}
kindIs “string” VALUE
kindIs "string" VALUE
- VALUE의 kind가 지정한 kind인지 확인
kind 문자열 종류
stringboolint/int64float64mapsliceinvalid
Info
실제 kind 문자열은 환경/버전에 따라 미묘하게 다를 수 있어, kindOf VALUE로 찍어서 확인
{% raw %}
{{ kindOf .Values.someValue }}
{% endraw %}
| 함수 | 입력 | 반환 | 확인 대상 |
|---|---|---|---|
empty | 아무 값 | bool | 값이 비었는지 |
hasKey | map + key | bool | 키가 존재하는지 |
kindIs | kind 문자열 + 값 | bool | 값의 kind(타입 범주) |
21. 문법 체크
helm lint .
helm template .
