Helm เป็นเครื่องมือที่ช่วยจัดการกับ Kubernetes application ผ่านทาง package manager ที่เรียกว่า Helm Chart
ขั้นตอนการติดตั้ง Helm
macOS
Helm Chart
Helm Chart เป็น repo ที่เก็บ template ของหลายๆ Kubernetes resource ที่เกี่ยวข้องกับ application หนึ่งๆ และมีการแยกส่วนของ configuration file ที่ช่วยให้ปรับแต่ง application ง่ายขึ้น
การสร้าง Helm chart ทำได้โดยคำสั่งดังนี้
จะเป็นการสร้าง chart ชื่อ demo
เริ่มต้นเรียนรู้ Helm Chart
เข้าไปใน folder chart demo ด้วยคำสั่งดังนี้
ภายใน folder จะประกอบด้วยโครงสร้าง file ดังต่อไปนี้
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
ให้ทำการลบไฟล์ใน folder template ทิ้งทั้งหมดก่อน และ clear content ใน values.yaml
rm -rf templates/*
echo > values.yaml
หลังจากนั้นสร้างไฟล์ configmap.yaml ใน folder templates
apiVersion: v1
kind: ConfigMap
metadata:
name: mychart-configmap
data:
myvalue: "Hello World"
ทดสอบ render output ด้วยคำสั่งดังนี้
helm template myrelease .
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mychart-configmap
data:
myvalue: "Hello World"
จะเห็นว่าเราสามารถ render yaml output ตามที่ต้องการได้ ผ่านการสร้าง file และ content ใน folder templates
หลังจากนั้น ให้แก้ไขไฟล์เป็นดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
ทดสอบ render อีกรอบ จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
จะเห็นว่าส่วน {{ .Release.Name }}
จะถูกแทนที่ด้วยคำว่า myrelease
ที่เป็นเช่นนั้น เพราะว่าจาก command ของเรา จะมี pattern ดังนี้
helm template <release name> <chart location>
release name จะเป็นชื่อ release ที่จะต้องชื่อที่ไม่ซ้ำกันภายใน namespace นั้นๆ เพราะเราสามารถติดตั้ง application ประเภทเดียวกันได้ใน namespace เดียวกัน
การมี release name จะทำให้เราสามารถ refer ได้ว่า Kubernetes resource นั้นเป็นของ application ไหน
chart location คือตำแหน่งที่เก็บ Chart.yaml ซึ่งในกรณีตัวอย่าง คือ current folder ที่เราอยู่ ซึ่งในกรณีแทนที่ได้ด้วย .
จะเห็นได้ว่าหากเราอยากให้ส่วนไหนใน Helm Chart ถูก render แบบ dynamic จะต้องเขียนไว้ในส่วนระหว่าง {{
และ }}
Built-in Object ใน Helm ที่ถูกใช้บ่อยๆ
Release
เป็น Object ที่ให้รายละเอียดเกี่ยวกับ release นั้นๆ
Release.name
เป็นชื่อของ release
Release.namespace
เป็น namespace ที่ติดตั้ง release นั้น
Values
เป็น Object ที่ refer ถึงค่าใน values.yaml
และจากค่าที่ user pass ให้ทาง cli
Chart
เป็น Object ที่ refer ถึง content ใน Chart.yaml
ส่วนที่มักจะถูกใช้งานคือ Chart.Name
และ Chart.Version
การอ้างถึงค่า Values
เปลี่ยน content ของ values.yaml
เป็นดังนี้
favoriteDrink: coffee
เปลี่ยน content ของ templates/configmap.yaml
เป็นดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favoriteDrink }}
ทดสอบ render จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: coffee
ลอง override ค่าด้วยคำสั่ง set ดังนี้
helm template myrelease . --set favoriteDrink=slurm
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: slurm
จะเห็นว่าคำสั่ง set สามารถ override ค่าทับ values ของ values.yaml
ได้
ลองเพิ่มค่าอื่นๆลงใน values.yaml
เพิ่มเติม
favorite:
drink: coffee
food: pizza
แก้ไข templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink }}
food: {{ .Values.favorite.food }}
ทดสอบรันด้วยคำสั่งดังนี้
helm template myrelease .
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: coffee
food: pizza
จะเห็นว่าเราสามารถ refer ค่าใน values ที่ถูกจัดเป็น structure ได้ ซึ่งจะทำให้ configuration เป็นระเบียบมากขึ้น
Template functions และ pipelines
แก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ quote .Values.favorite.drink }}
food: {{ quote .Values.favorite.food }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
ในที่นี้ quote
คือ function หนึ่งใน Helm Chart และค่าใดๆที่ตามหลัง function จะเป็น argument ของ function นั้น
function quote
นี้รับค่าเข้าไป และทำการ render ผลลัพธ์ออกมาเป็น string ที่ถูกครอบด้วย double quote ("
)
หลังจากนั้นลองแก้ไขค่าใน 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 | quote }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
ในที่นี้ เรามีการใช้ pipeline ( |
) ร่วมกับ function quote แสดงให้เห็นว่า ค่าใดๆก็ตามที่อยู่ก่อนหน้า pipeline จะถูก pass ไปเป็น argument สุดท้ายของ function หลัง pipeline
นอกจากนี้เรายังสามารถใช้ pipeline ร่วมกับหลายๆ function ได้อีกด้วย
ลองแก้ไขค่าใน 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 }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "PIZZA"
คำว่า pizza
จะถูกเปลี่ยนเป็น PIZZA
ตัวพิมพ์ใหญ่ด้วย function upper
ก่อนใส่ quote
pattern นี้เป็นสิ่งที่เราจะเห็นได้บ่อย เวลาใช้งาน Helm Chart
function ที่พบได้บ่อยๆใน Helm Chart
function default
ลองแก้ไขค่าใน 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 }}
comment values ใน values.yaml
favorite:
#drink: coffee
food: pizza
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: "tea"
food: "PIZZA"
function printf
ลองแก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: "tea"
food: "PIZZA"
function trim
ลองแก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ " Hello World " | trim }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: "Hello World"
drink: "tea"
food: "PIZZA"
function trunc
ลองแก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ " Hello World " | trim | trunc 5 }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: Hello
drink: "tea"
food: "PIZZA"
function toString
ลองแก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
function toYaml
แก้ไขค่าใน values.yaml ดังนี้
ลองแก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ " Hello World " | trim | trunc 5 }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
data:
{{ toYaml .Values.data }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
การใช้ condition ใน Helm Chart
การใช้ if
และ end
แก้ไขค่าใน values.yaml ดังนี้
favorite:
#drink: coffee
food: pizza
enableData: true
data:
foo: bar
ลองแก้ไขค่าใน templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{ if .Values.enableData }} data:
{{ toYaml .Values.data }}{{ end }}
any: any
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
any: any
ปัญหาของการวาง code ในลักษณะนี้จะทำให้เกิดปัญหาด้าน readability
เพื่อแก้ปัญหานั้น หน้าตาของ template/configmap.yaml ที่เราอยากได้ จะเป็นดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{ if .Values.enableData }}
data:
{{ toYaml .Values.data }}
{{ end }}
any: any
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
any: any
สาเหตที่เกิด whitespace ขึ้น เกิดจากการที่เรามีการ whitespace & newline ในส่วนอื่นๆของ content ในบริบทรอบข้าง {{ if }}
และ {{ end }}
การแก้ไขปัญหา ทำได้โดยเพิ่ม -
และ whitespace เพื่อบอกให้ engine ลบ whitespace ทิ้ง
แก้ไข templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{- if .Values.enableData }}
data:
{{ toYaml .Values.data }}
{{- end }}
any: any
เป็นการบอกให้ engine ลบ whitespace และ newline ฝั่งซ้ายของ {{ if }}
และ {{ end }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
any: any
หากเปลี่ยนค่า enableData
เป็น false
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
any: any
function indent
และ nindent
ในบางกรณีเราอยากจะให้ function เป็นตัวกำหนดจำนวน whitespace charcter ของต้นบรรทัดนั้นๆ แทนที่จะพิมพ์ whitespace ลงไปตรงๆ ซึ่งผิดพลาดได้ง่าย เราสามารถใช้ function indent
ทำหน้าที่นั้นแทนได้
หากลองแก้ไข templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{- if .Values.enableData }}
data:
{{ toYaml .Values.data | indent 4 }}
{{- end }}
any: any
และแก้ไขค่า enableData
เป็น true
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
any: any
แต่การแก้ไขลักษณะนี้จะทำให้เราเสีย readability ไป ดังนั้นเราสามารถแก้ไขได้โดยการใส่ whitespace ลงไป แล้วใช้ -
ในการลบ whitespace ก่อนหน้าแทน
หากลองแก้ไข templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{- if .Values.enableData }}
data:
{{- toYaml .Values.data | indent 4 }}
{{- end }}
any: any
ลองสั่งด้วย mode debug (helm template myrelease . --debug
) จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: release-name-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data: foo: bar
any: any
จะเห็นว่าผลลัพธ์ออกมาผิด
ในกรณีนี้เราสามารถแก้ไขได้โดยใช้ function nindent แทน indent ซึ่ง nindent จะทำให้เกิดการขึ้นบรรทัดใหม่ แล้วค่อย indent
หากลองแก้ไข templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
drink: {{ .Values.favorite.drink | default "tea" | quote }}
food: {{ .Values.favorite.food | upper | quote }}
{{- if .Values.enableData }}
data:
{{- toYaml .Values.data | nindent 4 }}
{{- end }}
any: any
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: release-name-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
any: any
ผลลัพธ์จะออกมาถูกต้องแล้ว
การใช้ with
จากตัวอย่างก่อนหน้าจะเห็นว่า เรา refer ค่าของ favorite drink และ favorite food โดยการ refer ไปยัง value ใน nested scope ใต้ .Values.favorite
ซึ่งทำให้เกิดการเขียน .Values.favorite
ซ้ำกัน เราสามารถลดการพิมพ์ซ้ำๆนั้นได้โดยการใช้ function with และ refer value ใต้ current scope นั้น ดังนี้
แก้ไข templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
{{- if .Values.enableData }}
data:
{{- toYaml .Values.data | nindent 4 }}
{{- end }}
any: any
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: release-name-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
data:
foo: bar
any: any
การใช้ loop ด้วย function range
แก้ไขไฟล์ values.yaml ดังนี้
favorite:
#drink: coffee
food: pizza
enableData: true
data:
foo: bar
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
แก้ไข templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
myvalue: {{ list 1 2 3 | toString }}
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
{{- end }}
toppings: |-
{{- range .Values.pizzaToppings }}
- {{ . | title | quote }}
{{- end }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: release-name-configmap
data:
myvalue: [1 2 3]
drink: "tea"
food: "PIZZA"
toppings: |-
- "Mushrooms"
- "Cheese"
- "Peppers"
- "Onions"
การใช้ variable
ใน helm เราสามารถ define variable ได้โดยการเขียนให้อยู่ในรูป $name
และ assign ค่าให้กับ variable นั้นได้ด้วยเครื่องหมาย :=
ทดสอบแก้ไข templates/configmap.yaml
ดังนี้
{{- $fixedstr := "test" -}}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
toppings: |-
{{- range .Values.pizzaToppings }}
- {{ . | title | quote }}
- {{ $fixedstr | quote }}
{{- end }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: release-name-configmap
data:
toppings: |-
- "Mushrooms"
- "test"
- "Cheese"
- "test"
- "Peppers"
- "test"
- "Onions"
- "test"
ตัวอย่างการใช้ร่วมกับ range
ทดสอบแก้ไข templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end }}
จะได้ผลลัพธ์จากการ render ดังนี้
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: release-name-configmap
data:
food: "pizza"
Subchart
ในเนื้อหาที่ผ่านมา เรามีการสร้าง chart สำหรับ application หนึ่ง แต่ในความเป็นจริง มีโอกาสบ่อยครั้งที่หลายๆ application จะต้องการอีก application หนึ่งในการทำงานร่วมกัน เช่น ทั้ง application A และ application B ต้องการ redis เพื่อใช้งานร่วมกัน แต่เป็น redis คนละตัว ไม่ share กัน เราก็ไม่ควรจะต้องเขียน manifest ของ redis ลงในทั้ง chart ของ application A และ application B
ทางแก้หนึ่งก็คือ แยก chart redis ออกมา และบอกให้ chart ของ application A และ B รู้ว่า เมื่อจะ deploy application A และ B จะต้องมีการ deploy redis ด้วยเช่นกัน
การเขียนให้ chart ของ application A และ B ไป depend กับ chart redis นี้ เราจะเรียกว่า เป็นการกำหนดให้ redis เป็น subchart ของ chart application A
การจะ pass values เข้าไปให้ subchart redis ได้นั้น จะต้องอาศัยการ pass ผ่าน global values
สร้าง subchart
cd charts
helm create mysubchart
rm -rf mysubchart/templates/*
echo 'dessert: cake' > mysubchart/values.yaml
cd ..
ใส่ content ของ charts/mysubchart/templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cfgmap2
data:
dessert: {{ .Values.dessert }}
ทดสอบ render ด้วยคำสั่ง ดังนี้
helm template myrelease .
จะได้ผลลัพธ์ดังนี้
---
# Source: demo/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-cfgmap2
data:
dessert: cake
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
food: "pizza"
จะพบว่ามี configmap ของ subchart เพิ่มขึ้นมา
การ override value ของ subchart ผ่าน parent chart
เราจะใส่ values ในไฟล์ values.yaml
เพิ่ม 2 บรรทัดท้าย ดังนี้
favorite:
#drink: coffee
food: pizza
enableData: true
data:
foo: bar
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
mysubchart:
dessert: ice cream
ทดสอบ render จะได้ผลลัพธ์ดังนี้
---
# Source: demo/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-cfgmap2
data:
dessert: ice cream
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
food: "pizza"
จะเห็นว่า ใน value file ท่อน mysubchart
ซึ่งตรงกับชื่อของ subchart ที่เราได้สร้างไว้ ค่าใดๆก็ตามภายใต้นั้นจะถูก pass ลงไปยัง subchart
ถ้าสร้าง subchart เป็นชื่ออื่น ต้องแก้ชื่อใน value file ตามด้วย
Global values
ในบางกรณีเราต้องการ pass value ที่ share ร่วมกันในหลายๆ subchart เราสามารถเขียนได้ภายใต้ .Values.global
ซึ่งจะทำให้เราไม่ต้อง maintain value หลายจุดในแต่ละ value สำหรับ subchart
แก้ values ในไฟล์ values.yaml
เพิ่ม 2 บรรทัดท้าย ดังนี้
favorite:
#drink: coffee
food: pizza
enableData: true
data:
foo: bar
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
mysubchart:
dessert: ice cream
global:
salad: caesar
แก้ templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s-configmap" .Release.Name }}
data:
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end }}
salad: {{ .Values.global.salad }}
แก้ charts/mysubchart/templates/configmap.yaml
ดังนี้
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cfgmap2
data:
dessert: {{ .Values.dessert }}
salad: {{ .Values.global.salad }}
ทดสอบ render จะได้ผลลัพธ์ดังนี้
---
# Source: demo/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-cfgmap2
data:
dessert: ice cream
salad: caesar
---
# Source: demo/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: myrelease-configmap
data:
food: "pizza"
salad: caesar
Chart & Subchart in real-world use case
ในการใช้งานจริง เราจะไม่ทำ subchart เป็น folder ภายใต้ chart ติดไปด้วยกัน แต่จะใช้การ refer ผ่าน helm dependencies แทนเพื่อสะดวกต่อการ maintain
เราจะกำหนด dependencies ภายใน Chart.yaml ดังนี้
dependencies:
- condition: memcached.enabled
name: memcached
repository: oci://registry-1.docker.io/bitnamicharts
version: 7.x.x
- condition: mariadb.enabled
name: mariadb
repository: oci://registry-1.docker.io/bitnamicharts
version: 19.x.x
- name: common
repository: oci://registry-1.docker.io/bitnamicharts
tags:
- bitnami-common
version: 2.x.x
จากตัวอย่างจะมีการ refer ให้หา chart จาก oci://registry-1.docker.io/bitnamicharts
โดยจะมี chart memcached, mariadb และ common ตาม version ที่กำหนดในท่อน version
และจะถูกใช้ต่อเมื่อ ใน values.yaml
แต่ละ value ของ subchart มีการกำหนด enabled
ให้มีค่าเป็น true
ตัวอย่างบางท่อนของ values.yaml
mariadb:
enabled: true
architecture: standalone