Basic Kubernetes Part 9 - Helm - เครื่องมือที่ช่วยในการ Deploy อะไรที่ซับซ้อน Part 2

Basic Kubernetes Part 9 - Helm - เครื่องมือที่ช่วยในการ Deploy อะไรที่ซับซ้อน Part 2

ในตอนที่แล้วเราได้ลองใช้งานตัว Helm ในการทำการ deploy application โดยทำการสร้าง template และแทนค่าด้วย value ตามที่กำหนดไว้ ซึ่งเราสามารถ deploy application ให้กับ company a , company b , company c ผ่านการใช้ config file ซึ่งดูเหมือนว่ามันจะหมดแล้ว แต่ในการใช้งานจริงนั้นมีความต้องการอีกหลายอย่างที่ต้องการและ Helm สามารถช่วยเราได้

ตัวอย่างไฟล์ทั้งหมดสามารถดูได้ที่ Link

if

ในบางกรณีที่เราต้องการ Deploy ที่ต้องใช้ if ตัวอย่างเช่นถ้าเป็นลูกค้า vip นั้นจะใช้ memory ได้ 500MB แต่ถ้าไม่ใช่จะใช้ memory ได้แค่ 100MB (ผมขอใช้ env บอกขนาด memory ที่ใช้ได้ แทนการบังคับ memory จริงๆ จะได้ตรวจสอบง่ายๆ)

ด้วยความรู้ที่เรามีตอนนี้สิ่งที่เราทำได้คือการสร้างค่า config เพิ่มในไฟล์ values.yaml และแก้ไขไฟล์ template ดังตัวอย่างด้านล่าง

values.yaml

1
2
3
domain: "company-c.com"
owner: "NORMAL PROGRAMMER"
maxMemory: "400MB"

จากตัวอย่างด้านบนเราทำการสร้าง config ชื่อ maxMemory ขึ้นมาเพื่อใช้แสดง memory สูงสุดที่สามารถใช้ได้

whoami.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-deployment
labels:
app: whoami
spec:
selector:
matchLabels:
app: whoami-app
template:
metadata:
labels:
app: whoami-app
spec:
containers:
- name: whoami-container
image: traefik/whoami
ports:
- containerPort: 80
env:
- name: "OWNER"
value: {{ .Values.owner }}
- name: "MAX_MEMORY"
value: {{ .Values.maxMemory }}
---
# ผมขอละการประกาศส่วน service กับ ingress นะครับ

จากตัวอย่างด้านบนจะเห็นว่าเราเพิ่ม .Values.maxMemory เข้าไป ด้วยการทำเท่านี้เราก็สามารถ deploy application ได้ตามความต้องการแล้ว

ปัญหาที่เกิดขึ้น

ปัญหาที่เกิดขึ้นนั้นมาจากการเรากำหนด maxMemory ไว้ที่ไฟล์ config เพื่อบอกว่า memory ที่ใช้ได้คือเท่าไหร่ ทีนี้ลองคิดภาพตามว่าถ้าสมมติว่ามีการเปลี่ยนกฏเกี่ยวกับ maxMemory เช่น ลูกค้า VIP ใช้ maxMemory ได้ 800MB ส่วนที่ไม่ใช่จะได้ 600MB ถ้ามีการเปลี่ยนกฏแบบนี้รับรองเลยว่าคุณจะต้องไปไล่แก้ config ไฟล์ของทุกลูกค้าโดยแก้จาก 400MB ไปเป็น 800MB ซึ่งแน่นอนว่าถ้ามีสัก 100 บริษัทก็น่าจะเป็นฝันร้ายในการไล่แก้ อีกทั้ง ถ้าชนิดของลูกค้ามีหลายระดับเช่น nomal , goal , vip แล้วบางระดับใช้ memory เท่ากัน เช่น goal กับ vip ใช้ memory เท่านั้น คราวนี้คุณจะไม่สามารถ replace all 400MB ไปเป็น 800MB ได้แล้ว เพราะคุณต้องไปแยกเองว่าตกลงแล้วบริษัทนี้มันอยู่ระดับอะไร สร้างความวุ่นวาย ปวดหัวไปอีก นี่ยังไม่รวมว่าถ้าย้ายระดับจะต้องแก้กี่ค่า (กรณีที่ไม่ได้จำกัดแค่ maxMemory)

