在Kubernetes中部署容器雲的應用也是一項有挑戰性的工做,Helm就是爲了簡化在Kubernetes中安裝部署容器雲應用的一個客戶端工具。經過helm可以幫助開發者定義、安裝和升級Kubernetes中的容器雲應用,同時,也能夠經過helm進行容器雲應用的分享。在Kubeapps Hub中提供了包括Redis、MySQL和Jenkins等常見的應用,經過helm可使用一條命令就可以將其部署安裝在本身的Kubernetes集羣中。node
Helm是一個用於kubernetes的包管理器。每一個包稱爲一個Chart,一個Chart是一個目錄(通常狀況下會將目錄進行打包壓縮,造成name-version.tgz格式的單一文件,方便傳輸和存儲)。咱們能夠將Helm看做Kubernetes下的apt-get/yum。mysql
對於應用發佈者而言,能夠經過Helm打包應用,管理應用依賴關係,管理應用版本併發布應用到軟件倉庫。linux
Helm組件及相關術語nginx
1)Helm Helm是一個命令行下的客戶端工具。主要用於Kubernetes應用程序Chart的建立、打包、發佈及建立和管理 本地和遠程的Chart倉庫。 2)Tiller Tiller是Helm的服務端,部署在Kubernetes集羣中,Tiller用於接收Helm的請求,並根據Chart生成Kubernete s的部署文件,而後提交給Kubernetes建立應用,Tiller還提供和了Release的升級、刪除、回滾等一系列功能。 3)Chart Chart是一個Helm的程序包,包含了運行一個Kubernetes應用程序所需的鏡像、依賴關係和資源定義等。 4)Repoistory Repoistory是Helm的軟件倉庫,Repository本質上是一個Web服務器,該服務器保存了一系列的Chart軟件包 以供用戶下載,而且提供了該Repository的Chart包的清單文件便於查詢。Helm能夠同時管理多個不一樣的Repository。 5)Release Release是應用程序運行Chart以後,獲得的一個實例。
elm架構
helm的總體架構以下圖所示,Helm架構由Helm客戶端、Tiller服務器端和Chart倉庫所組成;Tiller部署在Kubernetes中,Helm客戶端從Chart倉庫中獲取Chart安裝包,並將其安裝部署到Kubernetes集羣中。
web
Chart install過程: 1)Helm從指定的目錄或者tgz文件中解析出Chart結構信息; 2)Helm將指定的Chart結構和Values信息經過gRPC傳遞給Tiller; 3)Tiller根據Chart和Values生成一個Release; 4)Tiller將Release發送給Kubernetes用於生成Release; --- Chart update過程: 1)Helm從指定的目錄或者tgz文件中解析出Chart結構信息; 2)Helm將要更新的Release的名稱和Chart結構、Values信息傳遞給Tiller; 3)Tiller生成Release並更新指定名稱的Release的history; 4)Tiller將Release發送給Kubernetes用於更新Release; --- Chart Rollback過程: 1)Helm將要回滾的Release的名稱傳遞給Tiller; 2)Tiller根據Release的名稱查找history; 3)Tiller從history中獲取上一個Release; 4)Tiller將上一個Release發送給Kubernetes用於替換當前的Release;
1)安裝Helm客戶端sql
[root@master ~]# wget https://get.helm.sh/helm-v2.14.3-linux-amd64.tar.gz //從Github上下載Helm軟件包 [root@master ~]# tar zxf helm-v2.14.3-linux-amd64.tar.gz [root@master ~]# mv linux-amd64/helm /usr/local/bin/ [root@master ~]# chmod +x /usr/local/bin/helm //獲取這個軟件包只是爲了獲取這個helm文件 [root@master ~]# echo 'source <(helm completion bash)' >> /etc/profile [root@master ~]# source /etc/profile //設置helm命令能夠自動補全而且寫入環境變量文件中
2)安裝Tiller server(須要建立受權用戶)docker
[root@master ~]# vim tiller-rbac.yaml //編寫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 [root@master ~]# kubectl apply -f tiller-rbac.yaml [root@master ~]# helm init --service-account=tiller //Tiller server的環境初始化 //helm的服務端就是Tiller //指定剛纔建立的受權用戶初始化helm [root@master ~]# kubectl get pod -n kube-system | grep tiller //查看tiller的pod名稱 tiller-deploy-8557598fbc-mlr6c 0/1 ContainerCreating 0 6s //編輯pod的yaml文件,將其使用的鏡像改成國內阿里雲的,默認是Google的鏡像,下載不下來 //修改spec字段的image指定的鏡像,以下: [root@master ~]# kubectl edit pod -n kube-system tiller-deploy-8557598fbc-mlr6c //修改spec字段的image指定的鏡像,以下: image: gcr.io/kubernetes-helm/tiller:v2.14.3 //修改後以下: image: registry.cn-hangzhou.aliyuncs.com/google_containers/tiller:v2.14.3 //修改後,保存退出便可,它會去自動下載新鏡像(若是沒有自動下載,就想辦法吧,好比說在tiller容器所在的節點手動下載下來鏡像,而後重啓該節點的kubelet,或重啓該容器) [root@master ~]# kubectl get pod -n kube-system | grep tiller //必須保證tiller的Pod正常運行 tiller-deploy-8557598fbc-mlr6c 1/1 Running 0 5m16s
注:避免出錯附加一張圖片以下:
數據庫
3)配置Helm倉庫apache
[root@master ~]# helm repo list //查看倉庫的詳細信息 NAME URL stable https://kubernetes-charts.storage.googleapis.com //默認是Google,在國外,速度特別慢 local http://127.0.0.1:8879/charts [root@master ~]# helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts //更改成國內阿里雲的地址 [root@master ~]# helm repo list //再次查看倉庫的詳細信息,能夠發現地址已經換成了阿里雲的倉庫地址 NAME URL stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts local http://127.0.0.1:8879/charts [root@master ~]# helm repo update //更新一下helm倉庫 [root@master ~]# helm version //查看helm版本信息 Client: &version.Version{SemVer:"v2.14.3", GitCommit:"0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085", GitTreeState:"clean"} Server: &version.Version{SemVer:"v2.14.3", GitCommit:"0e7f3b6637f7af8fcfddb3d2941fcc7cbebb0085", GitTreeState:"clean"} //必須保證能夠查看出來client和server,纔可正常使用helm
注:就此Helm就已經表示部署成功,能夠正常使用!vim
建立Storage Class
1)部署nfs
[root@master ~]# yum -y install nfs-utils rpcbind [root@master ~]# mkdir /nfsdata [root@master ~]# echo "/nfsdata *(rw,no_root_squash,sync)" > /etc/exports [root@master ~]# systemctl start nfs-server && systemctl start rpcbind [root@master ~]# showmount -e Export list for master: /nfsdata *
2)建立rbac受權
[root@master ~]# vim rbac-rolebind.yaml //編輯yaml文件 apiVersion: v1 //建立一個用於認證的服務帳號 kind: ServiceAccount metadata: name: nfs-provisioner --- apiVersion: rbac.authorization.k8s.io/v1 //建立羣集規則 kind: ClusterRole metadata: name: nfs-provisioner-runner rules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["watch", "create", "update", "patch"] - apiGroups: [""] resources: ["services", "endpoints"] verbs: ["get","create","list", "watch","update"] - apiGroups: ["extensions"] resources: ["podsecuritypolicies"] resourceNames: ["nfs-provisioner"] verbs: ["use"] --- kind: ClusterRoleBinding //將服務認證用戶與羣集規則進行綁定 apiVersion: rbac.authorization.k8s.io/v1 metadata: name: run-nfs-provisioner subjects: - kind: ServiceAccount name: nfs-provisioner namespace: default roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io [root@master ~]# kubectl apply -f rbac-rolebind.yaml //執行yaml文件
3)建立nfs-deployment.資源
[root@master ~]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nfs-client-provisioner spec: replicas: 1 //指定副本數量爲1 strategy: type: Recreate //指定策略類型爲重置 template: metadata: labels: app: nfs-client-provisioner spec: serviceAccount: nfs-provisioner //指定rbac yaml文件中建立的認證用戶帳號 containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner //使用的鏡像 volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes //指定容器內掛載的目錄 env: - name: PROVISIONER_NAME //容器內的變量用於指定提供存儲的名稱 value: bjq-test - name: NFS_SERVER //容器內的變量用於指定nfs服務的IP地址 value: 192.168.45.129 - name: NFS_PATH //容器內的變量指定nfs服務器對應的目錄 value: /nfsdata volumes: //指定掛載到容器內的nfs的路徑及IP - name: nfs-client-root nfs: server: 192.168.45.129 path: /nfsdata //編輯完成保存退出便可 [root@master ~]# kubectl apply -f nfs-deployment.yaml //執行yaml文件 [root@master ~]# kubectl get pod | grep nfs //確認pod是否正常運行 nfs-client-provisioner-8844fb875-prjhq 1/1 Running 0 14s
4)建立Storage Class
[root@master ~]# vim storage-class.yaml //編輯yaml文件 apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: stateful-nfs provisioner: bjq-test //這個要和nfs-client-provisioner的env環境變量中的PROVISIONER_NAME的value值對應。 reclaimPolicy: Retain //指定回收策略爲Retain(手動釋放) [root@master ~]# kubectl apply -f storage-class.yaml //執行yaml文件 [root@master ~]# kubectl get sc //確認Storage Class建立成功 NAME PROVISIONER AGE stateful-nfs bjq-test 8s
5)helm部署mysql
[root@master ~]# helm fetch stable/mysql //將mysql的軟件包下載到本地 [root@master ~]# tar zxf mysql-0.3.5.tgz [root@master ~]# vim mysql/values.yaml +55 storageClass: "stateful-nfs" //去除註釋,並指定剛纔建立的Storage Class名稱 [root@master ~]# vim mysql/values.yaml +79 type: NodePort //默認是ClusterIP,可更改成NodePort [root@master ~]# helm install stable/mysql -f mysql/values.yaml --set mysqlRootPassword=123.com -n test-mysql //若是修改了values.yaml文件的數據,建立時應該指定values.yaml文件 //安裝mysql,並設置mysql的root密碼爲123.com,-n表示指定名稱 root@master ~]# helm list //查看已安裝的軟件包 NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE test-mysql 1 Tue Sep 1 13:26:01 2020 DEPLOYED mysql-0.3.5 default
避免出錯附加一張圖片:
[root@master ~]# kubectl get svc | grep test-mysql //確認service類型 test-mysql-mysql NodePort 10.98.129.4 <none> 3306:30083/TCP 4m56s [root@master ~]# kubectl get pv,pvc //查看PV、PVC是否綁定成功 NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE persistentvolume/pvc-4ebb3a43-b192-4e2d-884a-2b75308f63dd 8Gi RWO Delete Bound default/test-mysql-mysql stateful-nfs 5m5s NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE persistentvolumeclaim/test-mysql-mysql Bound pvc-4ebb3a43-b192-4e2d-884a-2b75308f63dd 8Gi RWO stateful-nfs 5m5s [root@master ~]# kubectl exec -it test-mysql-mysql-dfb9b6944-q7tcd -- mysql -u root -p123.com //登陸到剛纔建立的mysql數據庫中 mysql>
6)使用helm對mysql進行升級操做
[root@master ~]# kubectl describe pod test-mysql-mysql-dfb9b6944-q7tcd //查看pod的詳細信息如下能夠看出,該pod所用鏡像爲mysql:5.7.14 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 8m57s (x2 over 8m57s) default-scheduler pod has unbound immediate PersistentVolumeClaims (repeated 2 times) Normal Scheduled 8m56s default-scheduler Successfully assigned default/test-mysql-mysql-dfb9b6944-q7tcd to node02 Normal Pulling 8m55s kubelet, node02 Pulling image "busybox:1.25.0" Normal Pulled 8m46s kubelet, node02 Successfully pulled image "busybox:1.25.0" Normal Created 8m46s kubelet, node02 Created container remove-lost-found Normal Started 8m46s kubelet, node02 Started container remove-lost-found Normal Pulling 8m46s kubelet, node02 Pulling image "mysql:5.7.14" Normal Pulled 8m24s kubelet, node02 Successfully pulled image "mysql:5.7.14" Normal Created 8m24s kubelet, node02 Created container test-mysql-mysql Normal Started 8m24s kubelet, node02 Started container test-mysql-mysql [root@master ~]# kubectl get pod | grep test-mysql //注意升級以後,pod名稱會發生變化 test-mysql-mysql-54c7bfdd77-8jlpj 1/1 Running 0 2m54s [root@master ~]# kubectl describe pod test-mysql-mysql-54c7bfdd77-8jlpj //再次查看pod詳細信息,能夠看出,鏡像升級爲mysql:5.7.15 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 4m1s default-scheduler Successfully assigned default/test-mysql-mysql-54c7bfdd77-8jlpj to node01 Normal Pulling 4m1s kubelet, node01 Pulling image "busybox:1.25.0" Normal Pulled 3m50s kubelet, node01 Successfully pulled image "busybox:1.25.0" Normal Created 3m50s kubelet, node01 Created container remove-lost-found Normal Started 3m50s kubelet, node01 Started container remove-lost-found Normal Pulling 3m50s kubelet, node01 Pulling image "mysql:5.7.15" Normal Pulled 3m25s kubelet, node01 Successfully pulled image "mysql:5.7.15" Normal Created 3m25s kubelet, node01 Created container test-mysql-mysql Normal Started 3m25s kubelet, node01 Started container test-mysql-mysql
7)使用helm對mysql進行回滾操做
[root@master ~]# helm list //再次查看實例,能夠發現「REVISION」字段爲2,而初次建立實例時,該列爲1,只要對該實例進行升級回滾一次,數值便會加1 NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE test-mysql 2 Tue Sep 1 13:37:45 2020 DEPLOYED mysql-0.3.5 default [root@master ~]# helm history test-mysql //查看該實例的歷史版本 REVISION UPDATED STATUS CHART DESCRIPTION 1 Tue Sep 1 13:26:01 2020 SUPERSEDED mysql-0.3.5 Install complete 2 Tue Sep 1 13:37:45 2020 DEPLOYED mysql-0.3.5 Upgrade complete [root@master ~]# helm rollback test-mysql 1 //將該實例回滾到版本1 [root@master ~]# helm list //再次查看,能夠看到「REVISION」的值變成了3 NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE test-mysql 3 Tue Sep 1 13:55:57 2020 DEPLOYED mysql-0.3.5 default [root@master ~]# kubectl get pod | grep test-mysql //確認pod是正常狀態 test-mysql-mysql-dfb9b6944-fd6l9 1/1 Running 0 67s [root@master ~]# kubectl describe pod test-mysql-mysql-dfb9b6944-fd6l9 //查看pod的詳細信息,能夠看出,該pod使用的鏡像已經回滾到mysql:5.7.14版本 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m4s default-scheduler Successfully assigned default/test-mysql-mysql-dfb9b6944-fd6l9 to node02 Normal Pulled 2m3s kubelet, node02 Container image "busybox:1.25.0" already present on machine Normal Created 2m3s kubelet, node02 Created container remove-lost-found Normal Started 2m3s kubelet, node02 Started container remove-lost-found Normal Pulled 2m1s kubelet, node02 Container image "mysql:5.7.14" already present on machine Normal Created 2m1s kubelet, node02 Created container test-mysql-mysql Normal Started 2m1s kubelet, node02 Started container test-mysql-mysql
1)node01節點運行web容器做爲私有倉庫
[root@node01 ~]# mkdir -p /var/www/charts //建立目錄,用於存放charts包 [root@node01 ~]# docker run -d -p 8080:80 -v /var/www:/usr/local/apache2/htdocs httpd
2)master節點上,建立chart包並打包
[root@master ~]# helm create testchart //建立chart包(生成的是目錄),名稱爲testchart [root@master ~]# helm package testchart //將剛纔生成的目錄進行打包,會在當前目錄下生成名爲testchart-0.1.0.tgz的包
3)master節點生成倉庫的index文件
[root@master ~]# mkdir myrepo [root@master ~]# mv testchart-0.1.0.tgz myrepo/ //建立用於存放chart包的目錄,並將chart包移動到該目錄 [root@master ~]# helm repo index myrepo/ --url http://192.168.45.141:8080/charts //url路徑表示運行web容器的節點IP+端口,也就是指定的是node01節點 [root@master ~]# ls myrepo/ index.yaml testchart-0.1.0.tgz //確認已經生成index.yaml文件 [root@master ~]# scp myrepo/* node01:/var/www/charts //將生成的index.yaml文件及charts包複製到web容器所在節點映射的本地目錄
4)將新repo倉庫添加到helm
[root@master ~]# helm repo add newrepo http://192.168.45.141:8080/charts //url是web容器所在的節點的IP+端口+存放chart包的目錄,並指定倉庫的名稱爲newrepo [root@master ~]# helm repo list NAME URL stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts local http://127.0.0.1:8879/charts newrepo http://192.168.45.141:8080/charts //stable是剛建立helm添加的阿里雲的倉庫 //local是本地的緩存 //newrepo是剛剛添加的倉庫名稱(確認該倉庫已經存在)
注:配置至此,已經能夠正常供內網環境使用這個charts包的私有倉庫了,下面是一些驗證。
5)搜索可用的chart包並部署
[root@master ~]# helm search testchart NAME CHART VERSION APP VERSION DESCRIPTION local/testchart 0.1.0 1.0 A Helm chart for Kubernetes newrepo/testchart 0.1.0 1.0 A Helm chart for Kubernetes //local是本地的緩存,不用理會,能夠查看到newrepo提供的testchart包 [root@master ~]# helm install newrepo/testchart -n test-nginx //既然能夠搜索到就表示可使用chart包建立實例 [root@master ~]# kubectl get pod | grep test-nginx //確認pod運行成功 test-nginx-testchart-64d8585997-jxtv7 1/1 Running 0 33s [root@master ~]# kubectl describe pod test-nginx-testchart-64d8585997-jxtv7 //查看這個pod的詳細信息,並確認pod所使用的鏡像 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal Scheduled 2m28s default-scheduler Successfully assigned default/test-nginx-testchart-64d8585997-jxtv7 to node01 Normal Pulling 2m28s kubelet, node01 Pulling image "nginx:stable" Normal Pulled 2m10s kubelet, node01 Successfully pulled image "nginx:stable" Normal Created 2m10s kubelet, node01 Created container testchart Normal Started 2m9s kubelet, node01 Started container testchart
6)更新chart包中所運行服務的鏡像
其實就是一個服務版本升級的操做,大概思路以下:修改解壓後的charts包目錄下的values.yaml文件爲所需的值(values.yaml文件包含的是這個服務的值,能夠在裏面指定鏡像及標籤、數據持久化的類型等等),修改完成後,再使用下面的命令進行升級操做。
[root@master ~]# helm upgrade -f testchart/values.yaml test-nginx newrepo/testchart //my-nginx是以前實例的名稱,能夠經過「helm list」查看實例名稱 //newrepo/testchart :爲自定義倉庫中的chart包 [root@master ~]# kubectl describe pod test-nginx-testchart-6d6984ddd9-gn9sw //確認pod所使用的鏡像已經更新
注:若是使用命令的方式直接進行升級,命令執行完成不會報錯,可是鏡像並不會更新,推薦使用更改values.yaml的方式進行升級!
7)再次向newrepo倉庫上傳chart包
[root@master ~]# helm create mychart [root@master ~]# helm package mychart/ [root@master ~]# mv mychart-0.1.0.tgz myrepo/ [root@master ~]# helm repo index myrepo/ --url http://192.168.45.141:8080/charts //當有新的chart包時,需更新index.yaml文件 [root@master ~]# scp myrepo/* node01:/var/www/charts [root@master ~]# helm repo update //若是須要使用則需更新一下本地的倉庫 [root@master ~]# helm search mychart NAME CHART VERSION APP VERSION DESCRIPTION local/mychart 0.1.0 1.0 A Helm chart for Kubernetes newrepo/mychart 0.1.0 1.0 A Helm chart for Kubernetes //確保新添加的chart包能夠被搜索到
[root@master ~]# helm version //查看helm版本信息 [root@master ~]# helm list /查看當前安裝的Chart包 [root@master ~]# helm search mysql //查看與mysql相關的chart包 [root@master ~]# helm fetch stable/mysql //將mysql軟件包下載到本地 [root@master ~]# helm inspect stable/mysql //查看該軟件包的詳細信息 [root@master ~]# helm install stable/mysql -n mysql //安裝指定的mysql軟件包,並命名爲mysql [root@master ~]# helm status mysql //查看mysql的狀態信息 [root@master ~]# helm delete --purge mysql //刪除mysql,並將本地的緩存也進行刪除 [root@master ~]# helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts //添加阿里雲的repo源 [root@master ~]# helm repo update //更新repo倉庫資源 [root@master ~]# helm create helm_charts //建立一個chart,名稱爲helm_charts [root@master ~]# cd helm_charts/ && helm lint //測試charts語法 [root@master ~]# helm package helm_charts //打包charts [root@master helm_charts]# helm template helm_charts-0.1.0.tgz //查看該軟件包生成的yaml文件