Kubernetes之(二十)Helm程序包管理器

Kubernetes之(二十)Helm程序包管理器

概念

每一個成功的軟件平臺都有一個優秀的打包系統,好比 Debian、Ubuntu 的 apt,Redhat、Centos 的 yum。而 Helm 則是 Kubernetes 上的包管理器。
Kubernetes 可以很好地組織和編排容器,但它缺乏一個更高層次的應用打包工具,而 Helm 就是來幹這件事的。
舉個例子,咱們須要部署一個MySQL服務,Kubernetes則須要部署如下對象:
① 爲了可以讓外界訪問到MySQL,須要部署一個mysql的service;
②須要進行定義MySQL的密碼,則須要部署一個Secret;
③Mysql的運行須要持久化的數據存儲,此時還須要部署PVC;
④保證後端mysql的運行,還須要部署一個Deployment,以支持以上的對象。
針對以上對象,咱們可使用YAML文件進行定義並部署,可是僅僅對於單個的服務支持,若是應用須要由一個甚至幾十個這樣的服務組成,而且還須要考慮各類服務的依賴問題,可想而知,這樣的組織管理應用的方式就顯得繁瑣。爲此就誕生了一個工具Helm,就是爲了解決Kubernetes這種應用部署繁重的現象。node

Helm的核心術語:mysql

  • Chart:一個helm程序包,是建立一個應用的信息集合,包含各類Kubernetes對象的配置模板、參數定義、依賴關係、文檔說明等。能夠將Chart比喻爲yum中的軟件安裝包;
  • Repository:Charts倉庫,用於集中存儲和分發Charts;
  • Config:應用程序實例化安裝運行時所須要的配置信息;
  • Release:特定的Chart部署於目標集羣上的一個實例,表明這一個正在運行的應用。當chart被安裝到Kubernetes集羣,就會生成一個release,chart能夠屢次安裝到同一個集羣,每次安裝都是一個release。

Helm的程序架構:
Helm主要由Helm客戶端、Tiller服務器和Charts倉庫組成,以下圖:linux

  • helm:客戶端,GO語言編寫,實現管理本地的Chart倉庫,可管理Chart,與Tiller服務進行交互,用於發送Chart,實例安裝、查詢、卸載等操做。
  • Tiller:服務端,一般運行在K8S集羣之上。用於接收helm發來的Charts和Conifg,合併生成release,完成部署。

簡單的說:Helm 客戶端負責管理 chart;Tiller 服務器負責管理 release。nginx

部署Helm

下載helm

Helm的部署方式有兩種:預編譯的二進制程序和源碼編譯安裝,這裏使用二進制的方式進行安裝git

[root@master manifests]# wget https://storage.googleapis.com/kubernetes-helm/helm-v2.9.1-linux-amd64.tar.gz
[root@master manifests]# tar xf helm-v2.9.1-linux-amd64.tar.gz
[root@master manifests]# cd linux-amd64 
[root@master linux-amd64]# ls
helm  LICENSE  README.md
[root@master linux-amd64]# cp helm /usr/bin/

[root@master linux-amd64]# helm version
Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}

部署Tiller

helm第一次init時,須要連接api-server並進行認證,因此在運行helm時,會去讀取kube-config文件,因此必須確認當前用戶存在kube-config文件。github

Tiller運行在K8s集羣之上,也必須擁有集羣的管理權限,也就是須要一個serviceaccount,進行一個clusterrolebinding到cluster-admin。
Tiller的RBAC配置示例連接:web

https://github.com/helm/helm/blob/master/docs/rbac.mdsql

[root@master linux-amd64]# cd ..
[root@master manifests]# mkdir helm
[root@master manifests]# cd helm
[root@master helm]# vim tiller-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: tiller
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: tiller
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
  - kind: ServiceAccount
    name: tiller
    namespace: kube-system
    

[root@master helm]# kubectl apply -f tiller-rbac.yaml 
serviceaccount/tiller created
clusterrolebinding.rbac.authorization.k8s.io/tiller created
[root@master helm]# kubectl get sa -n kube-system|grep tiller
tiller                               1         14s

[root@master helm]# helm init 
Creating /root/.helm 
Creating /root/.helm/repository 
Creating /root/.helm/repository/cache 
Creating /root/.helm/repository/local 
Creating /root/.helm/plugins 
Creating /root/.helm/starters 
Creating /root/.helm/cache/archive 
Creating /root/.helm/repository/repositories.yaml 
Adding stable repo with URL: https://kubernetes-charts.storage.googleapis.com 
Adding local repo with URL: http://127.0.0.1:8879/charts 
$HELM_HOME has been configured at /root/.helm.

Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.

Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

#helm init命令進行初始化時,會用到gcr.io/kubernetes-helm中的景象,須要提早下載,鏡像標籤和Helm同版本號
[root@master helm]# docker pull xiaobai20201/tiller:v2.9.1

[root@master pki]#  docker tag xiaobai20201/tiller:v2.9.1 gcr.io/kubernetes-helm/tiller:v2.9.1


