# 簡化Kubernetes應用部署工具-Helm簡介
微服務和容器化給復雜應用部署與管理帶來了極大的挑戰。Helm是目前Kubernetes服務編排領域的唯一開源子項目,做為Kubernetes應用的一個包管理工具,可理解為Kubernetes的apt-get / yum,由Deis 公司發起,該公司已經被微軟收購。Helm通過軟件打包的形式,支持發布的版本管理和控制,很大程度上簡化了Kubernetes應用部署和管理的復雜性。
隨著業務容器化與向微服務架構轉變,通過分解巨大的單體應用為多個服務的方式,分解了單體應用的復雜性,使每個微服務都可以獨立部署和擴展,實現了敏捷開發和快速迭代和部署。但任何事情都有兩面性,雖然微服務給我們帶來了很多便利,但由于應用被拆分成多個組件,導致服務數量大幅增加,對于Kubernetest編排來說,每個組件有自己的資源文件,并且可以獨立的部署與伸縮,這給采用Kubernetes做應用編排帶來了諸多挑戰:
1. 管理、編輯與更新大量的K8s配置文件
1. 部署一個含有大量配置文件的復雜K8s應用
1. 分享和復用K8s配置和應用
1. 參數化配置模板支持多個環境
1. 管理應用的發布:回滾、diff和查看發布歷史
1. 控制一個部署周期中的某一些環節
1. 發布后的驗證
Helm把Kubernetes資源(比如deployments、services或 ingress等) 打包到一個chart中,而chart被保存到chart倉庫。通過chart倉庫可用來存儲和分享chart。Helm使發布可配置,支持發布應用配置的版本管理,簡化了Kubernetes部署應用的版本控制、打包、發布、刪除、更新等操作。
本文簡單介紹了Helm的用途、架構與實現。
## Helm產生原因
Helm基本架構如下:

# helm 安裝
完本文后您應該可以自己創建chart,并創建自己的私有chart倉庫。
Helm是一個kubernetes應用的包管理工具,用來管理charts——預先配置好的安裝包資源,有點類似于Ubuntu的APT和CentOS中的yum。
Helm chart是用來封裝kubernetes原生應用程序的yaml文件,可以在你部署應用的時候自定義應用程序的一些metadata,便與應用程序的分發。
Helm和charts的主要作用:
- 應用程序封裝
- 版本管理
- 依賴檢查
- 便于應用程序分發
本文同時歸檔到kubernetes-handbook。
安裝Helm
前提要求
- Kubernetes1.5以上版本
- 集群可訪問到的鏡像倉庫
- 執行helm命令的主機可以訪問到kubernetes集群
安裝步驟
首先需要安裝helm客戶端
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.shchmod 700 get_helm.sh./get_helm.sh
創建tiller的serviceaccount和clusterrolebinding
kubectl create serviceaccount --namespace kube-system tiller
kubectl create clusterrolebinding tiller-cluster-rule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller
然后安裝helm服務端tiller
helm init -i harbor-demo.dianrong.com/k8s/kubernetes-helm-tiller:v2.7.0 --service-account tiller
我們使用-i指定自己的鏡像,因為官方的鏡像因為某些原因無法拉取。
為應用程序設置serviceAccount:
kubectl patch deploy --namespace kube-system tiller-deploy -p '{"spec":{"template":{"spec":{"serviceAccount":"tiller"}}}}'
檢查是否安裝成功:
$ kubectl -n kube-system get pods|grep tiller
tiller-deploy-3243657295-4dg28 1/1 Running 0 8m
# helm version
Client: &version.Version{SemVer:"v2.7.0", GitCommit:"08c1144f5eb3e3b636d9775617287cc26e53dba4", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.7.0", GitCommit:"08c1144f5eb3e3b636d9775617287cc26e53dba4", GitTreeState:"clean"}
> 注意檢查是否安裝socat依賴 :yum install socat
### 創建自己的chart
我們創建一個名為mychart的chart,看一看chart的文件結構。
# helm create mychart
# tree mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ └── service.yaml
└── values.yaml
2 directories, 7 files
模板
Templates目錄下是yaml文件的模板,遵循Go template語法。使用過Hugo的靜態網站生成工具的人應該對此很熟悉。
我們查看下deployment.yaml文件的內容。
# cat mychart/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: {{ template "mychart.fullname" . }}
labels:
app: {{ template "mychart.name" . }}
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
release: {{ .Release.Name }}
heritage: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
template:
metadata:
labels:
app: {{ template "mychart.name" . }}
release: {{ .Release.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.internalPort }}
livenessProbe:
httpGet:
path: /
port: {{ .Values.service.internalPort }}
readinessProbe:
httpGet:
path: /
port: {{ .Values.service.internalPort }}
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- if .Values.nodeSelector }}
nodeSelector:
{{ toYaml .Values.nodeSelector | indent 8 }}
{{- end }}
這是該應用的Deployment的yaml配置文件,其中的雙大括號包擴起來的部分是Go template,其中的Values是在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: 1.9
pullPolicy: IfNotPresent
service:
name: nginx
type: ClusterIP
externalPort: 80
internalPort: 80
ingress:
enabled: false
# Used to create an Ingress record.
hosts:
- chart-example.local
annotations:
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
tls:
# Secrets must be manually created in the namespace.
# - 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
比如在Deployment.yaml中定義的容器鏡像image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"其中的:
- .Values.image.repository就是nginx
- .Values.image.tag就是stable
以上兩個變量值是在create chart的時候自動生成的默認值。
我們將默認的鏡像地址和tag改成我們自己的鏡像sz-pg-oam-docker-hub-001.tendcloud.com/library/nginx:1.9。
### 檢查配置和模板是否有效
當使用kubernetes部署應用的時候實際上講templates渲染成最終的kubernetes能夠識別的yaml格式。
helm install --dry-run --debug <chart_dir> -n string
命令來驗證chart配置。該輸出中包含了模板的變量配置與最終渲染的yaml文件。
# helm install --dry-run --debug mychart/ --name test
[debug] Created tunnel using local port: '45443'
[debug] SERVER: "localhost:45443"
[debug] Original chart version: ""
[debug] CHART PATH: /root/k8s/helm/mychart
NAME: test
REVISION: 1
RELEASED: Fri Nov 3 13:37:44 2017
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
image:
pullPolicy: IfNotPresent
repository: nginx
tag: 1.9
ingress:
annotations: null
enabled: false
hosts:
- chart-example.local
tls: null
replicaCount: 1
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
service:
externalPort: 80
internalPort: 80
name: nginx
type: ClusterIP
HOOKS:
MANIFEST:
---
# Source: mychart/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: test-mychart
labels:
app: mychart
chart: mychart-0.1.0
release: test
heritage: Tiller
spec:
type: ClusterIP
ports:
- port: 80
targetPort: 80
protocol: TCP
name: nginx
selector:
app: mychart
release: test
---
# Source: mychart/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-mychart
labels:
app: mychart
chart: mychart-0.1.0
release: test
heritage: Tiller
spec:
replicas: 1
template:
metadata:
labels:
app: mychart
release: test
spec:
containers:
- name: mychart
image: "nginx:1.9"
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
readinessProbe:
httpGet:
path: /
port: 80
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
我們可以看到Deployment和Service的名字前半截由兩個隨機的單詞組成,最后才是我們在values.yaml中配置的值。
### 部署到kubernetes
在mychart目錄下執行下面的命令將nginx部署到kubernetes集群上。
# helm install . --name test
NAME: test
LAST DEPLOYED: Fri Nov 3 14:30:19 2017
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
test-mychart ClusterIP 10.254.242.188 <none> 80/TCP 0s
==> v1beta1/Deployment
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
test-mychart 1 0 0 0 0s
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app=mychart,release=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已經部署到kubernetes集群上,本地執行提示中的命令在本地主機上訪問到nginx實例。
export POD_NAME=$(kubectl get pods --namespace default -l "app=eating-hound-mychart" -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
在本地訪問http://127.0.0.1:8080即可訪問到nginx。
查看部署的relaese
# helm list
NAME REVISION UPDATED STATUS CHART NAMESPACE
peeking-yak 1 Fri Nov 3 15:01:20 2017 DEPLOYED mychart-0.1.0 default
刪除部署的release
$ helm delete eating-houndrelease "eating-hound" deleted
打包分享
我們可以修改Chart.yaml中的helm chart配置信息,然后使用下列命令將chart打包成一個壓縮文件。
helm package .
打包出mychart-0.1.0.tgz文件。
- 第一章 kubernetes 功能介紹
- 第二章 在CentOS上部署kubernetes1.7.6集群
- 第三章 創建TLS證書和秘鑰
- 第四章 安裝kubectl命令行工具
- 第五章 創建kubeconfig 文件
- 第六章 etcd 集群部署
- 第七章 部署k8s-master-v1.7.6節點
- 第八章 部署k8s-v1.7.6 node 節點
- 第九章 kubectl 操作示例
- 第十章 在kubernetes 部署第一個應用
- 第十一章 kubernetes之pod 調度
- 第十二章 K8S服務組件之kube-dns&Dashboard
- 第十三章 Kubernetes中的角色訪問控制機制(RBAC)支持
- 第十四章 部署nginx ingress
- 第十五章 使用Prometheus監控Kubernetes集群和應用
- 第十六章 使用helm 應用部署工具
- 第十七章 kubernetes 從1.7 到1.8升級記錄
- 第十八章 在kubernetes 使用ceph
- 第十九章 基于 Jenkins 的 CI/CD(一)
- 第二十章 基于jenkins的CI/CD(二)
- 第二十一章 基于prometheus自定指標HPA彈性伸縮