포스트

Helm Chart 작성방법 (2)

Helm에서 사용하는 Go Template 문법 이해하기

Helm Chart 작성방법 (2)

Helm Chart의 핵심은 단순한 YAML 파일이 아니라, Go Template을 기반으로 한 동적 렌더링 로직에 있다. 조건문, 반복문, 변수 치환, 함수 호출 등 Go Template 문법을 이해하지 못하면 Chart가 커질수록 유지보수가 어려워진다.

Go Template의 기본 문법을 알아보자.

1. 기본 표현식 구문


템플릿 블록

1
2
3
{{ EXPRESSION }}

  • {{ }}내부만 템플릿 엔진이 평가
  • YAML/문자열 어디든 삽입 가능

공백 제어

1
2
3
4
5
{{- EXP }}    # 왼쪽 공백 제거
{{ EXP -}}    # 오른쪽 공백 제거
{{- EXP -}}   # 양쪽 제거

2. 값 참조 (Value Access)


기본 경로 접근

1
2
.Values.key
.Values.parent.child

YAML map → dot(.)으로 접근

dot(.) 의미

  • . = 현재 scope 객체
  • 기본 root = Helm context
1
2
3
4
5
.Values
.Chart
.Release
.Capabilities
.Files

3. 조건문 (if / else / else if)


if

1
2
3
4
5
{{ if CONDITION }}
...
{{ end }}

if / else

1
2
3
4
5
6
7
{{ if CONDITION }}
...
{{ else }}
...
{{ end }}

else if

1
2
3
4
5
6
7
{{ if CONDITION1 }}
...
{{ else if CONDITION2 }}
...
{{ end }}

조건 평가 규칙 (trythy / falsy)

평가
truetrue
falsefalse
””false
nilfalse
0false
비어있지 않은 문자열true

4. 논리 함수


and

1
and A B C
  • 좌 → 우 평가
  • 하나라도 false → false

or

1
or A B
  • 하나라도 true → true

not

1
not A
  • 반드시 함수 호출 형태

5. 비교 함수


1
2
3
4
5
6
eq A B    # ==
ne A B    # !=
lt A B    # <
le A B    # <=
gt A B    # >
ge A B    # >=

예시:

1
2
3
{{ if eq .Values.type "NodePort" }}

6. default / required


default

1
default DEFAULT_VALUE VALUE
  • VALUE falsy → DEFAULT 반환

예시:

1
2
3
{{ default "latest" .Values.image.tag }}

required

1
required "error message" VALUE
  • VALUE false → Helm 에러 발생

7. with (스코프 변경)


1
2
3
4
5
6
{{ with .Values.persistence }}
size: {{ .size }}
enabled: {{ .enabled }}
{{ end }}

  • .가 with 대상 객체로 변경
  • 대상이 nil/false → 블록 미실행

8. range (반복문)


리스트 반복

1
2
3
4
5
{{ range .Values.ports }}
- containerPort: {{ . }}
{{ end }}

map

1
2
3
4
5
{{ range $key, $value := .Values.env }}
{{ $key }}: {{ $value }}
{{ end }}

range + else

1
2
3
4
5
6
7
{{ range .Values.items }}
...
{{ else }}
# items empty
{{ end }}

9. 변수 선언


1
2
3
{{- $name := "my-app" }}

  • $ 접두어 → 변수
  • 스코프 내부에서 유효

루트 컨텍스트 접근

1
2
3
{{ $.Values.image.tag }}

range, with 안에서는 $ 없으면 root 접근 불가

10. include / template


include

1
2
3
{{ include "chart.fullname" }}

  • 문자열 반환
  • 파이프라인(|)과 함께 사용 가능

template

1
2
3
{{ template "chart.fullname" . }}

  • 직접 출력
  • 파이프라인 사용 불가

11. 파이프라인(|)


1
2
3
{{ .Values.name | upper | quote }}

  • 왼쪽 결과를 오른쪽 함수 인자로 전달

12. 문자열/타입 함수 (Sprig)


문자열 함수