[root@master helm]# kubectl get pods -n kube-system 
NAME                                     READY   STATUS    RESTARTS   AGE
canal-nbspn                              3/3     Running   0          30h
canal-pj6rx                              3/3     Running   0          30h
canal-rgsnp                              3/3     Running   0          30h
coredns-78d4cf999f-6cb69                 1/1     Running   3          14d
coredns-78d4cf999f-tflpn                 1/1     Running   2          14d
etcd-master                              1/1     Running   0          14d
kube-apiserver-master                    1/1     Running   0          14d
kube-controller-manager-master           1/1     Running   0          14d
kube-flannel-ds-amd64-5zrk7              1/1     Running   0          31h
kube-flannel-ds-amd64-pql5n              1/1     Running   0          31h
kube-flannel-ds-amd64-ssd29              1/1     Running   0          31h
kube-proxy-ch4vp                         1/1     Running   0          14d
kube-proxy-cz2rf                         1/1     Running   1          14d
kube-proxy-kdp7d                         1/1     Running   0          14d
kube-scheduler-master                    1/1     Running   0          14d
kubernetes-dashboard-6f9998798-klf4t     1/1     Running   0          2d2h
metrics-server-v0.3.1-65bd5d59b9-xvmns   2/2     Running   0          5h31m
tiller-deploy-c4f47c598-gl6rp            1/1     Running   0          11m

#安裝完成後,執行helm version能夠看到客戶端和服務端的版本號,兩個都顯示錶示正常安裝。
[root@master helm]# helm version
Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}

若是但願在安裝時自定義一些參數,能夠參考一下的一些參數:docker

  • --canary-image:安裝canary分支,即項目的Master分支
  • --tiller-image:安裝指定版本的鏡像,默認和helm同版本
  • --kube-context:安裝到指定的Kubernetes集羣
  • --tiller-namespace:安裝到指定的名稱空間,默認爲kube-system
    Tiller將數據存儲在ConfigMap資源當中,卸載或重裝不會致使數據丟失,卸載Tiller的方法有如下兩種:
(1)kubectl delete deployment tiller-deploy -n kube-system
(2)helm reset

helm的使用

官方可用的Chart列表:

https://hub.kubeapps.com

[root@master helm]# helm -h
The Kubernetes package manager

To begin working with Helm, run the 'helm init' command:

        $ helm init

This will install Tiller to your running Kubernetes cluster.
It will also set up any necessary local configuration.

Common actions from this point include:

- helm search:    search for charts  #搜索charts
- helm fetch:     download a chart to your local directory to view #下載charts到本地
- helm install:   upload the chart to Kubernetes #安裝charts
- helm list:      list releases of charts #列出charts的版本

Environment:
  $HELM_HOME          set an alternative location for Helm files. By default, these are stored in ~/.helm
  $HELM_HOST          set an alternative Tiller host. The format is host:port
  $HELM_NO_PLUGINS    disable plugins. Set HELM_NO_PLUGINS=1 to disable plugins.
  $TILLER_NAMESPACE   set an alternative Tiller namespace (default "kube-system")
  $KUBECONFIG         set an alternative Kubernetes configuration file (default "~/.kube/config")

Usage:
  helm [command]

Available Commands:
  completion  Generate autocompletions script for the specified shell (bash or zsh) #爲指定的shell生成自動補全腳本(bash或zsh)
  create      create a new chart with the given name #建立一個新的charts
  delete      given a release name, delete the release from Kubernetes #刪除指定版本的release
  dependency  manage a chart's dependencies # 管理charts的依賴
  fetch       download a chart from a repository and (optionally) unpack it in local directory #  下載charts並解壓到本地目錄
  get         download a named release# 下載一個release
  history     fetch release history #release歷史信息
  home        displays the location of HELM_HOME #顯示helm的家目錄
  init        initialize Helm on both client and server #在客戶端和服務端初始化helm
  inspect     inspect a chart #查看charts的詳細信息
  install     install a chart archive #安裝charts
  lint        examines a chart for possible issues #檢測包的存在問題
  list        list releases #列出release
  package     package a chart directory into a chart archive # 將chart目錄進行打包
  plugin      add, list, or remove Helm plugins #add(增長), list(列出), or remove(移除) Helm 插件
  repo        add, list, remove, update, and index chart repositories #add(增長), list(列出), remove(移除), update(更新), and index(索引) chart倉庫
  reset       uninstalls Tiller from a cluster #卸載tiller
  rollback    roll back a release to a previous revision #release版本回滾
  search      search for a keyword in charts#  關鍵字搜索chart
  serve       start a local http web server # 啓動一個本地的http server
  status      displays the status of the named release #查看release狀態信息
  template    locally render templates #本地模板
  test        test a release # release測試
  upgrade     upgrade a release #release更新
  verify      verify that a chart at the given path has been signed and is valid  #驗證chart的簽名和有效期
  version     print the client/server version information #打印客戶端和服務端的版本信息

Charts是Helm的程序包,它們都存在在Charts倉庫當中。Kubernetes官方的倉庫保存了一系列的Charts,倉庫默認的名稱爲stable。安裝Charts到集羣時,Helm首先會到官方倉庫獲取相關的Charts,並建立release。可執行 helm search 查看當前可安裝的 chart 。
Helm 能夠像 yum 管理軟件包同樣管理 chart。 yum 的軟件包存放在倉庫中,一樣的,Helm 也有倉庫。
Helm 安裝時已經默認配置好了兩個倉庫:stable 和 local。stable 是官方倉庫,local 是用戶存放本身開發的chart的本地倉庫。能夠經過helm repo list進行查看。因爲網絡緣由,國內可能沒法更新倉庫源(網絡不穩定偶爾出問題),這裏能夠更改成阿里雲的倉庫源,。

[root@master helm]# helm repo remove stable
"stable" has been removed from your repositories
[root@master helm]# 
[root@master helm]# helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
"stable" has been added to your repositories
[root@master helm]# 
[root@master helm]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈ Happy Helming!⎈ 
[root@master helm]# helm repo list
NAME    URL                                                   
local   http://127.0.0.1:8879/charts                          
stable  https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

與 yum 同樣,helm 也支持關鍵字搜索:

[root@master helm]# helm search stable/mysql
NAME                    CHART VERSION   APP VERSION     DESCRIPTION                                       
stable/mysql            0.15.0          5.7.14          Fast, reliable, scalable, and easy to use open-...
stable/mysqldump        2.4.0           2.4.0           A Helm chart to help backup MySQL databases usi..

使用helm inspect也能夠查看詳細信息

[root@master helm]# helm inspect stable/mysql

包括 DESCRIPTION 在內的全部信息,只要跟關鍵字匹配,都會顯示在結果列表中。
安裝 chart 也很簡單,執行以下命令能夠安裝 MySQL。

[root@master helm]# helm install stable/mysql
Error: no available release name found
#出現此類報錯主要是tiller權限的問題
[root@master helm]# kubectl create serviceaccount --namespace kube-system tiller
Error from server (AlreadyExists): serviceaccounts "tiller" already exists
[root@master helm]# kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
clusterrolebinding.rbac.authorization.k8s.io/tiller-cluster-rule created
[root@master helm]# kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
deployment.extensions/tiller-deploy patched (no change)

#再次安裝
[root@master helm]# helm install stable/mysql
NAME:   callous-zorse  #第一部分
LAST DEPLOYED: Thu Apr 11 09:31:41 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:   #第二部分
==> v1/Secret
NAME                 TYPE    DATA  AGE
callous-zorse-mysql  Opaque  2     0s

==> v1/ConfigMap
NAME                      DATA  AGE
callous-zorse-mysql-test  1     0s

==> v1/PersistentVolumeClaim
NAME                 STATUS   VOLUME  CAPACITY  ACCESS MODES  STORAGECLASS  AGE
callous-zorse-mysql  Pending  0s

==> v1/Service
NAME                 TYPE       CLUSTER-IP      EXTERNAL-IP  PORT(S)   AGE
callous-zorse-mysql  ClusterIP  10.109.125.202  <none>       3306/TCP  0s

==> v1beta1/Deployment
NAME                 DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
callous-zorse-mysql  1        1        1           0          0s

==> v1/Pod(related)
NAME                                 READY  STATUS   RESTARTS  AGE
callous-zorse-mysql-f5c97689b-ch5cf  0/1    Pending  0         0s


NOTES:  #第三部分
MySQL can be accessed via port 3306 on the following DNS name from within your cluster:
callous-zorse-mysql.default.svc.cluster.local

To get your root password run:

    MYSQL_ROOT_PASSWORD=$(kubectl get secret --namespace default callous-zorse-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echo)

To connect to your database:

1. Run an Ubuntu pod that you can use as a client:

    kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -il

2. Install the mysql client:

    $ apt-get update && apt-get install mysql-client -y

3. Connect using the mysql cli, then provide your password:
    $ mysql -h callous-zorse-mysql -p

To connect to your database directly from outside the K8s cluster:
    MYSQL_HOST=127.0.0.1
    MYSQL_PORT=3306

    # Execute the following command to route the connection:
    kubectl port-forward svc/callous-zorse-mysql 3306

    mysql -h ${MYSQL_HOST} -P${MYSQL_PORT} -u root -p${MYSQL_ROOT_PASSWORD}

輸出分爲三部分:

  1. chart 本次部署的描述信息:
    NAMErelease 的名字,由於咱們沒用 -n 參數指定,Helm 隨機生成了一個,這裏是 callous-zorse
    NAMESPACErelease 部署的 namespace,默認是 default,也能夠經過 --namespace 指定。
    STATUSDEPLOYED,表示已經將 chart 部署到集羣。
  2. 當前 release 包含的資源:ServiceDeploymentSecretPersistentVolumeClaim,其名字都是 callous-zorse-mysql,命名的格式爲 ReleasName-ChartName
  3. NOTES 部分顯示的是 release 的使用方法。好比如何訪問 Service,如何獲取數據庫密碼,以及如何鏈接數據庫等。
    經過 kubectl get 能夠查看組成 release 的各個對象:
[root@master helm]# kubectl get deploy,svc,pvc,secret callous-zorse-mysql
NAME                                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.extensions/callous-zorse-mysql   0/1     1            0           10m

NAME                          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/callous-zorse-mysql   ClusterIP   10.109.125.202   <none>        3306/TCP   10m

NAME                                        STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/callous-zorse-mysql   Pending                                                     10m

NAME                         TYPE     DATA   AGE
secret/callous-zorse-mysql   Opaque   2      10m

因爲咱們尚未準備 PersistentVolume,當前 release 還不可用。

helm list 顯示已經部署的 releasehelm delete 能夠刪除 release

[root@master helm]# helm list
NAME            REVISION        UPDATED                         STATUS          CHART           NAMESPACE
callous-zorse   1               Thu Apr 11 09:31:41 2019        DEPLOYED        mysql-0.15.0    default  
[root@master helm]# helm delete callous-zorse
release "callous-zorse" deleted

chart 目錄結構

chart 是 Helm 的應用打包格式。chart 由一系列文件組成,這些文件描述了 Kubernetes 部署應用時所須要的資源,好比 Service、Deployment、PersistentVolumeClaim、Secret、ConfigMap 等。

單個的 chart 能夠很是簡單,只用於部署一個服務,好比 Memcached;chart 也能夠很複雜,部署整個應用,好比包含 HTTP Servers、 Database、消息中間件、cache 等。

chart 將這些文件放置在預約義的目錄結構中,一般整個 chart 被打成 tar 包,並且標註上版本信息,便於 Helm 部署。

之前面 MySQL chart爲例。一旦安裝了某個 chart,咱們就能夠在 ~/.helm/cache/archive 中找到 chart 的 tar 包。

[root@master ~]# cd .helm/cache/archive/   
[root@master archive]# ls
mysql-0.15.0.tgz

[root@master archive]# tar xf mysql-0.15.0.tgz  
tar: mysql/Chart.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/values.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/NOTES.txt:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/_helpers.tpl:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/configurationFiles-configmap.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/deployment.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/initializationFiles-configmap.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/pvc.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/secrets.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/svc.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/tests/test-configmap.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/templates/tests/test.yaml:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/.helmignore:不可信的舊時間戳 1970-01-01 08:00:00
tar: mysql/README.md:不可信的舊時間戳 1970-01-01 08:00:00

[root@master archive]# tree
.
├── mysql
│   ├── Chart.yaml
│   ├── README.md
│   ├── templates
│   │   ├── configurationFiles-configmap.yaml
│   │   ├── deployment.yaml
│   │   ├── _helpers.tpl
│   │   ├── initializationFiles-configmap.yaml
│   │   ├── NOTES.txt
│   │   ├── pvc.yaml
│   │   ├── secrets.yaml
│   │   ├── svc.yaml
│   │   └── tests
│   │       ├── test-configmap.yaml
│   │       └── test.yaml
│   └── values.yaml
└── mysql-0.15.0.tgz

3 directories, 14 files
  • Chart.yaml:YAML 文件,描述 chart 的概要信息。
  • README.md:Markdown 格式的 README 文件,至關於 chart 的使用文檔,此文件爲可選。
  • LICENSE:文本文件,描述 chart 的許可信息,此文件爲可選。
  • requirements.yaml :chart 可能依賴其餘的 chart,這些依賴關係可經過 requirements.yaml 指定。
  • values.yaml:chart 支持在安裝的時根據參數進行定製化配置,而 values.yaml 則提供了這些配置參數的默認值。
  • templates目錄:各種 Kubernetes 資源的配置模板都放置在這裏。Helm 會將 values.yaml 中的參數值注入到模板中生成標準的 YAML 配置文件。
  • templates/NOTES.txt:chart 的簡易使用文檔,chart 安裝成功後會顯示此文檔內容。 與模板同樣,能夠在 NOTE.txt 中插入配置參數,Helm 會動態注入參數值。

chart模板

Helm 經過模板建立 Kubernetes 可以理解的 YAML 格式的資源配置文件,咱們將經過例子來學習如何使用模板。
以 templates/secrets.yaml 爲例:

{{- if not .Values.existingSecret }}
apiVersion: v1
kind: Secret
metadata:
  name: {{ template "mysql.fullname" . }}
  labels:
    app: {{ template "mysql.fullname" . }}
    chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    release: "{{ .Release.Name }}"
    heritage: "{{ .Release.Service }}"
type: Opaque
data:
  {{ if .Values.mysqlRootPassword }}
  mysql-root-password:  {{ .Values.mysqlRootPassword | b64enc | quote }}
  {{ else }}
  mysql-root-password: {{ randAlphaNum 10 | b64enc | quote }}
  {{ end }}
  {{ if .Values.mysqlPassword }}
  mysql-password:  {{ .Values.mysqlPassword | b64enc | quote }}
  {{ else }}
  mysql-password: {{ randAlphaNum 10 | b64enc | quote }}
  {{ end }}
{{- if .Values.ssl.enabled }}
{{ if .Values.ssl.certificates }}
{{- range .Values.ssl.certificates }}
---
apiVersion: v1
kind: Secret
metadata:
  name: {{ .name }}
  labels:
    app: {{ template "mysql.fullname" $ }}
    chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}"
    release: "{{ $.Release.Name }}"
    heritage: "{{ $.Release.Service }}"
type: Opaque
data:
  ca.pem: {{ .ca | b64enc }}
  server-cert.pem: {{ .cert | b64enc }}
  server-key.pem: {{ .key | b64enc }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}

從結構上看,文件的內容和咱們在定義Secret的配置上大體類似,只是大部分的屬性值變成了{{ xxx }}。這些{{ xx }}其實是模板的語法。Helm採用了Go語言的模板來編寫chart。

  • {{ template "mysql.fullname" . }} 定義 Secret 的 name
    關鍵字 template 的做用是引用一個子模板 mysql.fullname。這個子模板是在 templates/_helpers.tpl 文件中定義的。
[root@master templates]# vim _helpers.tpl
......
If release name contains chart name it will be used as a full name.
*/}}
{{- define "mysql.fullname" -}}
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- if contains $name .Release.Name -}}
{{- printf .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- end -}}
......

