Helm 入門指南

運維之美2018-08-12 13:26:33

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 的官方幫助文檔。

  • 使用官方提供的腳本一鍵安裝

$ curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
$ chmod 700 get_helm.sh
$ ./get_helm.sh
  • 手動下載安裝

# 下載 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 集羣中的,只需使用以下指令便可簡單的完成安裝。

$ helm init

由於 Helm 默認會去 storage.googleapis.com 拉取鏡像,如果你當前執行的機器不能訪問該域名的話可以使用以下命令來安裝:

# 使用阿里雲鏡像安裝並把默認倉庫設置為阿里雲上的鏡像倉庫
$ 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 的服務帳號和綁定角色

$ 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 設置帳號

# 使用 kubectl patch 更新 API 對象
$ kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
deployment.extensions "tiller-deploy" patched
  • 查看是否授權成功

$ kubectl get deploy --namespace kube-system   tiller-deploy  --output yaml|grep  serviceAccount
serviceAccount: tiller
serviceAccountName: tiller
驗證 Tiller 是否安裝成功
$ 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,可使用以下命令完成卸載。

$ helm reset

構建一個 Helm Chart

下面我們通過一個完整的示例來學習如何使用 Helm 創建、打包、分發、安裝、升級及回退Kubernetes應用。

創建一個名為 mychart 的 Chart

$ helm create mychart

該命令創建了一個 mychart 目錄,該目錄結構如下所示。這裏我們主要關注目錄中的 Chart.yaml、values.yaml、NOTES.txt 和 Templates 目錄。

$ 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 中定義的容器鏡像 image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" 其中的 .Values.image.repository 的值就是在  values.yaml 裏定義的 nginx,.Values.image.tag 的值就是 stable。

$ cat mychart/values.yaml|grep repository
repository: nginx

$ cat mychart/values.yaml|grep tag
tag: stable

以上兩個變量值是在 create chart 的時候就自動生成的默認值,你可以根據實際情況進行修改。

如果你需要了解更多關於 Go 模板的相關信息,可以查看 Hugo 的一個關於 Go 模板 的介紹。

編寫應用的介紹信息

打開 Chart.yaml, 填寫你部署的應用的詳細信息,以 mychart 為例:

$ 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 文件的內容:

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

檢查依賴和模板配置是否正確

$ helm lint mychart/
==> Linting .
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, no failures

如果文件格式錯誤,可以根據提示進行修改。

將應用打包

$ 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 參數來查看打包的輸出,輸出內容應該類似如下:

$ 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包。

$ helm search mychart
No results found

這是因為 Repository 目錄中的 Chart 包還沒有被 Helm 管理。通過 helm repo list 命令可以看到目前 Helm 中已配置的 Repository 的信息。

$ 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 端口上提供服務。

$ helm serve &
Now serving you on 127.0.0.1:8879

默認情況下該服務只監聽 127.0.0.1,如果你要綁定到其它網絡接口,可使用以下命令:

$ helm serve --address 192.168.100.211:8879 &

如果你想使用指定目錄來做為 Helm Repository 的存儲目錄,可以加上 --repo-path 參數:

$ 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 文件中:

# 更新 Helm Repository 的索引文件
$ cd /home/k8s/.helm/repository/local
$ helm repo index --url=http://192.168.100.211:8879 .

完成啟動本地 Helm Repository Server 後,就可以將本地 Repository 加入 Helm 的 Repo 列表。

$ helm repo add local http://127.0.0.1:8879
"local" has been added to your repositories

現在再次查找 mychart 包,就可以搜索到了。

$ 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 文件。

$ 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 上了。

# 部署時需指定 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 實例。

$ 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

$ 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。

$ 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 的狀態。

$ 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 命令打包併發布到本地倉庫。

$ 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 有兩個版本。

$ 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 參數指定需要升級的版本號,如果沒有指定版本號,則缺省使用最新版本。

$ 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 版本。

$ 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 的所有變更記錄。

$ 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

其次,我們可以使用下面的命令對指定的應用進行回退。

$ helm rollback mike-test 1
Rollback was a success! Happy Helming!

注:其中的參數 1 是 helm history 查看到 Release 的歷史記錄中 REVISION 對應的值。

最後,我們使用 helm listhelm history 命令都可以看到 mychart 的版本已經回退到 0.1.0 版本。

$ 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 命令來完成刪除。

$ helm delete mike-test
release "mike-test" deleted

確認應用是否刪除,該應用已被標記為 DELETED 狀態。

$ 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

$ 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 的歷史信息還是繼續被保存的。

$ 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 的歷史記錄,可以用如下命令:

$ helm delete --purge mike-test
release "mike-test" deleted

再次查看已刪除的 Release,已經無法找到相關信息。

$ 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 的相關信息我們會在後續的相關文章進行講解。

$ 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

部署完成後,我們可以通過上面的提示信息生成相應的訪問地址和用户名、密碼等相關信息。

# 生成 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 請執行:

$ source <(helm completion zsh)

如果使用 BASH 請執行:

$ source <(helm completion bash)
  • 如何使用第三方的 Chart 存儲庫?

隨着 Helm 越來越普及,除了使用預置官方存儲庫,三方倉庫也越來越多了(前提是網絡是可達的)。你可以使用如下命令格式添加三方 Chart 存儲庫。

$ helm repo add 存儲庫名 存儲庫URL
$ helm repo update

一些三方存儲庫資源:

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

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 參數,比如:

$ helm install local/mychart --name mike-test --namespace mynamespace
  • 如何查看已部署應用的詳細信息?

$ helm get wordpress-test

默認情況下會顯示最新的版本的相關信息,如果想要查看指定發佈版本的信息可加上 --revision 參數。

$ helm get  --revision 1  wordpress-test

參考文檔

http://www.google.com
http://t.cn/RgEE0dm
http://t.cn/RgE3MyP
http://t.cn/RgpiUAz


今日思想


問題永遠不在於如何使用頭腦裏產生嶄新的、創造性的思想,而在於如何從頭腦裏淘汰舊觀念。


——迪伊·霍克




推薦閲讀




閲讀原文

TAGS: