構建一個 Helm Chart
下面我們通過一個完整的示例來學習如何使用 Helm 建立、打包、分發、安裝、升級及回退Kubernetes應用。
建立一個名為 mychart 的 Chart
$ helm create mychart
該命令建立了一個 mychart 目錄,該目錄結構如下所示。這裡我們主要關注目錄中的 Chart.yaml、values.yaml、NOTES.txt 和 Templates 目錄。
[centos@k8s-master helm]$ tree mychart
mychart
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
- 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
。
以上兩個變數值是在 create chart 的時候就自動生成的預設值,你可以根據實際情況進行修改。實際上都是靜態文字,只在是執行的時候才被解析.
如果你需要了解更多關於 Go 模板的相關資訊,可以檢視 Hugo 的一個關於 Go 模板 的介紹
編寫應用的介紹資訊
開啟 Chart.yaml,可以看到內容如下
$ 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 init 命令後預設會配置一個名為 local 的本地倉庫。如果大家通過helm repo list 可以看到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.124.59:8879 --repo-path /data/helm/repository/ --url http://192.168.124.59: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
$ 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: tylertest
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: tylertest-mychart
labels:
app: mychart
chart: mychart-0.1.0
release: tyler-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: tylertest-mychart
labels:
app: mychart
chart: mychart-0.1.0
release: tyler-test
heritage: Tiller
spec:
replicas: 1
selector:
matchLabels:
app: mychart
release: tyler-test
template:
metadata:
labels:
app: mychart
release: tyler-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 軟體包。
關於訪問的部分這裡就不再介紹了,後面會講解一個完整專案對外暴露訪問
使用下面的命令列出的所有已部署的 Release 以及其對應的 Chart。
$ helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
tylertest 1 Mon Jul 23 10:41:20 2018 DEPLOYED mychart-0.1.0 default
你還可以使用 helm status
查詢一個特定的 Release 的狀態。
$ helm status tylertest
LAST DEPLOYED: Mon Jul 23 10:41:20 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
tylertest-mychart-6d56f8c8c9-d685v 1/1 Running 0 1m
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tylertest-mychart ClusterIP 10.254.120.177 <none> 80/TCP 1m
==> v1beta2/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
tylertest-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=tyler-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 有兩個版本
[centos@k8s-master helm]$ 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 命令將已部署的 tylertest 升級到新版本。你可以通過 --version 引數指定需要升級的版本號,如果沒有指定版本號,則預設使用最新版本。
[centos@k8s-master helm]$ helm upgrade tylertest mychart
Release "tylertest" has been upgraded. Happy Helming!
LAST DEPLOYED: Thu Apr 25 09:19:53 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Deployment
NAME READY UP-TO-DATE AVAILABLE AGE
tylertest-mychart 1/1 1 1 25m
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
tylertest-mychart-545479dd4b-hj9ml 1/1 Running 0 25m
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
tylertest-mychart ClusterIP 10.103.51.57 <none> 80/TCP 25m
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=tylertest" -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
完成後,可以看到已部署的 tylertest 被升級到 0.2.0 版本。
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
kubernetes-dashboard 1 Thu Mar 14 09:06:25 2019 DEPLOYED kubernetes-dashboard-1.2.0 1.10.1 kube-system
tylertest 2 Thu Apr 25 09:19:53 2019 DEPLOYED mychart-0.2.0 1.0 default
- 回退一個應用
如果更新後的程式由於某些原因執行有問題,需要回退到舊版本的應用。首先我們可以使用 helm history
命令檢視一個 Release 的所有變更記錄。
[centos@k8s-master helm]$ helm list tylertest
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
tylertest 2 Thu Apr 25 09:19:53 2019 DEPLOYED mychart-0.2.0 1.0 default
其次,我們可以使用下面的命令對指定的應用進行回退。
[centos@k8s-master helm]$ helm rollback tylertest 1
Rollback was a success! Happy Helming!
注:其中的引數 1 是 helm history 檢視到 Release 的歷史記錄中 REVISION 對應的值。
- 最後,我們使用 helm list 和 helm history 命令都可以看到 mychart 的版本已經回退到 0.1.0 版本。
[centos@k8s-master helm]$ helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
kubernetes-dashboard 1 Thu Mar 14 09:06:25 2019 DEPLOYED kubernetes-dashboard-1.2.0 1.10.1 kube-system
tylertest 3 Thu Apr 25 09:22:19 2019 DEPLOYED mychart-0.1.0 1.0 default
[centos@k8s-master helm]$ helm history tylertest
REVISION UPDATED STATUS CHART DESCRIPTION
1 Thu Apr 25 08:54:49 2019 SUPERSEDED mychart-0.1.0 Install complete
2 Thu Apr 25 09:19:53 2019 SUPERSEDED mychart-0.2.0 Upgrade complete
3 Thu Apr 25 09:22:19 2019 DEPLOYED mychart-0.1.0 Rollback to 1
刪除一個應用
如果需要刪除一個已部署的 Release,可以利用 helm delete 命令來完成刪除。
[centos@k8s-master helm]$ helm delete tylertest
release "tylertest" deleted
確認應用是否刪除,該應用已被標記為 DELETED 狀態
[centos@k8s-master helm]$ helm ls --deleted
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
intentional-chinchilla 1 Wed Apr 24 18:37:29 2019 DELETED mychart-0.1.0 1.0 default
invisible-turkey 1 Mon Apr 22 17:39:14 2019 DELETED nginx-ingress-0.21.1 0.14.0 jx
punk-condor 1 Wed Apr 24 18:38:09 2019 DELETED mychart-0.1.0 1.0 default
tylerchart 1 Wed Apr 24 18:40:01 2019 DELETED mychart-0.1.0 1.0 default
tylertest 3 Thu Apr 25 09:22:19 2019 DELETED mychart-0.1.0 1.0 default
vigilant-bat 1 Wed Apr 24 17:40:02 2019 DELETED xray-0.4.2 2.3.0 default
從上面的結果也可以看出,預設情況下已經刪除的 Release 只是將狀態標識為 DELETED 了 ,但該 Release 的歷史資訊還是繼續被儲存的。
[centos@k8s-master helm]$ helm history tylertest
REVISION UPDATED STATUS CHART DESCRIPTION
1 Thu Apr 25 08:54:49 2019 SUPERSEDED mychart-0.1.0 Install complete
2 Thu Apr 25 09:19:53 2019 SUPERSEDED mychart-0.2.0 Upgrade complete
3 Thu Apr 25 09:22:19 2019 DELETED mychart-0.1.0 Deletion complete
如果要移除指定 Release 所有相關的 Kubernetes 資源和 Release 的歷史記錄,可以用如下命令:
[centos@k8s-master helm]$ helm delete --purge tylertest
release "tylertest" deleted
再次檢視已刪除的 Release,已經無法找到相關資訊。
$ helm hist tylertest
Error: release: "tyertest" not found
# helm ls 命令也已均無查詢記錄。
$ helm ls --deleted
$ helm ls -a tylertest