這個定義仍是很複雜的,由於它用到了模板語言中的對象、函數、流控制等概念。如今看不懂不要緊,這裏咱們學習的重點是:若是存在一些信息多個模板都會用到,則可在 templates/_helpers.tpl 中將其定義爲子模板,而後經過 templates 函數引用。
這裏 mysql.fullname 是由 release 與 chart 兩者名字拼接組成。
根據 chart 的最佳實踐,全部資源的名稱都應該保持一致,對於咱們這個 chart,不管 Secret 仍是 Deployment、PersistentVolumeClaim、Service,它們的名字都是子模板 mysql.fullname 的值。

  • ChartRelease 是 Helm 預約義的對象,每一個對象都有本身的屬性,能夠在模板中使用。若是使用下面命令安裝 chart:
[root@master templates]# helm search stable/mysql
NAME                    CHART VERSION   APP VERSION     DESCRIPTION                                       
stable/mysql            0.15.0          5.7.14          Fast, reliable, scalable, and easy to use open-...
stable/mysqldump        2.4.0           2.4.0           A Helm chart to help backup MySQL databases usi...
[root@master templates]# helm install stable/mysql -n my


{{ .Chart.Name }} 的值爲 mysql
{{ .Chart.Version }} 的值爲 0.15.0
{{ .Release.Name }}的值爲 my
{{ .Release.Service }} 始終取值爲 Tiller.
{{ template "mysql.fullname" . }} 計算結果爲 my-mysql。

  • 這裏指定 mysql-root-password 的值,不過使用了 if-else 的流控制,其邏輯爲:
    若是 .Values.mysqlRootPassword有值,則對其進行 base64 編碼;不然隨機生成一個 10 位的字符串並編碼。

Values 也是預約義的對象,表明的是values.yaml 文件。而 .Values.mysqlRootPassword 則是values.yaml中定義的 mysqlRootPassword參數:

[root@master mysql]# vim values.yaml 
## mysql image version
## ref: https://hub.docker.com/r/library/mysql/tags/
##
image: "mysql"
imageTag: "5.7.14"

busybox:
  image: "busybox"
  tag: "1.29.3"

testFramework:
  image: "dduportal/bats"
  tag: "0.4.0"

## Specify password for root user
##
## Default: random 10 character string
# mysqlRootPassword: testing

## Create a database user
##
# mysqlUser:
## Default: random 10 character string
# mysqlPassword:

由於 mysqlRootPassword 被註釋掉了,沒有賦值,因此邏輯判斷會走 else,即隨機生成密碼。

randAlphaNumb64encquote 都是 Go 模板語言支持的函數,函數之間能夠經過管道 | 鏈接。
{{ randAlphaNum 10 | b64enc | quote }} 的做用是首先隨機產生一個長度爲 10 的字符串,而後將其 base64 編碼,最後兩邊加上雙引號。
templates/secrets.yaml 這個例子展現了chart 模板主要的功能,咱們最大的收穫應該是:模板將 chart參數化了,經過 values.yaml 能夠靈活定製應用。

不管多複雜的應用,用戶均可以用 Go 模板語言編寫出 chart。無非是使用到更多的函數、對象和流控制

定製安裝 MySQL chart

chart安裝準備

做爲準備工做,安裝以前須要先清楚 chart 的使用方法。這些信息一般記錄在 values.yaml 和 README.md 中。除了下載源文件查看,執行 helm inspect values 多是更方便的方法。

[root@master helm]# helm inspect values stable/mysql       
## mysql image version
## ref: https://hub.docker.com/r/library/mysql/tags/
##
image: "mysql"
imageTag: "5.7.14"

busybox:
  image: "busybox"
  tag: "1.29.3"

testFramework:
  image: "dduportal/bats"
  tag: "0.4.0"

## Specify password for root user
##
## Default: random 10 character string
# mysqlRootPassword: testing

## Create a database user
##
# mysqlUser:
## Default: random 10 character string
# mysqlPassword:

## Allow unauthenticated access, uncomment to enable
##
# mysqlAllowEmptyPassword: true

## Create a database
##
# mysqlDatabase:

## Specify an imagePullPolicy (Required)
## It's recommended to change this to 'Always' if the image tag is 'latest'
## ref: http://kubernetes.io/docs/user-guide/images/#updating-images
##
imagePullPolicy: IfNotPresent

extraVolumes: |
  # - name: extras
  #   emptyDir: {}

extraVolumeMounts: |
  # - name: extras
  #   mountPath: /usr/share/extras
  #   readOnly: true

extraInitContainers: |
  # - name: do-something
  #   image: busybox
  #   command: ['do', 'something']

# Optionally specify an array of imagePullSecrets.
# Secrets must be manually created in the namespace.
# ref: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
# imagePullSecrets:
  # - name: myRegistryKeySecretName

## Node selector
## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
nodeSelector: {}

## Tolerations for pod assignment
## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
##
tolerations: []

livenessProbe:
  initialDelaySeconds: 30
  periodSeconds: 10
  timeoutSeconds: 5
  successThreshold: 1
  failureThreshold: 3

readinessProbe:
  initialDelaySeconds: 5
  periodSeconds: 10
  timeoutSeconds: 1
  successThreshold: 1
  failureThreshold: 3

