-
[Helm] 가이드 - Flow Control공부/쿠버네티스&헬름 2025. 3. 15. 20:33
Helm 템플릿에서 Flow Control은 템플릿이 어떻게 렌더링될지 제어하는 데 사용되는 구문 구조를 의미합니다. 이를 통해 조건부 로직, 반복문 등을 템플릿 내에 구현하여 유연하고 동적인 매니페스트 생성을 가능하게 합니다. Helm의 Flow Control은 Go 템플릿 언어를 기반으로 하며, 특정 액션(Actions)을 사용하여 정의됩니다.
if/else
조건문의 기본 구조는 다음과 같습니다.
{{ if PIPELINE }} # Do something {{ else if OTHER PIPELINE }} # Do something else {{ else }} # Default case {{ end }}
파이프라인을 사용하면 조건문과 비슷한 표현을 할 수 있습니다. 파이프라인은 다음의 경우 false로 평가됩니다.
- boolean 값
false
- 숫자
0
- 빈 문자열
nil
(비어 있거나 null)- 빈 컬렉션 (맵, 슬라이스, 튜플, 딕트, 배열)
다른 모든 조건에서는 조건이 true입니다.
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 eq .Values.favorite.drink "coffee" }}mug: "true"{{ end }} -- 아래와 같이 확인 가능 # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: eyewitness-elk-configmap data: myvalue: "Hello World" drink: "coffee" food: "PIZZA" mug: "true"
공백 제어
아래의 yaml을 실행하면 mug 필드에 공백이 1개 더 추가되어 있어서 parsing error가 발생합니다.
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 eq .Values.favorite.drink "coffee" }} mug: "true" {{ end }} ------- $ helm install --dry-run --debug ./mychart SERVER: "localhost:44134" CHART PATH: /Users/mattbutcher/Code/Go/src/helm.sh/helm/_scratch/mychart Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: did not find expected key -------- # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: eyewitness-elk-configmap data: myvalue: "Hello World" drink: "coffee" food: "PIZZA" mug: "true"
들여쓰기를 정상적으로 한다면 다음과 같이 어색하게 출력됩니다.
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 eq .Values.favorite.drink "coffee" }} mug: "true" {{ end }} ------ # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: telling-chimp-configmap data: myvalue: "Hello World" drink: "coffee" food: "PIZZA" mug: "true"
템플릿 엔진이 실행될 때
{{
와}}
안의 내용은 제거하지만 나머지 공백은 정확히 그대로 남겨둡니다.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 eq .Values.favorite.drink "coffee" }} mug: "true" {{- end }} ------- # Source: mychart/templates/configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: clunky-cat-configmap data: myvalue: "Hello World" drink: "coffee" food: "PIZZA" mug: "true"
만약 하이픈을 왼쪽 뿐만 아니라 오른쪽에도 붙인다면 양쪽 모두 줄바꿈 문자를 사용하기 때문에 아래와 같은 결과가 나옵니다.
food: {{ .Values.favorite.food | upper | quote }} {{- if eq .Values.favorite.drink "coffee" -}} mug: "true" {{- end -}} ------ food: "PIZZA"mug: "true"
마지막으로, 템플릿 지시문의 간격 조정을 완벽하게 익히려고 애쓰는 대신, 템플릿 시스템에게 들여쓰기를 어떻게 할지 알려주는 것이 더 쉬울 때가 있습니다. 이러한 이유로
indent
함수({{ indent 2 "mug:true" }})를 사용하는 것이 유용할 때가 있습니다.with
특정 객체의 스코프 내에서 템플릿의 일부를 실행하는 데 사용됩니다. 이를 통해 긴 경로를 반복해서 사용하는 것을 방지하고 템플릿을 더 간결하게 만들 수 있습니다.
.
은 현재 스코프에 대한 참조이므로.Values
는 템플릿에게 현재 스코프에서Values
객체를 찾으라고 지시합니다.with
의 문법은 간단한if
구문과 유사합니다.{{ with PIPELINE }} # restricted scope {{ end }}
스코프는 변경될 수 있습니다.
with
를 사용하면 현재 스코프(.
)를 특정 객체로 설정할 수 있습니다. 예를 들어, 우리는.Values.favorite
로 작업을 해왔습니다..
스코프가.Values.favorite
를 가리키도록 ConfigMap을 다시 작성해 보겠습니다.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 }}
with
뒤의 블록은PIPELINE
의 값이 비어 있지 않은 경우에만 실행됩니다.이제
.drink
와.food
를 한정자 없이 참조할 수 있습니다. 이는with
구문이.
을.Values.favorite
를 가리키도록 설정했기 때문입니다..
은{{ end }}
뒤에 이전 스코프로 재설정됩니다.제한된 스코프 내에서는
..
을 사용하여 부모 스코프의 다른 객체에 접근할 수 없습니다. 예를 들어, 다음 코드는 실패합니다.{{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} release: {{ .Release.Name }} {{- end }}
이는
Release.Name
이..
에 대한 제한된 스코프 내에 없기 때문에 오류를 발생시킬 것입니다. 하지만 마지막 두 줄의 순서를 바꾸면{{ end }}
이후에 스코프가 재설정되므로 모든 것이 예상대로 작동할 것입니다.{{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} {{- end }} release: {{ .Release.Name }}
또는 부모 스코프에서
Release.Name
객체에 접근하기 위해$
를 사용할 수 있습니다.$
는 템플릿 실행이 시작될 때 루트 스코프에 매핑되며 템플릿 실행 중에는 변경되지 않습니다. 다음 코드도 잘 작동할 것입니다.{{- with .Values.favorite }} drink: {{ .drink | default "tea" | quote }} food: {{ .food | upper | quote }} release: {{ $.Release.Name }} {{- end }}
range
리스트나 맵과 같은 컬렉션의 각 항목에 대해 템플릿의 특정 부분을 반복적으로 렌더링하는 데 사용됩니다.
values.yaml
파일에 피자 토핑 목록이 있다고 가정합니다.favorite: drink: coffee food: pizza pizzaToppings: - mushrooms - cheese - peppers - onions - pineapple
이제
pizzaToppings
라는 리스트(템플릿에서는 슬라이스라고 함)가 생겼습니다. 이 리스트를 ConfigMap에 출력하도록 템플릿을 수정해봅니다.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 }}
부모 스코프에서
Values.pizzaToppings
리스트에 접근하기 위해$
를 사용할 수 있습니다.$
는 템플릿 실행이 시작될 때 루트 스코프에 매핑되며 템플릿 실행 중에는 변경되지 않습니다.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 }} toppings: |- {{- range $.Values.pizzaToppings }} - {{ . | title | quote }} {{- end }} {{- end }}
toppings:
리스트를 자세히 살펴보겠습니다.range
함수는pizzaToppings
리스트를 "range over"(반복)합니다. 여기서with
가.
의 스코프를 설정하는 것처럼range
연산자도 마찬가지입니다. 루프를 반복할 때마다.
은 현재 피자 토핑으로 설정됩니다. 즉, 처음에는.
이mushrooms
로 설정됩니다. 두 번째 반복에서는cheese
로 설정되는 식입니다..
의 값을 파이프라인으로 직접 보낼 수 있으므로{{ . | title | quote }}
를 실행하면.
이title
(제목 케이스 함수)로 보내진 다음quote
로 보내집니다. 이 템플릿을 실행하면 다음과 같은 출력이 생성됩니다.# 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" - "Pineapple"
이제 이 예제에서
toppings: |-
줄은 여러 줄 문자열을 선언하고 있습니다. 따라서 토핑 목록은 실제로 YAML 목록이 아니라 하나의 큰 문자열입니다. 이렇게 한 이유는 ConfigMap의data
는 키/값 쌍으로 구성되어 있으며 키와 값 모두 단순한 문자열이기 때문입니다.템플릿 내에서 빠르게 리스트를 만들고 그 리스트를 순회하는 것이 유용할 때가 있습니다.
tuple
함수를 사용하면 이를 쉽게 구현할 수 있습니다.sizes: |- {{- range tuple "small" "medium" "large" }} - {{ . }} {{- end }} -------- sizes: |- - small - medium - large
레퍼런스
https://helm.sh/docs/chart_template_guide/control_structures/
- boolean 값