ใช้ if มาแก้ปัญหา

จากปัญหาในส่วนที่แล้ว จะเห็นว่าเราต้องการควบคุมขนาดของ maxMemory ที่เดียว ไม่อยากไปจัดการที่ไฟล์ config ดังนั้นเราจึงควรกำหนดมันลงไปที่ template เลย ในส่วน config นั้นเราเปลี่ยนมากำหนดชนิดของลูกค้าไปในไฟล์ values แทน เพื่อที่จะได้รู้ไปเลยว่าตกลงแล้วลูกค้านี้เนี่ยอยู่ในระดับใด และเวลาแก้ไขก็แก้ระดับก็แก้ทีค่าเดียวไปเลย

values.yaml

1
2
3
domain: "company-c.com"
owner: "NORMAL PROGRAMMER"
customerType : "VIP"

ในส่วนนี้เราจะเพิ่ม config value : customerType ขึ้นมาเพื่อบอกว่าลูกค้านี้อยู่ type อะไร

whoami.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-deployment
labels:
app: whoami
spec:
selector:
matchLabels:
app: whoami-app
template:
metadata:
labels:
app: whoami-app
spec:
containers:
- name: whoami-container
image: traefik/whoami
ports:
- containerPort: 80
env:
- name: "OWNER"
value: {{ .Values.owner }}
- name: "CUSTOMER_TYPE"
value: {{ .Values.customerType }}
- name: "MAX_MEMORY"
{{ if eq .Values.customerType "VIP" }}
value: "400MB"
{{ else if eq .Values.customerType "GOLD" }}
value: "300MB"
{{ else }}
value: "100MB"
{{ end }}
---
# ผมขอละการประกาศส่วน service กับ ingress นะครับ

จากตัวอย่างจะเห็นว่าเราทำการเพิ่มส่วน if else เข้าไป โดยตรง if eq .Values.customerType “VIP” เป็นเงื่อนไขที่ต้องการ ถ้าตรงจะให้ทำสิ่งนั้น ในที่นี้เราทำการตั้งเงื่อนไขว่า ถ้า customerType มีค่าเป็น VIP เราจะกำหนด value ของ maxMemory เป็น 400MB ในส่วนของ else if ก็ใช้หลักการเดียวกันแต่เปลี่ยนจาก VIP เป็น GOLD และส่วนที่เป็น else ก็คือถ้าไม่ตรงอะไรเลยก็เข้าเงื่อนไขนั้นซึ่งในที่นี้คือกำหนด memory เป็น 100MB

ทดสอบ Deploy

เมื่อเราลอง dpeloy และเข้าดูผ่าน browser ที่ url : http://company-c.com/?env=true ซึ่งเมื่อเข้าไปดูแล้วจะพบว่า maxMemory เป็น 400MB ตามเงื่อนไขที่เรากำหนด

คราวนี้เรามาลองเปลี่ยน config customerType ในไฟล์ values.yaml ดูว่าถ้าเปลี่ยนแล้วค่าจะเปลี่ยนตามไหม โดยผมจะลองเปลี่ยน custmoerType เป็น GOLD ซึ่งเมื่อเปลี่ยนแล้วลองไปเช็คดูจะพบว่าค่าเปลี่ยนเป็น 300MB ตามที่ตั้งค่าไว้

คราวนี้ลองเปลี่ยน customerType เป็น NORMAL และลอง deploy update จะพบว่าค่าเปลี่ยนเป็น 100MB

ซึ่งจากการทดลองจะเห็นว่าเราสามารถ if else ได้ตามความต้องการของเราแล้ว

loop

ในบางกรณีเราอยากจะวน loop ทำอะไรสักอย่าง ตัวอย่างเช่น ถ้าลูกค้าบางคนต้องการเพิ่ม environment เพิ่มเข้าไปเองเพื่อเอาไปใช้ ซึ่งแต่ละลูกค้ามี environment ที่ไม่เหมือนกันเลยนั้น เราจะทำอย่างไร ซึ่งด้วยความรู้ที่เรามีอยู่ตอนนี้เราไม่สามารถทำได้เลยเพราะ template นั้นเป็นค่า fix จะไปรู้ได้อย่างไรว่ามีค่า environment อะไรบ้าง มีกี่ตัว ตรงจุดนี้เองที่ loop จะเข้ามาช่วยเรา

values.yaml