## Persist data to a persistent volume
persistence:
  enabled: true
  ## database data Persistent Volume Storage Class
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  # storageClass: "-"
  accessMode: ReadWriteOnce
  size: 8Gi
  annotations: {}

## Configure resource requests and limits
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
##
resources:
  requests:
    memory: 256Mi
    cpu: 100m

# Custom mysql configuration files used to override default mysql settings
configurationFiles: {}
#  mysql.cnf: |-
#    [mysqld]
#    skip-name-resolve
#    ssl-ca=/ssl/ca.pem
#    ssl-cert=/ssl/server-cert.pem
#    ssl-key=/ssl/server-key.pem

# Custom mysql init SQL files used to initialize the database
initializationFiles: {}
#  first-db.sql: |-
#    CREATE DATABASE IF NOT EXISTS first DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
#  second-db.sql: |-
#    CREATE DATABASE IF NOT EXISTS second DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;

metrics:
  enabled: false
  image: prom/mysqld-exporter
  imageTag: v0.10.0
  imagePullPolicy: IfNotPresent
  resources: {}
  annotations: {}
    # prometheus.io/scrape: "true"
    # prometheus.io/port: "9104"
  livenessProbe:
    initialDelaySeconds: 15
    timeoutSeconds: 5
  readinessProbe:
    initialDelaySeconds: 5
    timeoutSeconds: 1

## Configure the service
## ref: http://kubernetes.io/docs/user-guide/services/
service:
  annotations: {}
  ## Specify a service type
  ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types
  type: ClusterIP
  port: 3306
  # nodePort: 32000

ssl:
  enabled: false
  secret: mysql-ssl-certs
  certificates:
#  - name: mysql-ssl-certs
#    ca: |-
#      -----BEGIN CERTIFICATE-----
#      ...
#      -----END CERTIFICATE-----
#    cert: |-
#      -----BEGIN CERTIFICATE-----
#      ...
#      -----END CERTIFICATE-----
#    key: |-
#      -----BEGIN RSA PRIVATE KEY-----
#      ...
#      -----END RSA PRIVATE KEY-----

## Populates the 'TZ' system timezone environment variable
## ref: https://dev.mysql.com/doc/refman/5.7/en/time-zone-support.html
##
## Default: nil (mysql will use image's default timezone, normally UTC)
## Example: 'Australia/Sydney'
# timezone:

# To be added to the database server pod(s)
podAnnotations: {}

podLabels: {}

## Set pod priorityClassName
# priorityClassName: {}

輸出的其實是 values.yaml 的內容。閱讀註釋就能夠知道 MySQL chart 支持哪些參數,安裝以前須要作哪些準備。其中有一部分是關於存儲的:

## Persist data to a persistent volume
persistence:
  enabled: true
  ## database data Persistent Volume Storage Class
  ## If defined, storageClassName: <storageClass>
  ## If set to "-", storageClassName: "", which disables dynamic provisioning
  ## If undefined (the default) or set to null, no storageClassName spec is
  ##   set, choosing the default provisioner.  (gp2 on AWS, standard on
  ##   GKE, AWS & OpenStack)
  ##
  # storageClass: "-"
  accessMode: ReadWriteOnce
  size: 8Gi
  annotations: {}

chart 定義了一個 PersistentVolumeClaim,申請 8G 的 PersistentVolume。因爲咱們的實驗環境不支持動態供給,因此得預先建立好相應的 PV,其配置文件 mysql-pv.yml 內容爲:

[root@master helm]# cd ../volume/
[root@master volume]# vim mysql-pv.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: mysql-pv2
spec:
  accessModes:
    - ReadWriteOnce
  capacity:
    storage: 8Gi
  persistentVolumeReclaimPolicy: Retain
  nfs:
    path: /data/volume/db
    server: nfs
    
[root@master volume]# kubectl apply -f mysql-pv.yaml 
persistentvolume/mysql-pv2 created
[root@master volume]# kubectl get pv   
NAME        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM                       STORAGECLASS   REASON   AGE
mysql-pv2   8Gi        RWO            Retain           Bound       default/my-mysql                                    30s

定製化安裝 chart

除了接受 values.yaml 的默認值,咱們還能夠定製化 chart,好比設置 mysqlRootPassword
Helm有兩種方式傳遞配置參數:

  • 指定本身的values文件,一般是先經過helm inspect values mysql > myvalues.yaml生成values,而後設置mysqlRootPassword以後執行 helm install --values=myvalues.yaml mysql
  • 經過 --set 直接傳入參數值,好比:
[root@master helm]# helm install stable/mysql --set mysqlRootPassword=abc123 -n my-2
NAME:   my-2
LAST DEPLOYED: Thu Apr 11 11:26:33 2019
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME        TYPE       CLUSTER-IP     EXTERNAL-IP  PORT(S)   AGE
my-2-mysql  ClusterIP  10.97.198.107  <none>       3306/TCP  1s

==> v1beta1/Deployment
NAME        DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
my-2-mysql  1        1        1           0          1s

==> v1/Pod(related)
NAME                         READY  STATUS   RESTARTS  AGE
my-2-mysql-5dc69d7d66-rmt2z  0/1    Pending  0         1s

==> v1/Secret
NAME        TYPE    DATA  AGE
my-2-mysql  Opaque  2     1s