1
2
3
4
5
6
quote VALUE
upper VALUE
lower VALUE
trim VALUE
replace OLD NEW STRING
printf "%s-%s" A B

숫자 / 타입 함수

1
2
3
int VALUE
float64 VALUE
toString VALUE

13. 들여쓰기 제어


1
2
3
{{ toYaml .Values.resources | nindent 8 }}

함수의미
indent줄 앞에 공백 추가
nindent개행 + 공백

14. 파일 처리


단일 파일

1
2
3
{{ .Files.Get "config/app.conf" }}

1
2
3
{{ .Files.Get "file.yaml" | indent 2 }}

Glob

1
2
3
{{ (.Files.Glob "files/*").AsConfig }}

15. 주석


1
2
3
{{/* 템플릿 주석 */}}

  • 렌더링 결과에 포함되지 않음

16. lookup


1
lookup API KIND NAMESPACE NAME
1
2
3
{{ lookup "v1" "Secret" .Release.Namespace "my-secret" }}

  • 존재하면 object
  • 없으면 nil

17. Capabilities


1
2
.Capabilities.KubeVersion.Version
.Capabilities.APIVersions.Has "apps/v1"

18. define (함수 정의)


1
2
3
4
5
{{- define "chart.fullname" -}}
{{ printf "%s-%s" .Release.Name .Chart.Name }}
{{- end }}

19. fail


1
2
3
{{ fail "error message" }}

  • 즉시 helm 실패

20. empty / hasKey / kindIs


empty

1
empty VALUE
  • VALUE가 비어있으면 true

판정 기준

  • nil / 미정의 값
  • false
  • "" (빈 문자열)
  • 0 (정수/실수)
  • [] (길이 0인 리스트)
  • {} (길이 0인 map)
1
2
3
4
5
6
7
8
{{ empty "" }}        => true
{{ empty "abc" }}     => false
{{ empty 0 }}         => true
{{ empty 1 }}         => false
{{ empty (list) }}    => true
{{ empty (dict) }}    => true

사용 시 주의 점

  • empty .Values.foo.Values.foo가 정의되지 않은 경우에도 true로 평가되는 경우가 많음
  • 다만 “값이 0인데 유효한 설정” 같은 경우(예: 포트 0, replica 0 허용)에는 empty가 true로 나옴

hasKey MAP “key”

1
hasKey MAP "key"
  • MAP에 key 키 값이 존재하는지 확인

사용 시 주의 점

  1. hasKey는 키 존재 여부만 확인

예를 들어,

values.yaml

1
2
env:
  FOO: ""

라면,

template에서

1
2
3
4
{{ hasKey .Values.env "FOO" }}          => true
{{ empty (index .Values.env "FOO") }}   => true

  • 키는 존재하지만 값은 빈 문자열
  1. MAP이 map이 아닐 때
    • hasKey의 첫 번째 인자는 map 타입이어야 함
    • MAP이 nil이거나 map이 아닌 경우 에러
1
2
3
4
5
6
{{- $m := (default dict .Values.env) -}}
{{- if hasKey $m "FOO" -}}
...
{{- end -}}

dict는 빈 map을 만드는 Sprig 함수

  1. 키에 하이픈/점 이 있을 때 values key가 foo-bar와 같이 dot 접근이 어려우면 index 사용
1
2
3
4
{{- if hasKey .Values "foo-bar" -}}
{{- end -}}

kindIs “string” VALUE

1
kindIs "string" VALUE
  • VALUE의 kind가 지정한 kind인지 확인

kind 문자열 종류

  • string
  • bool
  • int / int64
  • float64
  • map
  • slice
  • invalid

실제 kind 문자열은 환경/버전에 따라 미묘하게 다를 수 있어, kindOf VALUE로 찍어서 확인

1
2
3
{{ kindOf .Values.someValue }}

함수입력반환확인 대상
empty아무 값bool값이 비었는지
hasKeymap + keybool키가 존재하는지
kindIskind 문자열 + 값bool값의 kind(타입 범주)

21. 문법 체크


1
2
helm lint .
helm template .