是時候使用Helm了:Helm, Kubernetes的包管理工具_Kubernetes中文社群
目前我們的一個產品共有4套環境:dev環境、test環境、staging環境、production環境。 其中dev, test, staging環境在一個Kubernetes叢集上以不同namespace部署,production環境部署在另一個Kubernetes叢集上。這個產品總共有14個微服務組成,對應gitlab中14個程式碼庫,Kubernetes的deployment yaml檔案也儲存在程式碼庫,為每個服務的每套環境以環境名建立了一個目錄,裡面是yaml檔案,yaml檔案的內容使用sed實現了簡單的模板功能。14個服務*4套環境總共56個yaml檔案,比較原始。
最近需要新起另外的一套測試環境這裡稱它為test2吧,需要在第一個Kubernetes叢集上建立新的namespace,要維護的yaml檔案馬上也要增加到70個,有點噩夢的感覺了。 因此我們需要一個模板工具來管理這些yaml檔案。早就知道helm這個東西,但為了保持簡單,一直遵循著最少引入新東西的原則,那麼現在是時候使用Helm了吧?
1.Helm的基本概念
Helm是Kubernetes的一個包管理工具,用來簡化Kubernetes應用的部署和管理。可以把Helm比作CentOS的yum工具。 Helm有如下幾個基本概念:
- Chart: 是Helm管理的安裝包,裡面包含需要部署的安裝包資源。可以把Chart比作CentOS yum使用的rpm檔案。每個Chart包含下面兩部分:
- 包的基本描述檔案Chart.yaml
- 放在templates目錄中的一個或多個Kubernetes manifest檔案模板
- Release:是chart的部署例項,一個chart在一個Kubernetes叢集上可以有多個release,即這個chart可以被安裝多次
- Repository:chart的倉庫,用於釋出和儲存chart
使用Helm可以完成以下事情:
- 管理Kubernetes manifest files
- 管理Helm安裝包charts
- 基於chart的Kubernetes應用分發
2.Helm的組成
Helm由兩部分組成,客戶端helm和服務端tiller。
- tiller執行在Kubernetes叢集上,管理chart安裝的release
- helm是一個命令列工具,可在本地執行,一般執行在CI/CD Server上。
3.Helm的安裝
我們將在Kubernetes 1.8上安裝Helm。
3.1 客戶端helm和服務端tiller
首先從這裡下載Helm的二進位制檔案. 這裡下載的是helm 2.7.2,解壓縮後將可執行檔案helm拷貝到/usr/local/bin下。這樣客戶端helm就在這臺機器上安裝完成了。
此時執行helm version可以打印出客戶端helm的版本,同時會提示無法連線到服務端Tiller。
helm version Client: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"} Error: cannot connect to Tiller
為了安裝服務端tiller,還需要在這臺機器上配置好kubectl工具和kubeconfig檔案,確保kubectl工具可以在這臺機器上訪問apiserver且正常使用。
kubectl get cs NAME STATUS MESSAGE ERROR scheduler Healthy ok controller-manager Healthy ok etcd-4 Healthy {"health": "true"} etcd-0 Healthy {"health": "true"} etcd-2 Healthy {"health": "true"} etcd-3 Healthy {"health": "true"} etcd-1 Healthy {"health": "true"}
使用helm在k8s上部署tiller:
helm init --service-account tiller --skip-refresh 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.
注意由於某些原因需要網路可以訪問gcr.io和kubernetes-charts.storage.googleapis.com,如果無法訪問可以通過helm init –service-account tiller –tiller-image <your-docker-registry>/tiller:2.7.2 –skip-refresh使用私有映象倉庫中的tiller映象
tiller預設被部署在k8s叢集中的kube-system這個namespace下。
kubectl get pod -n kube-system -l app=helm NAME READY STATUS RESTARTS AGE tiller-deploy-587df449fb-c6tzp 1/1 Running 0 9m
再次helm version可以列印客戶端和服務端的版本:
helm version Client: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.7.2", GitCommit:"8478fb4fc723885b155c924d1c8c410b7a9444e6", GitTreeState:"clean"}
3.2 Kubernetes RBAC配置
因為我們將tiller部署在Kubernetes 1.8上,Kubernetes APIServer開啟了RBAC訪問控制,所以我們需要建立tiller使用的service account: tiller並分配合適的角色給它。 詳細內容可以檢視helm文件中的Role-based Access Control。 這裡簡單起見直接分配cluster-admin這個叢集內建的ClusterRole給它。
建立rbac-config.yaml檔案:
apiVersion: v1 kind: ServiceAccount metadata: name: tiller namespace: kube-system --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: tiller roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-admin subjects: - kind: ServiceAccount name: tiller namespace: kube-system
kubectl create -f rbac-config.yaml serviceaccount "tiller" created clusterrolebinding "tiller" created
4.Helm的基本使用
已經安裝helm的客戶端helm和服務端tiller,下面要熟悉如何使用helm管理Kubernetes叢集的安裝包。
更新chart repo:
helm repo update
實際上如果helm所在的機器訪問不了google的話,會報錯,因為訪問不了 “stable” chart repository (https://kubernetes-charts.storage.googleapis.com)
4.1 建立一個chart
下面我們開始嘗試建立一個chart,這個chart用來部署一個簡單的服務。
helm create hello-svc Creating hello-svc tree hello-svc/ hello-svc/ ├── charts ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── ingress.yaml │ ├── NOTES.txt │ └── service.yaml └── values.yaml 2 directories, 7 files
先熟悉一下hello-svc這個chart中目錄和檔案內容:
- charts目錄中是本chart依賴的chart,當前是空的
- Chart.yaml這個yaml檔案用於描述Chart的基本資訊,如名稱版本等
cat Chart.yaml apiVersion: v1 description: A Helm chart for Kubernetes name: hello-svc version: 0.1.0
- templates是Kubernetes manifest檔案模板目錄,模板使用chart配置的值生成Kubernetes manifest檔案。模板檔案使用的Go語言模板語法
- templates/NOTES.txt 純文字檔案,可在其中填寫chart的使用說明
- value.yaml 是chart配置的預設值
通過檢視deployment.yaml和value.yaml,大概知道這個chart預設安裝就是在Kubernetes部署一個nginx服務。
更多Chart的內容可以檢視Chart官方文件
4.2 對chart的模板和配置進行測試
使用helm在Kubernetes上安裝chart時,實際上是將chart的模板生成Kubernetes使用的manifest yaml檔案。 在編寫chart的過程中可以chart目錄下使用helm install –dry-run –debug ./來驗證模板和配置。
helm install --dry-run --debug ./ [debug] Created tunnel using local port: '22635' [debug] SERVER: "127.0.0.1:22635" [debug] Original chart version: "" [debug] CHART PATH: /root/helm/hello-svc NAME: foolish-zebra REVISION: 1 ......輸出基於配置值和模板生成的yaml檔案
4.3 在Kubernetes上安裝chart
在hello-svc這個chart目錄下執行:
helm install ./ NAME: wishful-squid LAST DEPLOYED: Thu Dec 21 22:04:19 2017 NAMESPACE: default STATUS: DEPLOYED RESOURCES: ==> v1/Service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE wishful-squid-hello-svc ClusterIP 10.111.223.243 <none> 80/TCP 0s ==> v1beta1/Deployment NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE wishful-squid-hello-svc 1 0 0 0 0s ==> v1/Pod(related) NAME READY STATUS RESTARTS AGE wishful-squid-hello-svc-6bbb59dfb6-smvz5 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=hello-svc,release=wishful-squid" -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
檢視release:
helm list NAME REVISION UPDATED STATUS CHART NAMESPACE wishful-squid 1 Thu Dec 21 22:04:19 2017 DEPLOYED hello-svc-0.1.0 default
刪除release:
helm delete wishful-squid release "wishful-squid" deleted
4.4 chart的分發
打包:
helm package ./ tree . ├── charts ├── Chart.yaml ├── hello-svc-0.1.0.tgz ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── ingress.yaml │ ├── NOTES.txt │ └── service.yaml └── values.yaml