==> v1/ConfigMap
NAME             DATA  AGE
my-2-mysql-test  1     1s

==> v1/PersistentVolumeClaim
NAME        STATUS   VOLUME  CAPACITY  ACCESS MODES  STORAGECLASS  AGE
my-2-mysql  Pending  1s
......

mysqlRootPassword設置爲 abc123。另外,-n設置elease 爲 my-2,各種資源的名稱即爲my-2-mysql

經過 helm listhelm status 能夠查看 chart 的最新狀態。

升級和回滾release

release 發佈後能夠執行 helm upgrade 對其升級,經過 --values 或 --set應用新的配置。好比將當前的 MySQL 版本升級到 5.7.15:

[root@master helm]# helm upgrade --set imageTag=5.7.15 my stable/mysql

helm history 能夠查看 release 全部的版本。經過 helm rollback 能夠回滾到任何版本。

[root@master helm]# helm history my-2 
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION     
1               Thu Apr 11 11:26:33 2019        SUPERSEDED      mysql-0.15.0    Install complete
2               Thu Apr 11 11:29:41 2019        DEPLOYED        mysql-0.15.0    Upgrade complete

[root@master helm]# helm rollback my-2 1
Rollback was a success! Happy Helming!

[root@master helm]# helm history my-2
REVISION        UPDATED                         STATUS          CHART           DESCRIPTION     
1               Thu Apr 11 11:26:33 2019        SUPERSEDED      mysql-0.15.0    Install complete
2               Thu Apr 11 11:29:41 2019        SUPERSEDED      mysql-0.15.0    Upgrade complete
3               Thu Apr 11 11:30:21 2019        DEPLOYED        mysql-0.15.0    Rollback to 1

自定義chart

Kubernetes 給咱們提供了大量官方 chart,不過要部署微服務應用,仍是須要開發本身的 chart。

建立chart

執行 helm create mychart 的命令建立 chart mychart

[root@master helm]# cd mychart/
[root@master mychart]# tree
.
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── ingress.yaml
│   ├── NOTES.txt
│   └── service.yaml
└── values.yaml

2 directories, 7 files

Helm 會幫咱們建立目錄 mychart,並生成了各種 chart 文件。這樣咱們就能夠在此基礎上開發本身的 chart 了。

調試chart

elm 提供了 debug 的工具:helm linthelm install --dry-run --debug
helm lint會檢測 chart 的語法,報告錯誤以及給出建議。 故意修改mychart中的value.yaml,進行檢測:
helm lint mychart會指出這個語法錯誤。

[root@master helm]# helm lint mychart
==> Linting mychart
[INFO] Chart.yaml: icon is recommended
[ERROR] values.yaml: unable to parse YAML
        error converting YAML to JSON: yaml: line 12: could not find expected ':'

Error: 1 chart(s) linted, 1 chart(s) failed

1 chart(s) linted, no failures
[root@master helm]# helm lint mychart
==> Linting mychart
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, no failures

helm install --dry-run --debug 會模擬安裝 chart,並輸出每一個模板生成的 YAML 內容。

[root@master helm]# helm install --dry-run mychart --debug
[debug] Created tunnel using local port: '28515'

[debug] SERVER: "127.0.0.1:28515"

[debug] Original chart version: ""
[debug] CHART PATH: /root/manifests/helm/mychart

NAME:   early-marsupial
REVISION: 1
RELEASED: Thu Apr 11 11:40:39 2019
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: early-marsupial-mychart
  labels:
    app: mychart
    chart: mychart-0.1.0
    release: early-marsupial
    heritage: Tiller
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: http
      protocol: TCP
      name: http
  selector:
    app: mychart
    release: early-marsupial
---
# Source: mychart/templates/deployment.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: early-marsupial-mychart
  labels:
    app: mychart
    chart: mychart-0.1.0
    release: early-marsupial
    heritage: Tiller
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mychart
      release: early-marsupial
  template:
    metadata:
      labels:
        app: mychart
        release: early-marsupial
    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:
            {}

咱們能夠檢視這些輸出,判斷是否與預期相符。

安裝chart

Helm自持四種方法安裝chart:

  • 安裝倉庫中的 chart,例如:helm install stable/nginx
  • 經過 tar 包安裝,例如:helm install ./nginx-1.2.3.tgz
  • 經過 chart 本地目錄安裝,例如:helm install ./nginx
  • 經過 URL 安裝,例如:helm install https://example.com/charts/nginx-1.2.3.tgz

本次使用本地目錄安裝

[root@master helm]# helm install ./mychart/ 
NAME:   soft-worm
LAST DEPLOYED: Thu Apr 11 13:43:18 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1beta2/Deployment
NAME               DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
soft-worm-mychart  1        1        1           0          0s

==> v1/Pod(related)
NAME                               READY  STATUS   RESTARTS  AGE
soft-worm-mychart-78ccf58c6-t6jp5  0/1    Pending  0         0s

==> v1/Service
NAME               TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)  AGE
soft-worm-mychart  ClusterIP  10.103.92.36  <none>       80/TCP   0s


NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=soft-worm" -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

當 chart 部署到 Kubernetes 集羣,即可以對其進行更爲全面的測試。

將chart添加到倉庫

chart 經過測試後能夠將其添加到倉庫,團隊其餘成員就可以使用。任何 HTTP Server 均可以用做 chart 倉庫,下面演示在 nfs 10.0.0.14 上搭建倉庫。

