Helm3 - 入門 === ###### tags: `K8s / Helm` ###### tags: `Kubernetes`, `k8s`, `Helm Chart`, `HelmChart` <br> ![](https://i.imgur.com/pvq0pZ5.png =35%x) [TOC] <br> ## Helm 官網 - 英文 - https://helm.sh/docs/intro/using_helm/ - 中文 - https://helm.sh/zh/docs/topics/charts/ <br> <hr> <br> ## 前言 ### Helm - 管理 K8s Chart 套件的工具 ### Chart - 預先配置好的 K8s 資源物件集合 ### [輔助] K8s 的 debug 資源 [HackMD筆記] - [K8s / Hello World](/WTFM-2OsRXK-tW-YwKWzzg) - [K8s / 指令集](/kD5ynMNsRH-TWq9KUwXfCQ) <br> <hr> <br> ## 安裝 Helm ### 安裝 Helm3 (Helm v3) - [[NVIDIA] Install NVIDIA GPU Operator / Install Helm](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/getting-started.html#install-helm) ```bash curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 \ && chmod 700 get_helm.sh \ && ./get_helm.sh ``` - ### 參數說明: | 參數 | 說明 | |-----|------| | `-f` | **Fail silently (on HTTP errors)**:如果 HTTP 回應狀態碼是 400 以上的錯誤,不會輸出錯誤訊息,也不會將錯誤 HTML 顯示出來。適合在腳本中使用。 | | `-s` | **Silent mode**:不顯示任何進度條或錯誤訊息(除非搭配 `-f` 時有特殊行為)。這樣可以讓輸出更乾淨。| | `-S` | **Show error**:與 `-s` 搭配使用時,會在失敗時顯示錯誤訊息。 | | `-L` | **Location**:如果 URL 回傳的是 3xx 的重新導向,會自動跟隨新的位置。 | | `-o get_helm.sh` | 將下載的內容輸出到名為 `get_helm.sh` 的檔案中(output to file)。| - 沒有 `-s` 會有底下 verbose log ``` % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 11913 100 11913 0 0 59703 0 --:--:-- --:--:-- --:--:-- 59864 ``` - ### 綜合解釋: 這條指令的意思是: > 使用 `curl` 靜默且安全地下載 Helm 安裝腳本,如果有重新導向也會跟過去,並將檔案儲存成 `get_helm.sh`,接著給它執行權限,然後執行這個腳本。 這樣的寫法常用在自動化腳本中,避免不必要的輸出干擾使用者或其他工具的判斷。 <br> ## Hello World > 預設的 image 樣板範例為 nginx (port:80) - 建立 Chart 參考樣板 ```bash= $ helm create tj-helm-for-nginx Creating tj-helm-for-nginx ``` - 查看檔案結構 ```bash= $ tree . └── tj-helm-for-nginx ├── Chart.yaml <--- 紀錄 Chart 的版本、名稱、描述 ├── charts <--- 放置 sub charts ├── templates <--- K8s 資源物件定義 │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ └── test-connection.yaml └── values.yaml <--- 定義 K8s 資源物件的參數,要帶入到 templates 中 4 directories, 10 files ``` - 切到 剛建立出來的 Chart 目錄 ```bash= $ cd tj-helm-for-nginx/ ``` - 查看要佈署到 K8s 的樣板: deployment.yaml ```bash= $ cat templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "tj-helm-for-nginx.fullname" . }} labels: {{- include "tj-helm-for-nginx.labels" . | nindent 4 }} spec: {{- if not .Values.autoscaling.enabled }} replicas: {{ .Values.replicaCount }} ... ``` - 可以看到:很多的「**參數代碼 {{ ... }}**」 - 這些參數,將由 values.yaml 餵入 - 其他檔案,以此類推 <br> - 查看 K8s 資源物件的參數:```values.yaml``` ```bash= $ cat values.yaml # Default values for tj-helm-for-nginx. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 image: repository: nginx pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "" ... ``` - 可以看到:很多的「參數」 - 預設是使用 nginx 這個 web app,port 使用 80 <br> - 將當前目錄下的 Chart 安裝到 K8s ```bash= # 查詢已安裝的 Chart (helm list 或 helm ls) $ helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION # 將當前目錄下的 Chart,安裝到 K8s ## helm 2 $ helm install . # 或是 $ helm install . -n tj-helm-demo1 $ helm install -n tj-helm-demo1 . ## helm 3 $ helm install tj-helm-demo1 . NAME: tj-helm-demo1 LAST DEPLOYED: Tue Dec 1 17:30:24 2020 NAMESPACE: helm-lab STATUS: deployed REVISION: 1 NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace helm-lab -l "app.kubernetes.io/name=tj-helm-for-nginx,app.kubernetes.io/instance=tj-helm-demo1" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace helm-lab port-forward $POD_NAME 8080:80 # 查詢已安裝的 Chart (helm list 或 helm ls) $ helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION tj-helm-demo1 helm-lab 1 2020-12-01 17:30:24.483291444 +0800 CST deployed tj-helm-for-nginx-0.1.01.16.0 ``` - 測試佈署到 K8s 的結果 ```bash= $ kubectl get pods NAME READY STATUS RESTARTS AGE tj-helm-demo1-tj-helm-for-nginx-9f5b9949d-nmbzf 1/1 Running 0 7m33s $ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES tj-helm-demo1-tj-helm-for-nginx-9f5b9949d-nmbzf 1/1 Running 0 8m45s 10.244.1.3 tj-cluster-worker2 <none> <none> ``` - 測試 pod 的連線 ```bash= # 安裝完 Chart 後,最後三行會顯示連線資訊 export POD_NAME=$(kubectl get pods --namespace helm-lab -l "app.kubernetes.io/name=tj-helm-for-nginx,app.kubernetes.io/instance=tj-helm-demo1" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace helm-lab port-forward $POD_NAME 8080:80 ``` - 執行「上述三行指令」的過程: [![](https://i.imgur.com/lgbng5c.png)](https://i.imgur.com/lgbng5c.png) <br> - 開啟另一個 terminal 測試連線 ``` $ curl -X GET 127.0.0.1:8080 ``` [![](https://i.imgur.com/of8clcy.png)](https://i.imgur.com/of8clcy.png) ![](https://i.imgur.com/tzSi2Tt.png) <br> - 刪除佈署到 K8s 的 Chart ```bash= $ helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION tj-helm-demo1 helm-lab 1 2020-12-01 17:30:24.483291444 +0800 CST deployed tj-helm-for-nginx-0.1.0 1.16.0 $ helm delete --purge tj-helm-demo1 release "tj-helm-demo1" uninstalled $ helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION $ kubectl get pods No resources found in helm-lab namespace. ``` - 測試沒問題,就將當前的 Chart 目錄,打包成壓縮檔 (tgz 檔) ```bash= # This command packages a chart into a versioned chart archive file. # If a path is given, this will look at that path for a chart # (which must contain a Chart.yaml file) and then package that directory. $ helm package . Successfully packaged chart and saved it to: .../tj-helm-for-nginx/tj-helm-for-nginx-0.1.0.tgz $ ll total 32 drwxr-xr-x 4 ubuntu ubuntu 4096 Dec 1 17:54 ./ drwxrwxr-x 3 ubuntu ubuntu 4096 Dec 1 17:15 ../ -rw-r--r-- 1 ubuntu ubuntu 349 Dec 1 17:15 .helmignore -rw-r--r-- 1 ubuntu ubuntu 1108 Dec 1 17:15 Chart.yaml drwxr-xr-x 2 ubuntu ubuntu 4096 Dec 1 17:15 charts/ drwxr-xr-x 3 ubuntu ubuntu 4096 Dec 1 17:15 templates/ -rw-rw-r-- 1 ubuntu ubuntu 3589 Dec 1 17:54 tj-helm-for-nginx-0.1.0.tgz <--- -rw-r--r-- 1 ubuntu ubuntu 1810 Dec 1 17:15 values.yaml ``` - 可將打包好的 tgz 檔,進行佈署到其他節點 ``` # helm 3 $ helm install tj-helm-demo2 tj-helm-for-nginx-0.1.0.tgz $ helm install tj-helm-demo3 tj-helm-for-nginx-0.1.0.tgz $ helm install tj-helm-demo4 tj-helm-for-nginx-0.1.0.tgz $ helm ls NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION tj-helm-demo2 helm-lab 1 2020-12-01 17:59:34.291777489 +0800 CST deployed tj-helm-for-nginx-0.1.0 1.16.0 tj-helm-demo3 helm-lab 1 2020-12-01 18:01:37.284712894 +0800 CST deployed tj-helm-for-nginx-0.1.0 1.16.0 tj-helm-demo4 helm-lab 1 2020-12-01 18:01:42.366486885 +0800 CST deployed tj-helm-for-nginx-0.1.0 1.16.0 $ kubectl get pods NAME READY STATUS RESTARTS AGE tj-helm-demo2-tj-helm-for-nginx-777d9c67d7-4cnwh 1/1 Running 0 2m15s tj-helm-demo3-tj-helm-for-nginx-86654488-7bd78 1/1 Running 0 12s tj-helm-demo4-tj-helm-for-nginx-549df6d677-tkzzg 1/1 Running 0 7s ``` - 每一次的佈署,都會產生新的 instance (實例) - K8s 與 Java 有異曲同工之妙 | Java | K8s | | ------------- | --------------- | | 類別(class) / 多個物件(object) | 資源物件(resource object) / 實體(instance) | | my-utils-**v1**.jar | apiVersion: **v1** | | package **a.b.c** | metadata:<br>&nbsp;&nbsp;namespace: **a.b.c** | | class **Abc** extends **SomeClass** | kind: **SomeClass**<br>metadata:<br>&nbsp;&nbsp;name: **Abc** | | 欄位(fields) | 後設資料(metadata) | | 方法(method) | 技術規格(spec) | <br> - 參考資料 - [Kubernetes 基礎教學(三)Helm 介紹與建立 Chart]() <br> <hr> <hr> <br> ## Hello World 2 (v2 & v3) - with NodePort - 指令 ```bash # 建立 Chart 參考樣板 $ helm create tj-helm-for-nginx2 ``` ```bash # 進入 Chart 根目錄 $ cd tj-helm-for-nginx2 ``` ```bash # 到 service.yaml 中,新增 nodePort 樣板 # nodePort: {{ .Values.service.nodePort }} $ nano templates/service.yaml ``` - service.yaml 變更前 ```yaml ports: - port: {{ .Values.service.port }} targetPort: http protocol: TCP name: http ``` - service.yaml 變更後 ```yaml ports: - port: {{ .Values.service.port }} nodePort: {{ .Values.service.nodePort }} # <--- targetPort: http protocol: TCP name: http ``` ```bash # 到 values.yaml 中,新增 nodePort 參數 $ nano values.yaml ``` - values.yaml 變更前 ```yaml service: type: ClusterIP port: 80 ``` - values.yaml 變更後 ```yaml service: type: NodePort # <--- nodePort: 30080 # <--- port: 80 ``` ```bash # 將當前目錄下的 Chart 安裝到 K8s $ helm install tj-helm-for-nginx-demo2 . ``` - 連線測試 http://192.168.34.8:30080 http://203.145.218.3:30080/ (若有公開 IP 的話) - 若沒問題,就可以打包 Chart,並測試 chart 檔(壓縮檔) ```bash # 刪除已經佈署的 Chart $ helm ls $ helm delete tj-helm-for-nginx-demo2 $ helm ls # 打包成 Chart $ helm package . # 安裝 Chart 檔 $ helm install tj-helm-for-nginx-demo2 tj-helm-for-nginx2-0.1.0.tgz # 可用 tar -xvcf xxx.tgz 解壓縮 # 查看佈署結果 $ helm ls $ kubectl get pods -o wide $ kubectl get services -o wide ``` <br> <hr> <hr> <br> ## Hello World 3 (v2 & v3) - with Ingress - 指令 ```bash # 建立 Chart 參考樣板 $ helm create tj-helm-for-ingress3 ``` ```bash # 進入 Chart 根目錄 $ cd tj-helm-for-ingress3 ``` --- ```bash # 到 values.yaml 中,新增 nodePort 參數 $ nano values.yaml ``` - 差異性 (變更前 v.s. 變更後) ```diff image: - repository: nginx + repository: hcwxd/blue-whale pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. - tag: "" + tag: "latest" +containerPort: 3000 ingress: - enabled: false + enabled: true - annotations: {} + annotations: # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" + nginx.ingress.kubernetes.io/rewrite-target: / hosts: - - host: chart-example.local - paths: [] + - paths: ["/blue"] ``` - 注意:host 要拿掉 不然綁訂了 host name,就無法用 IP 存取, 會出現 502 Bad Gateway,例如 ``` $ kubectl get ing Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress NAME CLASS HOSTS ADDRESS PORTS AGE tjdemo3-tj-helm-for-ingress3 <none> chart-example.local 10.98.112.86 80 74s $ curl 10.98.112.86/blue <html> <head><title>502 Bad Gateway</title></head> <body> <center><h1>502 Bad Gateway</h1></center> <hr><center>nginx/1.17.8</center> </body> </html> ``` --- ```bash # 到 depoyment.yaml 中,新增 containerPort 參數 $ nano templates/deployment.yaml ``` - 差異性 (變更前 v.s. 變更後) ```diff ports: - name: http - containerPort: 80 + containerPort: {{ .Values.containerPort }} protocol: TCP ``` --- ```bash # 將當前目錄下的 Chart 安裝到 K8s $ helm install tjdemo3 . ``` - 連線測試1: 測試內部的 ingress ``` $ kubectl get ing Warning: extensions/v1beta1 Ingress is deprecated in v1.14+, unavailable in v1.22+; use networking.k8s.io/v1 Ingress NAME CLASS HOSTS ADDRESS PORTS AGE tjdemo3-tj-helm-for-ingress3 <none> * 10.98.112.86 80 16m $ curl 10.98.112.86:80/blue ``` - 連線測試2: 測試對外的 ingress ``` $ kubectl get svc -o wide --all-namespaces $ kubectl get svc -o wide -n ingress-nginx NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR ingress-nginx NodePort 10.98.112.86 <none> 80:30511/TCP,443:30152/TCP 4d3h app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx $ curl 127.0.0.1:30511/blue ``` http://203.145.218.3:30511/blue (若有公開 IP 的話) - 若沒問題,就可以打包 Chart,並測試 chart 檔(壓縮檔) ```bash # 刪除已經佈署的 Chart $ helm ls $ helm delete tj-helm-for-ingress3 $ helm ls # 打包成 Chart $ helm package . # 安裝 Chart 檔 $ helm install tj-helm-for-ingress3 tj-helm-for-ingress3 -0.1.0.tgz # 可用 tar -xvcf xxx.tgz 解壓縮 # 查看佈署結果 $ helm ls $ kubectl get pods -o wide $ kubectl get services -o wide ``` <br> <hr> <hr> <br> - [[Helm] Helm v3 使用簡介 -- 小信豬的原始部落](https://godleon.github.io/blog/DevOps/Helm-v3-Chart-Template-Guide/) ## [[helm 2][小信豬的原始部落] 什麼是 Kubernetes Helm?](https://godleon.github.io/blog/Kubernetes/k8s-Helm-Introduction/) - **Helm** is a tool for managing Kubernetes charts. **Helm** 是管理 K8s Chart 的工具 - **Charts** are packages of pre-configured Kubernetes resources. **Charts** 是預先配置好 K8s 資源的軟體套件 <br> - Helm 就有點像是 Ubuntu 中的 APT 系統 - Chart 是多個 k8s resource object configuration 的集合 ### 安裝 Helm client ``` $ wget https://storage.googleapis.com/kubernetes-helm/helm-$(curl -s https://api.github.com/repos/helm/helm/releases/latest | jq --raw-output '.tag_name')-linux-amd64.tar.gz -O helm-linux-amd64.tar.gz $ tar -zxvf helm-linux-amd64.tar.gz $ sudo mv linux-amd64/helm /usr/local/bin/helm ``` ### 將 Helm 佈署至 Cluster Level - [helm init is not recognized #6996](https://github.com/helm/helm/issues/6996) ![](https://i.imgur.com/dpDAvjH.png) ### 更新 Helm Repo (v3) ```bash $ helm repo update # Usage: helm search [command] # Available Commands: # - hub search for charts in the Helm Hub or an instance of Monocular # - repo search repositories for a keyword in charts $ helm search repo $ helm search repo | grep nginx ingress-nginx/ingress-nginx 3.12.0 0.41.2 Ingress controller for Kubernetes using NGINX a... stable/nginx-ingress 1.41.3 v0.34.1 DEPRECATED! An nginx Ingress controller that us... stable/nginx-ldapauth-proxy 0.1.6 1.13.5 DEPRECATED - nginx proxy with ldapauth stable/nginx-lego 0.3.1 Chart for nginx-ingress-controller and kube-lego ``` ### helm command ```bash= # 取得最新的 chart 資訊 $ helm repo update # 搜尋 helm charts (會出現很多 charts info) $ helm search -l # 安裝 mysql helm chart (必要時,好像要加上 sudo ?) $ sudo helm install stable/mysql # 刪除佈署 $ helm delete wayfaring-butterfly --purge # 列出所有的佈署 $ helm list -a # helm ls -a ``` ### 小節複習 - Helm 是什麼? - Helm 是一項工具,是什麼工具? - 用來管理 K8s Charts 的工具 - 簡單來講,Helm 就如同 Ubuntu 的 apt 系統 - Helm 可以將一個或多個應用打包成一個服務,方便佈署到 K8s 上 - Charts 是什麼? - Charts 是一種軟體套件,是什麼樣的軟體套件? - 預先配置好 K8s 資源的的軟體套件 <br> ## Helm v.s. Helm-based Operator - Helm - K8s 的 Chart 套件管理員 - 透過 Helm 工具,將 Chart 佈署到 K8s ```helm install -n release_name path_to_chart``` - Helm-based Operator - 利用 K8s 的 CRD 機制 - operator-sdk 工具提供 "helm-based operator" 功能 可將 Helm Chart 資源轉成 operator - 透過 kubectl apply -f xxx.yaml 方式部署 <br> ## 參考資料 ### Nginx - [Nginx: Installation with Helm](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-helm/) ### Prometheus - [Installing the Prometheus-Operator on Kubernetes with Helm 3](http://www.dcasati.net/posts/installing-prometheus-on-kubernetes-v1.16.9/) - [Install prometheus-operator doesn't work on AWS EC2 keeps produce “Error: failed to download ”stable/prometheus-operator"](https://stackoverflow.com/questions/64226913/install-prometheus-operator-doesnt-work-on-aws-ec2-keeps-produce-error-failed) ``` $ helm install prometheus-community/prometheus-operator --generate-name --namespace monitor WARNING: This chart is deprecated manifest_sorter.go:192: info: skipping unknown hook: "crd-install" manifest_sorter.go:192: info: skipping unknown hook: "crd-install" manifest_sorter.go:192: info: skipping unknown hook: "crd-install" manifest_sorter.go:192: info: skipping unknown hook: "crd-install" manifest_sorter.go:192: info: skipping unknown hook: "crd-install" manifest_sorter.go:192: info: skipping unknown hook: "crd-install" NAME: prometheus-operator-1607335590 LAST DEPLOYED: Mon Dec 7 18:06:34 2020 NAMESPACE: monitor STATUS: deployed REVISION: 1 NOTES: DEPRECATED - This chart will be renamed. See https://github.com/prometheus-community/community/issues/28#issuecomment-670406329 --- The Prometheus Operator has been installed. Check its status by running: kubectl --namespace monitor get pods -l "release=prometheus-operator-1607335590" Visit https://github.com/coreos/prometheus-operator for instructions on how to create & configure Alertmanager and Prometheus instances using the Operator. $ kubectl --namespace monitor get pods -l "release=prometheus-operator-1607335590" NAME READY STATUS RESTARTS AGE prometheus-operator-160733-operator-589476996d-5nlxb 2/2 Running 0 32s prometheus-operator-1607335590-prometheus-node-exporter-fbxnb 1/1 Running 0 32s prometheus-operator-1607335590-prometheus-node-exporter-ngdhk 1/1 Running 0 32s ``` - [[GitHub] prometheus-community / helm-charts](https://github.com/prometheus-community/helm-charts/) - helm repo ``` $ helm repo add prometheus-community https://prometheus-community.github.io/helm-charts ``` - charts 資源列表 https://github.com/prometheus-community/helm-charts/tree/main/charts - Install Charts ``` $ helm install [RELEASE_NAME] prometheus-community/prometheus ``` - 參考資料 - [prometheus 12.0.2 · prometheus/prometheus-community](https://artifacthub.io/packages/helm/prometheus-community/prometheus) ### Others - [How To Install Software on Kubernetes Clusters with the Helm 3 Package Manager](https://www.digitalocean.com/community/tutorials/how-to-install-software-on-kubernetes-clusters-with-the-helm-3-package-manager)