+7

Sử dụng Helm Chart

Cài đặt:

#https://helm.sh/docs/intro/install/ 
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

Bash Complete for helm

yum install bash-completion -y  
helm completion bash > /etc/bash_completion.d/helm
Thoát session ssh và vào lại

P1: Làm quen Helm Chart

# Add Repo
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable --force-update
(Note: khi add repo, helm sẽ tạo file config tại ~/.config/helm/repositories.yaml)
helm repo list   #(liệt kê repo)
helm repo update   #(cập nhập repo)
helm search repo nginx   #(search nginx từ các repo đã add)
helm search repo nginx --versions

1.1 Tải helm chart từ ArtifactHub

https://artifacthub.io/ chứa rất nhiều helm được chia sẻ từ cộng đồng.

helm pull bitnami/nginx ; ls -la
helm pull bitnami/nginx --untar

1.2 Run first helm chart

- Chạy helm trực tiếp từ repo internet
# helm install first-chart1 bitnami/nginx -n tuanda --create-namespace
# helm ls -A
# helm ls -A --all

- Chạy helm từ folder đã pull về
# helm pull bitnami/nginx --untar ; ls -la
# cd nginx
# helm template first-chart2 . --namespace=tuanda  #(Kiểm tra helm)
# helm install first-chart2 . --namespace=tuanda --create-namespace  #(install nginx bitnami)
# helm ls -A  #(show helm chart deployed)

- Xóa helm chart
helm status first-chart2 -n tuanda
helm uninstall first-chart2 -n tuanda

1.3 Test Chart

Ta có 3 cách kiểm tra config helm đã đúng chưa:

cd nginx
helm template .
helm lint .
helm install nginx . --dry-run --debug

1.4 Show thông tin của chart trên ArtifactHub

helm show chart bitnami/nginx
helm show values bitnami/nginx

1.5 Liệt kê chart nào đang chạy

helm ls -n tuanda   #(-n là namespace)
helm ls -A

P2: Tự tạo Helm Chart

2.1 Tạo và chạy self chart

# helm create nginx-test2

> Cấu trúc thư mục helm như sau:
├── charts
├── Chart.yaml
├── templates (chứa toàn bộ thông tin file .yaml để deploy k8s)
│   ├── deployment.yaml (Chứa deployment k8s)
│   ├── _helpers.tpl (chứa teamplate / include)
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml (chứ tham số để thay vào file yaml trong thư mục template)

#Chạy 
helm template nginx-test2 . --namespace=tuanda
helm install nginx-test2 . -n tuanda  --create-namespace

2.2 Upgrade Chart

Nếu Chart yaml có update (ví dụ ta sửa configmap, thay đổi image deployment, tăng số pod scale...), ta apply chart mới như sau:

#Ta tăng số pod lên 5 (sửa mục 2.1) và thử chạy upgrade
(vim values.yaml và sửa replicaCount: 5)
helm upgrade nginx-test2 . -n tuanda
kubectl get pod -A (kết quả pod đã tăng lên 5)

2.3 Rollback Chart

$ helm history nginx-test2 -n tuanda
REVISION	UPDATED                 	STATUS    	CHART            	APP VERSION	DESCRIPTION     
1       	Sat Oct 15 10:57:24 2022	superseded	nginx-test2-0.1.0	1.16.0     	Install complete
2       	Sat Oct 15 10:59:37 2022	deployed  	nginx-test2-0.1.0	1.16.0     	Upgrade complete

$ helm rollback nginx-test2 -n tuanda (về bản trước đó)
$ helm rollback nginx-test2 1 -n tuanda (về bản chỉ định)

P3: .Values / .Chart

Để chuẩn bị cho các bài test từ phần 3,4... trở đi, ta thực hiện xóa vài thư mục sau

