Thứ Sáu, 21 tháng 10, 2022

Sử dụng Helm Chart

 Cài đặt:

#https://helm.sh/docs/intro/install/ 
curl -k -O https://get.helm.sh/helm-canary-linux-amd64.tar.gz
tar -xvzf helm-canary-linux-amd64.tar.gz
cd linux-amd64/
mv helm /usr/bin/
chmod 755 /usr/bin/helm

#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)

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
helm pull bitnami/nginx --untar

1.2 Run 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

- Chạy helm từ folder đã pull về
# helm pull bitnami/nginx --untar
# 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

- 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 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 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)

2.2 Upgrade Chart

Nếu Chart yaml có update (ví dụ thêm biến ở configmap, thay đổi image deployment), ta chạy như sau:

helm template nginx-test2 . --namespace=tuanda
helm install nginx-test2 . -n tuanda

#Ta tăng số pod lên 5 và thử chạy upgrade
(vim values.yaml và sửa replicaCount: 5)
helm upgrade nginx-test2 . -n tuanda

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' > values.yaml

B2: Sửa deployment.yaml

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

B3: 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: values.yaml

replicaCount: 2
image:
  repository: nginx:alpine

B2: Sửa 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: Kết quả

Ngoài ra, ta còn có một số Values, chart build-in có sẵn 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: Sửa file values.yaml và Chart.yaml

# vim values.yaml
replicaCount: 2
image:
  repository: nginx:alpine
-----------------
#vim 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...

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: 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...

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: {}

Kết quả:

P5: IF

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

VD1: Kiểm tra tồn tại bằng if

B1: File values.yaml

replicaCount: 5

B2: Sửa deployment.yaml

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

B3: Kết quả

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!

Ứng cứu khi chown -R user1:user1 /etc

1. Bài toán Gõ nhầm: chown -R user1:user1 /etc 2. Giải: Cách 1: Tìm bản backup /etc cũ (tỉ lệ phục hồi gần như ~100%) Cách 2: Tìm tạm 1 thư ...