helm簡介、安裝、應用
Helm 是 Kubernetes 生態系統中的一個軟體包管理工具。本文將介紹 Helm 中的相關概念和基本工作原理,並通過一個具體的示例學習如何使用 Helm 打包、分發、安裝、升級及回退 Kubernetes 應用。
Kubernetes 應用部署的挑戰
Kubernetes 是一個提供了基於容器的應用叢集管理解決方案,Kubernetes 為容器化應用提供了部署執行、資源排程、服務發現和動態伸縮等一系列完整功能。
Kubernetes 的核心設計理念是: 使用者定義要部署的應用程式的規則,而 Kubernetes 則負責按照定義的規則部署並執行應用程式。如果應用程式出現問題導致偏離了定義的規格,Kubernetes 負責對其進行自動修正。例如:定義的應用規則要求部署兩個例項(Pod),其中一個例項異常終止了,Kubernetes 會檢查到並重新啟動一個新的例項。
使用者通過使用 Kubernetes API 物件來描述應用程式規則,包括 Pod、Service、Volume、Namespace、ReplicaSet、Deployment、Job等等。一般這些資源物件的定義需要寫入一系列的 YAML 檔案中,然後通過 Kubernetes 命令列工具 Kubectl 調 Kubernetes API 進行部署。
以一個典型的三層應用 Wordpress 為例,該應用程式就涉及到多個 Kubernetes API 物件,而要描述這些 Kubernetes API 物件就可能要同時維護多個 YAML 檔案。
從上圖可以看到,在進行 Kubernetes 軟體部署時,我們面臨下述幾個問題:
- 如何管理、編輯和更新這些這些分散的 Kubernetes 應用配置檔案。
- 如何把一套相關的配置檔案作為一個應用進行管理。
- 如何分發和重用 Kubernetes 的應用配置。
Helm 的出現就是為了很好地解決上面這些問題。
Helm 是什麼?
Helm 是 Deis 開發的一個用於 Kubernetes 應用的包管理工具,主要用來管理 Charts。有點類似於 Ubuntu 中的 APT 或 CentOS 中的 YUM。
Helm Chart 是用來封裝 Kubernetes 原生應用程式的一系列 YAML 檔案。可以在你部署應用的時候自定義應用程式的一些 Metadata,以便於應用程式的分發。
對於應用釋出者而言,可以通過 Helm 打包應用、管理應用依賴關係、管理應用版本併發布應用到軟體倉庫。
對於使用者而言,使用 Helm 後不用需要編寫複雜的應用部署檔案,可以以簡單的方式在 Kubernetes 上查詢、安裝、升級、回滾、解除安裝應用程式。
Helm 元件及相關術語
- Helm
Helm 是一個命令列下的客戶端工具。主要用於 Kubernetes 應用程式 Chart 的建立、打包、釋出以及建立和管理本地和遠端的 Chart 倉庫。
- Tiller
Tiller 是 Helm 的服務端,部署在 Kubernetes 叢集中。Tiller 用於接收 Helm 的請求,並根據 Chart 生成 Kubernetes 的部署檔案( Helm 稱為 Release ),然後提交給 Kubernetes 建立應用。Tiller 還提供了 Release 的升級、刪除、回滾等一系列功能。
- Chart
Helm 的軟體包,採用 TAR 格式。類似於 APT 的 DEB 包或者 YUM 的 RPM 包,其包含了一組定義 Kubernetes 資源相關的 YAML 檔案。
- Repoistory
Helm 的軟體倉庫,Repository 本質上是一個 Web 伺服器,該伺服器儲存了一系列的 Chart 軟體包以供使用者下載,並且提供了一個該 Repository 的 Chart 包的清單檔案以供查詢。Helm 可以同時管理多個不同的 Repository。
- Release
使用 helm install
命令在 Kubernetes 叢集中部署的 Chart 稱為 Release。
注:需要注意的是:Helm 中提到的 Release 和我們通常概念中的版本有所不同,這裡的 Release 可以理解為 Helm 使用 Chart 包部署的一個應用例項。
Helm 工作原理
這張圖描述了 Helm 的幾個關鍵元件 Helm(客戶端)、Tiller(伺服器)、Repository(Chart 軟體倉庫)、Chart(軟體包)之間的關係。
Chart Install 過程
- Helm 從指定的目錄或者 TAR 檔案中解析出 Chart 結構資訊。
- Helm 將指定的 Chart 結構和 Values 資訊通過 gRPC 傳遞給 Tiller。
- Tiller 根據 Chart 和 Values 生成一個 Release。
- Tiller 將 Release 傳送給 Kubernetes 用於生成 Release。
Chart Update 過程
- Helm 從指定的目錄或者 TAR 檔案中解析出 Chart 結構資訊。
- Helm 將需要更新的 Release 的名稱、Chart 結構和 Values 資訊傳遞給 Tiller。
- Tiller 生成 Release 並更新指定名稱的 Release 的 History。
- Tiller 將 Release 傳送給 Kubernetes 用於更新 Release。
Chart Rollback 過程
- Helm 將要回滾的 Release 的名稱傳遞給 Tiller。
- Tiller 根據 Release 的名稱查詢 History。
- Tiller 從 History 中獲取上一個 Release。
- Tiller 將上一個 Release 傳送給 Kubernetes 用於替換當前 Release。
Chart 處理依賴說明
Tiller 在處理 Chart 時,直接將 Chart 以及其依賴的所有 Charts 合併為一個 Release,同時傳遞給 Kubernetes。因此 Tiller 並不負責管理依賴之間的啟動順序。Chart 中的應用需要能夠自行處理依賴關係。
部署 Helm
安裝 Helm 客戶端
Helm 的安裝方式很多,這裡採用二進位制的方式安裝。更多安裝方法可以參考 Helm 的官方幫助文件。
- 使用官方提供的指令碼一鍵安裝
1 2 3 |
$ curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh $ chmod 700 get_helm.sh $ ./get_helm.sh |
- 手動下載安裝
1 2 3 4 5 6 |
# 下載 Helm $ wget https://storage.googleapis.com/kubernetes-helm/helm-v2.9.1-linux-amd64.tar.gz # 解壓 Helm $ tar -zxvf helm-v2.9.1-linux-amd64.tar.gz # 複製客戶端執行檔案到 bin 目錄下 $ cp linux-amd64/helm /usr/local/bin/ |
注:storage.googleapis.com 預設是不能訪問的,該問題請自行解決。
安裝 Helm 伺服器端 Tiller
Tiller 是以 Deployment 方式部署在 Kubernetes 叢集中的,只需使用以下指令便可簡單的完成安裝。
1 |
$ helm init |
由於 Helm 預設會去 storage.googleapis.com 拉取映象,如果你當前執行的機器不能訪問該域名的話可以使用以下命令來安裝:
1 2 |
# 使用阿里雲映象安裝並把預設倉庫設定為阿里雲上的映象倉庫 $ helm init --upgrade --tiller-image registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.9.1 --stable-repo-url https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts |
給 Tiller 授權
因為 Helm 的服務端 Tiller 是一個部署在 Kubernetes 中 Kube-System Namespace 下 的 Deployment,它會去連線 Kube-Api 在 Kubernetes 裡建立和刪除應用。
而從 Kubernetes 1.6 版本開始,API Server 啟用了 RBAC 授權。目前的 Tiller 部署時預設沒有定義授權的 ServiceAccount,這會導致訪問 API Server 時被拒絕。所以我們需要明確為 Tiller 部署新增授權。
- 建立 Kubernetes 的服務帳號和繫結角色
1 2 3 4 5 |
$ kubectl get deployment --all-namespaces NAMESPACE NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE kube-system tiller-deploy 1 1 1 1 1h $ kubectl create serviceaccount --namespace kube-system tiller $ kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller |
- 為 Tiller 設定帳號
1 2 3 |
# 使用 kubectl patch 更新 API 物件 $ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}' deployment.extensions "tiller-deploy" patched |
- 檢視是否授權成功
1 2 3 |
$ kubectl get deploy --namespace kube-system tiller-deploy --output yaml|grep serviceAccount serviceAccount: tiller serviceAccountName: tiller |
驗證 Tiller 是否安裝成功
1 2 3 4 5 6 |
$ kubectl -n kube-system get pods|grep tiller tiller-deploy-6d68f5c78f-nql2z 1/1 Running 0 5m $ helm version Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"} |
解除安裝 Helm 伺服器端 Tiller
如果你需要在 Kubernetes 中解除安裝已部署的 Tiller,可使用以下命令完成解除安裝。
1 |
$ helm reset |
構建一個 Helm Chart
下面我們通過一個完整的示例來學習如何使用 Helm 建立、打包、分發、安裝、升級及回退Kubernetes應用。
建立一個名為 mychart 的 Chart
1 |
$ helm create mychart |
該命令建立了一個 mychart 目錄,該目錄結構如下所示。這裡我們主要關注目錄中的 Chart.yaml、values.yaml、NOTES.txt 和 Templates 目錄。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ tree mychart/ mychart/ ├── charts ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── ingress.yaml │ ├── NOTES.txt │ └── service.yaml └── values.yaml 2 directories, 7 files |
- Chart.yaml 用於描述這個 Chart的相關資訊,包括名字、描述資訊以及版本等。
- values.yaml 用於儲存 templates 目錄中模板檔案中用到變數的值。
- NOTES.txt 用於介紹 Chart 部署後的一些資訊,例如:如何使用這個 Chart、列出預設的設定等。
- Templates 目錄下是 YAML 檔案的模板,該模板檔案遵循 Go template 語法。
Templates 目錄下 YAML 檔案模板的值預設都是在 values.yaml 裡定義的,比如在 deployment.yaml 中定義的容器映象。
1 |
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" |
其中的 .Values.image.repository
的值就是在 values.yaml 裡定義的 nginx,.Values.image.tag
的值就是 stable。
1 2 3 4 5 |
$ cat mychart/values.yaml|grep repository repository: nginx $ cat mychart/values.yaml|grep tag tag: stable |
以上兩個變數值是在 create chart
的時候就自動生成的預設值,你可以根據實際情況進行修改。
編寫應用的介紹資訊
開啟 Chart.yaml, 填寫你部署的應用的詳細資訊,以 mychart 為例:
1 2 3 4 5 6 |
$ cat mychart/Chart.yaml apiVersion: v1 appVersion: "1.0" description: A Helm chart for Kubernetes name: mychart version: 0.1.0 |
編寫應用具體部署資訊
編輯 values.yaml,它預設會在 Kubernetes 部署一個 Nginx。下面是 mychart 應用的 values.yaml 檔案的內容:
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 36 37 38 39 40 41 42 43 44 45 46 |
$ cat mychart/values.yaml # Default values for mychart. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 image: repository: nginx tag: stable pullPolicy: IfNotPresent service: type: ClusterIP port: 80 ingress: enabled: false annotations: {} # kubernetes.io/ingress.class: nginx # kubernetes.io/tls-acme: "true" path: / hosts: - chart-example.local tls: [] # - secretName: chart-example-tls # hosts: # - chart-example.local resources: {} # We usually recommend not to specify default resources and to leave this as a conscious # choice for the user. This also increases chances charts run on environments with little # resources, such as Minikube. If you do want to specify resources, uncomment the following # lines, adjust them as necessary, and remove the curly braces after 'resources:'. # limits: # cpu: 100m # memory: 128Mi # requests: # cpu: 100m # memory: 128Mi nodeSelector: {} tolerations: [] affinity: {} |
檢查依賴和模板配置是否正確
1 2 3 4 5 |
$ helm lint mychart/ ==> Linting . [INFO] Chart.yaml: icon is recommended 1 chart(s) linted, no failures |
如果檔案格式錯誤,可以根據提示進行修改。
將應用打包
1 2 |
$ helm package mychart Successfully packaged chart and saved it to: /home/k8s/mychart-0.1.0.tgz |
mychart 目錄會被打包為一個 mychart-0.1.0.tgz 格式的壓縮包,該壓縮包會被放到當前目錄下,並同時被儲存到了 Helm 的本地預設倉庫目錄中。
如果你想看到更詳細的輸出,可以加上 --debug
引數來檢視打包的輸出,輸出內容應該類似如下:
1 2 3 |
$ helm package mychart --debug Successfully packaged chart and saved it to: /home/k8s/mychart-0.1.0.tgz [debug] Successfully saved /home/k8s/mychart-0.1.0.tgz to /home/k8s/.helm/repository/local |
將應用釋出到 Repository
雖然我們已經打包了 Chart 併發布到了 Helm 的本地目錄中,但通過 helm search
命令查詢,並不能找不到剛才生成的 mychart包。
1 2 |
$ helm search mychart No results found |
這是因為 Repository 目錄中的 Chart 包還沒有被 Helm 管理。通過 helm repo list
命令可以看到目前 Helm 中已配置的 Repository 的資訊。
1 2 3 |
$ helm repo list NAME URL stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts |
注:新版本中執行 helm init 命令後預設會配置一個名為 local 的本地倉庫。
我們可以在本地啟動一個 Repository Server,並將其加入到 Helm Repo 列表中。Helm Repository 必須以 Web 服務的方式提供,這裡我們就使用 helm serve
命令啟動一個 Repository Server,該 Server 預設使用 $HOME/.helm/repository/local
目錄作為 Chart 儲存,並在 8879 埠上提供服務。
1 2 |
$ helm serve & Now serving you on 127.0.0.1:8879 |
預設情況下該服務只監聽 127.0.0.1,如果你要繫結到其它網路介面,可使用以下命令:
1 |
$ helm serve --address 192.168.100.211:8879 & |
如果你想使用指定目錄來做為 Helm Repository 的儲存目錄,可以加上 --repo-path
引數:
1 |
$ helm serve --address 192.168.100.211:8879 --repo-path /data/helm/repository/ --url http://192.168.100.211:8879/charts/ |
通過 helm repo index
命令將 Chart 的 Metadata 記錄更新在 index.yaml 檔案中:
1 2 3 |
# 更新 Helm Repository 的索引檔案 $ cd /home/k8s/.helm/repository/local $ helm repo index --url=http://192.168.100.211:8879 . |
完成啟動本地 Helm Repository Server 後,就可以將本地 Repository 加入 Helm 的 Repo 列表。
1 2 |
$ helm repo add local http://127.0.0.1:8879 "local" has been added to your repositories |
現在再次查詢 mychart 包,就可以搜尋到了。
1 2 3 4 |
$ helm repo update $ helm search mychart NAME CHART VERSION APP VERSION DESCRIPTION local/mychart 0.1.0 1.0 A Helm chart for Kubernetes |
在 Kubernetes 中部署應用
部署一個應用
Chart 被髮布到倉儲後,就可以通過 helm install
命令部署該 Chart。
- 檢查配置和模板是否有效
當使用 helm install
命令部署應用時,實際上就是將 templates 目錄下的模板檔案渲染成 Kubernetes 能夠識別的 YAML 格式。
在部署前我們可以使用 helm install --dry-run --debug <chart_dir> --name <release_name>
命令來驗證 Chart 的配置。該輸出中包含了模板的變數配置與最終渲染的 YAML 檔案。
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 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
$ helm install --dry-run --debug local/mychart --name mike-test [debug] Created tunnel using local port: '46649' [debug] SERVER: "127.0.0.1:46649" [debug] Original chart version: "" [debug] Fetched local/mychart to /home/k8s/.helm/cache/archive/mychart-0.1.0.tgz [debug] CHART PATH: /home/k8s/.helm/cache/archive/mychart-0.1.0.tgz NAME: mike-test REVISION: 1 RELEASED: Mon Jul 23 10:39:49 2018 CHART: mychart-0.1.0 USER-SUPPLIED VALUES: {} COMPUTED VALUES: affinity: {} image: pullPolicy: IfNotPresent repository: nginx tag: stable ingress: annotations: {} enabled: false hosts: - chart-example.local path: / tls: [] nodeSelector: {} replicaCount: 1 resources: {} service: port: 80 type: ClusterIP tolerations: [] HOOKS: MANIFEST: --- # Source: mychart/templates/service.yaml apiVersion: v1 kind: Service metadata: name: mike-test-mychart labels: app: mychart chart: mychart-0.1.0 release: mike-test heritage: Tiller spec: type: ClusterIP ports: - port: 80 targetPort: http protocol: TCP name: http selector: app: mychart release: mike-test --- # Source: mychart/templates/deployment.yaml apiVersion: apps/v1beta2 kind: Deployment metadata: name: mike-test-mychart labels: app: mychart chart: mychart-0.1.0 release: mike-test heritage: Tiller spec: replicas: 1 selector: matchLabels: app: mychart release: mike-test template: metadata: labels: app: mychart release: mike-test spec: containers: - name: mychart image: "nginx:stable" imagePullPolicy: IfNotPresent ports: - name: http containerPort: 80 protocol: TCP livenessProbe: httpGet: path: / port: http readinessProbe: httpGet: path: / port: http resources: {} |
驗證完成沒有問題後,我們就可以使用以下命令將其部署到 Kubernetes 上了。
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 |
# 部署時需指定 Chart 名及 Release(部署的例項)名。 $ helm install local/mychart --name mike-test NAME: mike-test LAST DEPLOYED: Mon Jul 23 10:41:20 2018 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mike-test-mychart ClusterIP 10.254.120.177 <none> 80/TCP 1s ==> v1beta2/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE mike-test-mychart 1 0 0 0 0s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE mike-test-mychart-6d56f8c8c9-d685v 0/1 Pending 0 0s NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=mike-test" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:80 |
注:helm install 預設會用到 socat,需要在所有節點上安裝 socat 軟體包。
完成部署後,現在 Nginx 就已經部署到 Kubernetes 叢集上。在本地主機上執行提示中的命令後,就可在本機訪問到該 Nginx 例項。
1 2 3 |
$ export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=mike-test" -o jsonpath="{.items[0].metadata.name}") $ echo "Visit http://127.0.0.1:8080 to use your application" $ kubectl port-forward $POD_NAME 8080:80 |
在本地訪問 Nginx
1 2 3 4 5 6 7 8 |
$ curl http://127.0.0.1:8080 ..... <title>Welcome to nginx!</title> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> ...... |
使用下面的命令列出的所有已部署的 Release 以及其對應的 Chart。
1 2 3 |
$ helm list NAME REVISION UPDATED STATUS CHART NAMESPACE mike-test 1 Mon Jul 23 10:41:20 2018 DEPLOYED mychart-0.1.0 default |
你還可以使用 helm status
查詢一個特定的 Release 的狀態。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$ helm status mike-test LAST DEPLOYED: Mon Jul 23 10:41:20 2018 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE mike-test-mychart-6d56f8c8c9-d685v 1/1 Running 0 1m ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mike-test-mychart ClusterIP 10.254.120.177 <none> 80/TCP 1m ==> v1beta2/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE mike-test-mychart 1 1 1 1 1m NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=mike-test" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:80 |
升級和回退一個應用
從上面 helm list
輸出的結果中我們可以看到有一個 Revision(更改歷史)欄位,該欄位用於表示某一個 Release 被更新的次數,我們可以用該特性對已部署的 Release 進行回滾。
- 修改 Chart.yaml 檔案
將版本號從 0.1.0 修改為 0.2.0, 然後使用 helm package
命令打包併發布到本地倉庫。
1 2 3 4 5 6 7 8 9 |
$ cat mychart/Chart.yaml apiVersion: v1 appVersion: "1.0" description: A Helm chart for Kubernetes name: mychart version: 0.2.0 $ helm package mychart Successfully packaged chart and saved it to: /home/k8s/mychart-0.2.0.tgz |
- 查詢本地倉庫中的 Chart 資訊
我們可以看到在本地倉庫中 mychart 有兩個版本。
1 2 3 4 |
$ helm search mychart -l NAME CHART VERSION APP VERSION DESCRIPTION local/mychart 0.2.0 1.0 A Helm chart for Kubernetes local/mychart 0.1.0 1.0 A Helm chart for Kubernetes |
- 升級一個應用
現在用 helm upgrade
命令將已部署的 mike-test 升級到新版本。你可以通過 --version
引數指定需要升級的版本號,如果沒有指定版本號,則預設使用最新版本。
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 |
$ helm upgrade mike-test local/mychart Release "mike-test" has been upgraded. Happy Helming! LAST DEPLOYED: Mon Jul 23 10:50:25 2018 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE mike-test-mychart-6d56f8c8c9-d685v 1/1 Running 0 9m ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mike-test-mychart ClusterIP 10.254.120.177 <none> 80/TCP 9m ==> v1beta2/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE mike-test-mychart 1 1 1 1 9m NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=mike-test" -o jsonpath="{.items[0].metadata.name}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl port-forward $POD_NAME 8080:80 |
完成後,可以看到已部署的 mike-test 被升級到 0.2.0 版本。
1 2 3 |
$ helm list NAME REVISION UPDATED STATUS CHART NAMESPACE mike-test 2 Mon Jul 23 10:50:25 2018 DEPLOYED mychart-0.2.0 default |
- 回退一個應用
如果更新後的程式由於某些原因執行有問題,需要回退到舊版本的應用。首先我們可以使用 helm history
命令檢視一個 Release 的所有變更記錄。
1 2 3 4 |
$ helm history mike-test REVISION UPDATED STATUS CHART DESCRIPTION 1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete 2 Mon Jul 23 10:50:25 2018 DEPLOYED mychart-0.2.0 Upgrade complete |
其次,我們可以使用下面的命令對指定的應用進行回退。
1 2 |
$ helm rollback mike-test 1 Rollback was a success! Happy Helming! |
注:其中的引數 1 是 helm history 檢視到 Release 的歷史記錄中 REVISION 對應的值。
最後,我們使用 helm list
和 helm history
命令都可以看到 mychart 的版本已經回退到 0.1.0 版本。
1 2 3 4 5 6 7 8 9 |
$ helm list NAME REVISION UPDATED STATUS CHART NAMESPACE mike-test 3 Mon Jul 23 10:53:42 2018 DEPLOYED mychart-0.1.0 default $ helm history mike-test REVISION UPDATED STATUS CHART DESCRIPTION 1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete 2 Mon Jul 23 10:50:25 2018 SUPERSEDED mychart-0.2.0 Upgrade complete 3 Mon Jul 23 10:53:42 2018 DEPLOYED mychart-0.1.0 Rollback to 1 |
刪除一個應用
如果需要刪除一個已部署的 Release,可以利用 helm delete
命令來完成刪除。
1 2 |
$ helm delete mike-test release "mike-test" deleted |
確認應用是否刪除,該應用已被標記為 DELETED 狀態。
1 2 3 |
$ helm ls -a mike-test NAME REVISION UPDATED STATUS CHART NAMESPACE mike-test 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 default |
也可以使用 --deleted
引數來列出已經刪除的 Release
1 2 3 |
$ helm ls --deleted NAME REVISION UPDATED STATUS CHART NAMESPACE mike-test 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 default |
從上面的結果也可以看出,預設情況下已經刪除的 Release 只是將狀態標識為 DELETED 了 ,但該 Release 的歷史資訊還是繼續被儲存的。
1 2 3 4 5 |
$ helm hist mike-test REVISION UPDATED STATUS CHART DESCRIPTION 1 Mon Jul 23 10:41:20 2018 SUPERSEDED mychart-0.1.0 Install complete 2 Mon Jul 23 10:50:25 2018 SUPERSEDED mychart-0.2.0 Upgrade complete 3 Mon Jul 23 10:53:42 2018 DELETED mychart-0.1.0 Deletion complete |
如果要移除指定 Release 所有相關的 Kubernetes 資源和 Release 的歷史記錄,可以用如下命令:
1 2 |
$ helm delete --purge mike-test release "mike-test" deleted |
再次檢視已刪除的 Release,已經無法找到相關資訊。
1 2 3 4 5 6 |
$ helm hist mike-test Error: release: "mike-test" not found # helm ls 命令也已均無查詢記錄。 $ helm ls --deleted $ helm ls -a mike-test |
Helm 部署應用例項
部署 Wordpress
這裡以一個典型的三層應用 Wordpress 為例,包括 MySQL、PHP 和 Apache。
由於測試環境沒有可用的 PersistentVolume(持久卷,簡稱 PV),這裡暫時將其關閉。關於 Persistent Volumes 的相關資訊我們會在後續的相關文章進行講解。
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 36 37 38 39 40 41 42 43 44 45 |
$ helm install --name wordpress-test --set "persistence.enabled=false,mariadb.persistence.enabled=false,serviceType=NodePort" stable/wordpress NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1beta1/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE wordpress-test-mariadb 1 1 1 1 26m wordpress-test-wordpress 1 1 1 1 26m ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE wordpress-test-mariadb-84b866bf95-n26ff 1/1 Running 1 26m wordpress-test-wordpress-5ff8c64b6c-sgtvv 1/1 Running 6 26m ==> v1/Secret NAME TYPE DATA AGE wordpress-test-mariadb Opaque 2 26m wordpress-test-wordpress Opaque 2 26m ==> v1/ConfigMap NAME DATA AGE wordpress-test-mariadb 1 26m wordpress-test-mariadb-tests 1 26m ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE wordpress-test-mariadb ClusterIP 10.254.99.67 <none> 3306/TCP 26m wordpress-test-wordpress NodePort 10.254.175.16 <none> 80:8563/TCP,443:8839/TCP 26m NOTES: 1. Get the WordPress URL: Or running: export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-test-wordpress) export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}") echo http://$NODE_IP:$NODE_PORT/admin 2. Login with the following credentials to see your blog echo Username: user echo Password: $(kubectl get secret --namespace default wordpress-test-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode) |
訪問 Wordpress
部署完成後,我們可以通過上面的提示資訊生成相應的訪問地址和使用者名稱、密碼等相關資訊。
1 2 3 4 5 6 7 8 9 10 11 |
# 生成 Wordpress 管理後臺地址 $ export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services wordpress-test-wordpress) $ export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}") $ echo http://$NODE_IP:$NODE_PORT/admin http://192.168.100.211:8433/admin # 生成 Wordpress 管理帳號和密碼 $ echo Username: user Username: user $ echo Password: $(kubectl get secret --namespace default wordpress-test-wordpress -o jsonpath="{.data.wordpress-password}" | base64 --decode) Password: 9jEXJgnVAY |
給一張訪問效果圖吧:
Helm 其它使用技巧
- 如何設定 helm 命令自動補全?
為了方便 helm
命令的使用,Helm 提供了自動補全功能,如果使用 ZSH 請執行:
1 |
$ source <(helm completion zsh) |
如果使用 BASH 請執行:
1 |
$ source <(helm completion bash) |
- 如何使用第三方的 Chart 儲存庫?
隨著 Helm 越來越普及,除了使用預置官方儲存庫,三方倉庫也越來越多了(前提是網路是可達的)。你可以使用如下命令格式新增三方 Chart 儲存庫。
1 2 |
$ helm repo add 儲存庫名 儲存庫URL $ helm repo update |
一些三方儲存庫資源:
1 2 3 4 5 6 7 8 9 10 11 12 |
# Prometheus Operator https://github.com/coreos/prometheus-operator/tree/master/helm # Bitnami Library for Kubernetes https://github.com/bitnami/charts # Openstack-Helm https://github.com/att-comdev/openstack-helm https://github.com/sapcc/openstack-helm # Tick-Charts https://github.com/jackzampolin/tick-charts |
- Helm 如何結合 CI/CD ?
採用 Helm 可以把零散的 Kubernetes 應用配置檔案作為一個 Chart 管理,Chart 原始碼可以和原始碼一起放到 Git 庫中管理。通過把 Chart 引數化,可以在測試環境和生產環境採用不同的 Chart 引數配置。
下圖是採用了 Helm 的一個 CI/CD 流程
- Helm 如何管理多環境下 (Test、Staging、Production) 的業務配置?
Chart 是支援引數替換的,可以把業務配置相關的引數設定為模板變數。使用 helm install
命令部署的時候指定一個引數值檔案,這樣就可以把業務引數從 Chart 中剝離了。例如: helm install --values=values-production.yaml wordpress
。
- Helm 如何解決服務依賴?
在 Chart 裡可以通過 requirements.yaml 宣告對其它 Chart 的依賴關係。如下面宣告表明 Chart 依賴 Apache 和 MySQL 這兩個第三方 Chart。
1 2 3 4 5 6 7 8 9 10 |
dependencies: - name: mariadb version: 2.1.1 repository: https://kubernetes-charts.storage.googleapis.com/ condition: mariadb.enabled tags: - wordpress-database - name: apache version: 1.4.0 repository: https://kubernetes-charts.storage.googleapis.com/ |
- 如何讓 Helm 連線到指定 Kubernetes 叢集?
Helm 預設使用和 kubectl 命令相同的配置訪問 Kubernetes 叢集,其配置預設在 ~/.kube/config
中。
- 如何在部署時指定名稱空間?
helm install
預設情況下是部署在 default 這個名稱空間的。如果想部署到指定的命令空間,可以加上 --namespace
引數,比如:
1 |
$ helm install local/mychart --name mike-test --namespace mynamespace |
- 如何檢視已部署應用的詳細資訊?
1 |
$ helm get wordpress-test |
預設情況下會顯示最新的版本的相關資訊,如果想要檢視指定釋出版本的資訊可加上 --revision
引數。
1 |
$ helm get --revision 1 wordpress-test |
參考文件
http://www.google.com
http://t.cn/RgEE0dm
http://t.cn/RgE3MyP
http://t.cn/RgpiUAz