1
2
3
4
5
6
7
8
domain: "company-c.com"
owner: "NORMAL PROGRAMMER"

customEnvironment:
CUSTOM_VALUE_1 : "WASINEE"
MY_TIMEZONE: "Asia/Bangkok"
MAX_RETRY: "5"
USERNAME: "TEST_USER"

ตรงส่วนนี้เราทำการเพิ่ม config : customEnvironment โดยภายใต้ customEnvironment นั้นเรามีการกำหนด environment ที่เราจะเพิ่มเข้าไปคือ CUSTOM_VALUE_1 , MY_TIMEZONE , MAX_RETRY, USERNAME

whoami.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
apiVersion: apps/v1
kind: Deployment
metadata:
name: whoami-deployment
labels:
app: whoami
spec:
selector:
matchLabels:
app: whoami-app
template:
metadata:
labels:
app: whoami-app
spec:
containers:
- name: whoami-container
image: traefik/whoami
ports:
- containerPort: 80
env:
- name: "OWNER"
value: {{ .Values.owner }}
{{ range $key, $value := .Values.customEnvironment }}
- name: "{{ $key }}"
value: "{{ $value }}"
{{ end }}
---
# ผมขอละการประกาศส่วน service กับ ingress นะครับ

ตรงส่วนนี้เราจะเพิ่มส่วนการ for loop เอาค่าไปใน environment โดยตรงส่วนที่เราประกาศว่า range $key, $value := .Values.customEnvironment ตรงส่วนนี้คือการบอกว่าจะทำการวน loop โดยวนที่ตัว customEnvironment ซึ่งภายในมีค่า

1
2
3
4
CUSTOM_VALUE_1 : "WASINEE"
MY_TIMEZONE: "Asia/Bangkok"
MAX_RETRY: "5"
USERNAME: "TEST_USER"

โดยตอนวนนั้นจะให้ค่า $key คือค่าที่เป็น key (ซึ่งนั่นก็คือ CUSTOM_VALUE_1 , MY_TIMEZONE , MAX_RETRY , USERNAME ) และค่า $value คือค่าที่เป็น value (ซึ่งนั่นก็คือ WASINEE , Asia/Bangkok , 5, TEST_USER) ดังนั้นเวลาวนค่าของ key value จะเป็น

1
2
3
4
- key : CUSTOM_VALUE_1  - value : WASINEE
- key : MY_TIMEZONE - value : Asia/Bangkok
- key : MAX_RETRY - value : 5
- key : USERNAME - value : TEST_USER

ซึ่งในส่วนที่ต่อมาคือส่วนที่เราเอาค่า key value ไปใช้ ในที่นี้คือการกำหนดค่า environment ของ pod นั่นเอง

ทดสอบ Deploy

เมื่อเราลอง dpeloy และเข้าดูผ่าน browser ที่ url : http://company-c.com/?env=true จะพบว่ามีค่า Environment เป็นไปตามที่เราใช้ loop กำหนดใน template

คราวนี้เรามาลองทดสอบเพิ่มค่าใน customEnvironment เหมือนด้านล่าง จากนั้นลองสั่ง Deploy

1
2
3
4
5
6
7
8
9
10
domain: "company-c.com"
owner: "NORMAL PROGRAMMER"

customEnvironment:
CUSTOM_VALUE_1 : "WASINEE"
CUSTOM_VALUE_2 : "PICHAYA"
CUSTOM_VALUE_3 : "SUNISA"
MY_TIMEZONE: "Asia/Bangkok"
MAX_RETRY: "5"
USERNAME: "TEST_USER"

ซึ่งจากภาพจะเห็นว่าค่า environment มีการเพิ่มตามที่เราเพิ่มในไฟล์ values.yaml จริงๆ ดังนั้นก็แปลว่าการประกาศ template แบบ loop ที่เราต้องการนั้นทำงานถูกต้อง

สรุป

สำหรับตอนนี้เราได้เรียนรู้การใช้ความสามารถของ Helm ในการใช้ if และ loop บนตัว template เพื่อให้สามารถทำการ deploy application ที่มีความซับซ้อนมากขึ้นได้แล้ว สำหรับตอนหน้าซึ่งน่าจะเป็นตอนสุดท้ายของซีรีย์ Basic Kubernetes เราจะมาเรียนรู้วิธีการ Rollback โดยใช้ Helm