在nfs上啓動nginx(容器也能夠)並建立一個server標籤(因爲實驗用nfs已經有nginx服務,新建個server標籤監聽8080端口)

......
    server {
        listen       8080;
        location / {
        root         /data/;
        }
        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        }
.....
[root@nfs ~]# mkdir /data/charts/ -p
[root@nfs ~]#  nginx -s reload

經過 helm package 將 mychart 打包。

[root@master helm]# helm package ./mychart/
Successfully packaged chart and saved it to: /root/manifests/helm/mychart-0.1.0.tgz
#執行 helm repo index 生成倉庫的 index 文件
[root@master helm]# helm package ./mychart/
Successfully packaged chart and saved it to: /root/manifests/helm/mychart-0.1.0.tgz
[root@master helm]# mkdir myrepo
[root@master helm]# mv /root/manifests/helm/mychart-0.1.0.tgz ./myrepo/
[root@master helm]# helm repo index ./myrepo/ --url http://10.0.0.14:8080/charts
[root@master helm]# ls myrepo/
index.yaml  mychart-0.1.0.tgz

Helm 會掃描 myrepo 目錄中的全部 tgz 包並生成 index.yaml。--url指定的是新倉庫的訪問路徑。新生成的 index.yaml 記錄了當前倉庫中全部 chart 的信息:
當前只有 mychart 這一個 chart。

[root@master helm]# cat myrepo/index.yaml 
apiVersion: v1
entries:
  mychart:
  - apiVersion: v1
    appVersion: "1.0"
    created: 2019-04-11T14:18:48.494631141+08:00
    description: A Helm chart for Kubernetes
    digest: 08abeb3542e8a9ab90df776d3a646199da8be0ebfc5198ef032190938d49e30a
    name: mychart
    urls:
    - http://10.0.0.14:8080/charts/mychart-0.1.0.tgz
    version: 0.1.0
generated: 2019-04-11T14:18:48.494210001+08:00

將 mychart-0.1.0.tgz 和 index.yaml 上傳到 k8s-node1 的 /var/www/charts 目錄。

[root@master helm]# scp ./myrepo/* nfs:/data/charts/
index.yaml                                                              100%  394   407.6KB/s   00:00    
mychart-0.1.0.tgz                                                       100% 2556     2.8MB/s   00:00

經過 helm repo add 將新倉庫添加到 Helm。

[root@master helm]# helm repo add nfs_repo http://10.0.0.14:8080/charts
"nfs_repo" has been added to your repositories
[root@master helm]# helm repo list 
NAME            URL                                             
stable          https://kubernetes-charts.storage.googleapis.com
local           http://127.0.0.1:8879/charts                    
nfs_repo        http://10.0.0.14:8080/charts

如今已經能夠 repo search 到 mychart 了。
[root@master helm]# helm search mychart NAME CHART VERSION APP VERSION DESCRIPTION local/mychart 0.1.0 1.0 A Helm chart for Kubernetes nfs_repo/mychart 0.1.0 1.0 A Helm chart for Kubernetes
除了 newrepo/mychart,這裏還有一個 local/mychart。這是由於在執行打包操做的同時,mychart 也被同步到了 local 的倉庫。

已經能夠直接重新倉庫安裝 mychart 了。

[root@master helm]# helm install --name my-3 nfs_repo/mychart
NAME:   my-3
LAST DEPLOYED: Thu Apr 11 14:26:53 2019
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                           READY  STATUS             RESTARTS  AGE
my-3-mychart-69cdddc4fb-cljmt  0/1    ContainerCreating  0         0s

==> v1/Service
NAME          TYPE       CLUSTER-IP    EXTERNAL-IP  PORT(S)  AGE
my-3-mychart  ClusterIP  10.97.149.58  <none>       80/TCP   0s

==> v1beta2/Deployment
NAME          DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
my-3-mychart  1        1        1           0          0s


NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=my-3" -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

若是之後倉庫添加了新的 chart,須要用 helm repo update 更新本地的 index。相似於yum update /apt-get update

[root@master helm]# helm repo update
Hang tight while we grab the latest from your chart repositories...
...Skip local chart repository
...Successfully got an update from the "nfs_repo" chart repository
...Unable to get an update from the "stable" chart repository (https://kubernetes-charts.storage.googleapis.com):
        Get https://kubernetes-charts.storage.googleapis.com/index.yaml: dial tcp 172.217.161.176:443: connect: connection timed out
Update Complete. ⎈ Happy Helming!⎈

總結

  • Helm是Kubernetes的包管理器,Helm 讓咱們可以像 yum 管理 rpm 包那樣安裝、部署、升級和刪除容器化應用。
  • Helm 由客戶端和 Tiller 服務器組成。客戶端負責管理 chart,服務器負責管理 release。
  • chart 是 Helm 的應用打包格式,它由一組文件和目錄構成。其中最重要的是模板,模板中定義了 Kubernetes 各種資源的配置信息,Helm 在部署時經過 values.yaml 實例化模板。
  • Helm 容許用戶開發本身的 chart,併爲用戶提供了調試工具。用戶能夠搭建本身的 chart 倉庫,在團隊中共享 chart。
參考資料

https://www.cnblogs.com/linuxk

相關文章
相關標籤/搜索