helm create nginx-test3
cd nginx-test3
rm -rf templates/*
cat /dev/null > values.yaml

# tạo 2 file MẪU
kubectl create configmap nginx-test3-cfg --from-literal=PORT=80 --dry-run=client -o yaml > templates/configmap.yaml
kubectl create deployment nginx-test3-dpl --image=nginx:alpine --replicas=2 --dry-run=client -o yaml > templates/deployment.yaml

VD1: Load tham số .Values từ values.yaml

B1: Chuẩn bị values.yaml

echo 'replicaCount: 5' > nginx-test3/values.yaml

B2: Sửa deployment.yaml

vi nginx-test3/templates/deployment.yaml
sửa
  replicas: 2
thành:
  replicas: {{ .Values.replicaCount }}

B3: Thực hiện chạy test

cd nginx-test3
helm template nginx-test3 .

B4: Kết quả

Replicas đã được ghi đè từ 2 lên 5 khi chạy helm template (hoặc install/upgrade)

VD2: Load tham số .Chart từ Chart.yaml

B1: Sửa values.yaml để thêm image nginx

# vi nginx-test3/values.yaml
replicaCount: 2
image:
  repository: nginx:alpine

B2: Sửa deployment.yaml thay labels

# vi nginx-test3/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: {{ .Chart.Name }}-dpl
  name: {{ .Chart.Name }}-dpl
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Chart.Name }}-dpl
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: {{ .Chart.Name }}-dpl
    spec:
      containers:
      - image: {{ .Values.image.repository }}
        name: {{ .Chart.Name }}
        resources: {}

B3: Thực hiện chạy test

cd nginx-test3
helm template nginx-test3 .

B4: Kết quả

Ngoài ra, ta còn có một số Values, Chart build-in "có sẵn" thường hay sử dụng:

Release.Name
Chart.Name
Chart.ApiVersion
...
URL: https://helm.sh/docs/chart_template_guide/builtin_objects/

P4: Function và Pipeline

Các Function helm ta có thể tìm ở đây: https://helm.sh/docs/chart_template_guide/function_list/#string-functions

VD1: Function

B1: Kiểm tra lại file file values.yaml và Chart.yaml

# vim nginx-test3/values.yaml
replicaCount: 2
image:
  repository: nginx:alpine
-----------------
#vim nginx-test3/Chart.yaml
apiVersion: v2
name: nginx-test3
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.16.0"
  

B2: Sửa deployment.yaml. Áp dụng function: upper, title, replace, camelcase...

# vi nginx-test3/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: {{ upper .Chart.Name }}-dpl
  name: {{ title .Chart.Name }}-dpl
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ replace "nginx" "test" .Chart.Name }}-dpl
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: {{ camelcase  .Chart.Name }}-dpl
    spec:
      containers:
      - image: {{ .Values.image.repository }}
        name: {{ .Chart.Name }}
        resources: {}

B3: Thực hiện chạy test

cd nginx-test3
helm template nginx-test3 .

B4: Kết quả

VD2: Pipeline

Pipeline có kêt quả tương tự như function, ta có thể xem ví dụ dưới đây về upper, title, replace, camelcase...

# vi nginx-test3/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: {{ .Chart.Name | upper }}-dpl
  name: {{ .Chart.Name | title }}-dpl
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Chart.Name | replace "nginx" "test" }}-dpl
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: {{  .Chart.Name | camelcase }}-dpl
    spec:
      containers:
      - image: {{ .Values.image.repository }}
        name: {{ .Chart.Name }}
        resources: {}

B3: Thực hiện chạy test

cd nginx-test3
helm template nginx-test3 .

Kết quả:

P5: IF

Chức năng: (1) so sánh, (2) Nếu exist sẽ in ra

VD1: Kiểm tra nếu tồn tại sẽ in ra

B1: File values.yaml

replicaCount: 5

B2: Sửa deployment.yaml

spec:
  {{- if .Values.replicaCount }}
  replicas: {{ .Values.replicaCount }}
  {{- end }}

B3: Kết quả (Nếu tồn tại replicaCount sẽ in ra)

VD2: Các ví dụ so sánh về IF

{{- if and (eq $.Values.service.type "NodePort") .Values.nodePort }}
> nếu service.type là NodePort -VÀ- nodePort=8080 tồn tại thì thực hiện ...

{{- if eq (include "paperless.trash.enabled" .) "true" }}
> nếu template paperless.trash.enabled được khai báo thì thực hiện ...

{{- if or .Values.serverBlock .Values.existingServerBlockConfigmap }}
> nếu tồn tại 1 trong 2 value thì thực hiện ...

{{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }}
> nếu svc khai báo là "LoadBalancer hoặc NodePort" thì thực hiện ...

{{- if and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http)) }}
      nodePort: {{ .Values.service.nodePorts.http }}
      {{- end }}

P6: With

Chức năng:

  • Dùng để rút gọn Chart.
  • Kiểm tra tồn tại nếu có thì insert., nếu ko có thì xóa (giống IF).
  • Dùng để load 1 list string vào trong Chart.

VD1: Rút gọn Chart

B1: File values.yaml

app:
  mobile:
    account: taikhoan
    password: matkhau
  db:
    max: 15
    min: 5

B2: File configmap.yaml khi chưa sửa

apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data:
  account: {{ .Values.app.mobile.acc }}
  password: {{ .Values.mobile.ui.pwd }}
  max: {{ .Values.app.db.max }}
  min: {{ .Values.app.db.min }}

B3: Sửa configmap.yaml rút gọn ".Values.app." đưa vào with

apiVersion: v1
kind: ConfigMap
metadata:
  name: test
data:
  {{- with .Values.app. }}
  account: {{ .mobile.account }}
  password: {{ .mobile.password }}
  max: {{ .db.max }}
  min: {{ .db.min }}

B4: Kết quả

VD2: kiểm tra tồn tại nếu có thì insert., nếu ko có thì xóa (giống IF)

B1: File values.yaml

pod:
  labels:
    app: test

B2: Sửa deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  {{- with .Values.pod.labels }}
  labels:
    {{ toYaml . }}
  {{- end }}
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test
  strategy: {}
  template:
    metadata:
      {{- with .Values.pod.labels }}
      labels:
        {{ toYaml . }}
      {{- end }}
    spec:
      containers:
      - image: nginx
        name: nginx     

B3: Kết quả

P7: Range (for i)

Range gần giống như with để load values ra, nhưng sử dụng cho array values. Ta có thể xem ví dụ sau

VD1: Range sử dụng để fill array list

B1: File values.yaml

configMapReload:
  #extraArgs: []
  extraArgs:
    - --webhook-method HEAD
    - --webhook-retries 5

B2: Sửa deployment.yaml

          args:
            - --webhook-url=http://127.0.0.1:{{ .Values.ports.http.port }}/-/reload
          {{- range $i, $val := .Values.configMapReload.extraArgs }}
            - {{ $val }}
          {{- end }}

B3: Kết quả

          args:
            - --webhook-url=http://127.0.0.1:9090/-/reload
            - --webhook-method HEAD
            - --webhook-retries 5

VD2: Range with multi values

B1: File values.yaml

env:
  # -- Timezone for the container.
  - name: TZ
    value: UTC
  - name: VN
    value: GMT

B2: Sửa deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: test
  name: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: test
  strategy: {}
  template:
    metadata:
      labels:
        app: test
    spec:
      containers:
      - image: nginx
        name: nginx
        env:
        {{- range $i, $val := .Values.env }}
        - name: {{ $val.name | quote }}
          value: {{ $val.value | quote }}
        {{- end }}

B3: Kết quả

VD3: Range without $val

B1: File values.yaml

configMapReload:
  extraConfigMapMounts:
    - name: alerts
      configMap: prometheus-alerts
      mountPath: /etc/alerts
      subPath: 'test'

B2: Sửa deployment.yaml

        {{- range .Values.configMapReload.extraConfigMapMounts }}
        - name: {{ .name }}
          configMap:
            name: {{ .configMap }}
        {{- end }}

B3: Kết quả

        - name: alerts
          configMap:
            name: prometheus-alerts

P8: Include/Template

helm create self-chart

B1: File _helper.tpl

{{- define "self-chart.labels" -}}
helm.sh/chart: {{ include "self-chart.chart" . }}
{{ include "self-chart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

B2: Trong deployment.yaml có gọi include

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "self-chart.fullname" . }}
  labels:
    {{- include "self-chart.labels" . | nindent 4 }}
spec:

B3: Kết quả

apiVersion: apps/v1
kind: Deployment
metadata:
  name: release-name-nginx-test3
  labels:
    helm.sh/chart: nginx-test3-0.1.0
    app.kubernetes.io/name: nginx-test3
    app.kubernetes.io/instance: release-name
    app.kubernetes.io/version: "1.16.0"
    app.kubernetes.io/managed-by: Helm
spec:

P9: Print function

B1: File values.yaml

configProperties:
  codeString: dynamic

B2: Sửa configmap.yaml

apiVersion: v1
kind: ConfigMap
data:
  TEST: {{ printf "static-%s" (.Values.configProperties.codeString) -}} 

B3: Kết quả

P10: Default

B1: File values.yaml

imageName: tomcat

B2: Sửa deployment.yaml

    spec:
      containers:
      - image: {{- default "nginx" .Values.imageName }}
        name: {{- default "nginx" .Values.imageName }}
        resources: {}

B3: Kết quả

Các bạn có thể tham khảo video của Bizfly khá hay về helm https://www.facebook.com/BizflyCloud.VCCorp/videos/2205618102920117

Bài viết trong phạm vi kiến thức của người viết, có thể các bạn có idea hay hơn, xin hướng dẫn. Cảm ơn!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí