上一篇文章 Kubernetes上应用部署之三步曲 中提到了一句话 Kubernetes上一切皆资源,我们通过创建pods(deployment),service,ingress三种资源完成了 HelloDevOps应用的部署,一个简单的应用就有了三个yaml文件,但是真实实践中,应用(微服务应用)肯定不止一个,这样下来,就会有十多个,甚至几十个yaml文件,如果每次部署都用 kubectl 来对相应的资源进行增(create),删(delete),改(edit),查(get),那么这种管理方式无疑是复杂多变甚至是灾难的,在这种情况下,Kubernetes提供了Helm来让整个流程变得简单起来。
Helm 介绍
正如官网所说, Helm is the packagemanager for Kubernetes and Helm is the best way to find,share,and use software built for Kubernetes. 顾名思义,Helm 是kubernetes的包管理器,就像apt-get 与之Ubuntu和yum与之Redhat和Centos。
Helm 基本原理
Helm 是C/S模型,总共有两部分组成: Helm客户端(Helm)和服务器端(Tiller,以2.x版本为例,3.x剔除了tiller)。Helm 客户端是一个CLI,而Tiller是以deployment形式部署在Kubernetes平台的kube-system namespace下。
其中Helm接受来自于用户对于Helm Charts 所生成的Release的增(helm install)、删(helm delete)、改(helm upgrade)、查(helm ls);Tiller主要用来与Kubernetes API server进行交互(因为对于Kubernetes来说,一切请求的入口都是API server),从而实现对于Kubernetes资源的增、删、改、查,另外Tiller还可以对于已经创建好的Release进行存储与管理。
当用户需要用某一个chart来通过install方式生成一个Release的时候,Helm客户端接受这个install请求,并将请求发个Tiller服务端,Tiller服务端会将chart中的相关文件根据values.yaml中定义的值或者来自于--set后面指定的参数来进行渲染,而后将渲染好的文件发给Kubernetes API server生成相应的资源,最终完成一个Release的创建。
Helm 安装
由于Helm有客户端与服务端两部分组成,所以安装分两步走。
第一步:Helm 客户端的安装
Helm客户端有源码和二进制码两种安装方式,本文采用二进制进行安装(二进制安装比较方便,所以个人推荐用二进制进行安装)。首先在Helm 客户端Release的github页面中,找到与自己OS想匹配的版本进行下载,将下载文件进行解压并将解压之后的二进制文件helm拷贝至目标路径(比如/usr/local/bin/helm),可以用helm help命令来验证helm 客户端是否安装成功。
第二步:创建Service Account
由于在Kubernetes中,对于资源的控制权限是通过RBAC(Role-Based Access Control)来实现的, 而Tiller是在kube-system namespace下的,但是由Tiller管理的Release 是在别的namespace下面的,这种情况下需要给Tiller创建一个相应权限的Service Account,这个Service Account和cluster-admin这个ClusterRole进行绑定,这样确保Tiller能够对于整个cluster各个namespace下面的资源进行list,delete,update等操作。
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
创建完service account,可以在kube-system ns下面查看service account的具体信息
$ kubectl -n kube-system get sa | grep tillertiller 1 115d
第三步:Helm 服务端的安装
借助于上一步生成的Service Account(tiller),可以执行 helm init --service-account tiller 命令来完成 Tiller 服务端的安装。这个过程会先对helm本地环境进行有效性验证,然后会与Kubernetes cluster的kubectl进行连接,如果连接成功 ,会在kube-system namespace形势下部署一个与tiller相关的deployment。可以在 kube-system namespace下面进行查看。
$kubectl -n kube-system get deploy,pods | grep tiller
deployment.extensions/tiller-deploy 1 1 1 1 115d
pod/tiller-deploy-6f6fd74b68-tzhcv 1/1 Running
0 2d21h
执行 helm version
$ helm version
Client: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
Server: &version.Version{SemVer:"v2.11.0", GitCommit:"2e55dbe1fdb5fdb96b75ff144a339489417b146b", GitTreeState:"clean"}
至此,helm 客户端和服务端都安装完成。下面我们就可以用helm来部署上篇文章中的应用了,部署之前先要讲几个与Helm相关的概念。
Helm的一些基本概念
Chart
部署一个应用所需要的一个包,这个包是由能够描述kubernetes 相关资源(deploy, service, ingress 等等)的一系列文件组成 ,通过这些文件,可以在kubernetes上创建相关资源
Release
由Helm Chart所创建生成的一个实例(一般情况下就是部署了一个微服务应用)
Repoistory
存放Helm charts的仓库,和Docker Registry Repository一样,用来存放helm chart包。比如Jfrog Artifactory。
Helm 部署应用
首先,我们用 helm create devops命令创建一个名为devops的chart,查看一下包含的文件有哪些
$ tree devops
devops/
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── ingress.yaml
│ └── service.yaml
└── values.yaml
先简单的介绍一下上面出现的一些文件的作用
Chart.yaml
此文件主要用来描述此chart的信息,包括版本号,维护者的信息等。
charts
这是个目录,里面主要存放此chart所依赖的一些chart包。
templates
这是一个目录,里面包含chart的重点内容,可以看到有 deployment.yaml,ingress.yaml,service.yaml
,这三个文件(chart创建出来之后,默认只有这三种资源的定义文件,但是这并不代表只能有这三个文件,如果部署应用的过程中用到了secret,configmap等相关资源,也可以写在这个目录下,这也是就看出来了,文件越来越多的时候 helm 的方便快捷就能体现出来了)描述的就是与pod(deployment),ingress,service 等kubernetes资源相关的信息。
_helpers.tpl
这是个模版文件,用来定义用于一些模版语言。
value.yaml
这是最后也是要着重要介绍的一个文件。在介绍这个文件之前,我们先看一下,service.yaml文件中的内容有什么,这样能帮我们更好的理解 values.yaml
文件。
$ cat service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "devops.fullname" . }}
labels:
app: {{ .Release.Name }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app: {{ .Release.Name }}
可以看到上面有很多用 "{{}}"括起来的内容,这是Helm Chart中定义的变量。Helm Chart的书写用到了Go Template Language。 Package Template主要实现了一些数据驱动模块,这些数据模块可以用来生成一些文本输出。而对于Template 最直观的理解可以这么理解
这些括弧里面的内容可以理解为 "形参",而"实参"的值就是来自于 values.yaml 文件,其实如果逐个打开chart目录下的其他文件,比如 deployment.yaml, ingress.yaml打开之后都会看到与 service.yaml相似的情况。所以 values.yaml文件的重要性就体现出来了,部署出来的deployment,ingress ,service是什么样的,完全取决于在 values.yaml文件中是怎么样定义的。
而且helm chart的另外一个便利之处就是,一个chart可以部署多个Release,而这多个Release又可以对应多个不同的环境,比如dev环境,svt环境,prod环境,这种变化需要的仅仅是一个 values.yaml 文件,比如将dev环境相关的信息,写在一个 values-dev.yaml的文件中,那么创建出来的Release所对应的环境就是dev环境,svt和prod都可以用同样的方式创建出来。 这些用"{{}}"括起来的变量中,有几个全局的变量,需要关注一下:
.Chart.Name
表示chart的name,比如上面用helm create devops创建了devops 这个chart,则.Chart.Name的值就是devops。
.Release.Name
表示由chart创建的Release的name,比如用上述的devops chart通过install命令生成了一个hello-devops的Release,则.Release.Name的值就是hello-devops。
.Release.Namespace
由chart创建的Release所在的namespace,比如用上述的devops chart在devops namespace下面创建的hello-devops Release,则 .Release.Namespace的值就是devops。 我们将上一篇文章中deployment,yaml,service.yaml,ingress.yaml文件中的"实参"内容写入到 values.yaml 文件中
$ cat values.yaml
replicaCount: 1
env:
running_env: dev
name: devops
client: helm
server: tiller
version: v1
image:
repository: dllhb/go_test
tag: v1.3
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: true
annotations:
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
path: /
hosts:
- devops.test.com
tls:
- secretName: devops-tls
hosts:
- devops.test.com
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
deployment.yaml
文件的内容如下
$ cat templates/deployment.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
version: non-canary
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 9999
protocol: TCP
env:
{{- include "devops.env" . | nindent 12}}
service.yaml 文件内容如下
$ cat templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "devops.fullname" . }}
labels:
app: {{ .Release.Name }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app: {{ .Release.Name }}
ingress.yaml 文件内容如下
$ cat templates/ingress.yaml
{{- if .Values.ingress.enabled -}}
{{- $fullName := include "devops.fullname" . -}}
{{- $ingressPath := .Values.ingress.path -}}
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ $fullName }}
labels:
app.kubernetes.io/instance: {{ .Release.Name }}
{{- with .Values.ingress.annotations }}
annotations:
{{ toYaml . | indent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
{{- range .Values.ingress.tls }}
- hosts:
{{- range .hosts }}
- {{ . | quote }}
{{- end }}
secretName: {{ .secretName }}
{{- end }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ . | quote }}
http:
paths:
- path: {{ $ingressPath }}
backend:
serviceName: {{ $fullName }}
servicePort: http
{{- end }}
{{- end }}
下面就可以进入到devops目录下用 helm install 来进行应用安装,
$ helm install . --name devops --namespace devops -f values.yaml
NAME: devops
LAST DEPLOYED: Sun Aug 4 16:21:03 2019
NAMESPACE: devops
STATUS: DEPLOYED
RESOURCES:
==> v1/Service
NAME AGE
devops 4s
==> v1beta2/Deployment
devops 4s
==> v1beta1/Ingress
devops 4s
==> v1/Pod(related)
NAME READY STATUS RESTARTS AGE
devops-5f499c48b4-rzldr 1/1 Running 0 4s
NOTES:
1. Get the application URL by running these commands:
https://devops.test.com/
查看pod,service,ingress资源
$ kubectl -n devops get pods,svc,ing
NAME READY STATUS RESTARTS AGE
pod/hello-devops-78dd67d9cc-jpx2z 1/1 Running 0 2d22h
NAME TYPE CLUSTER-IP EXTERNAL-IP
PORT(S) AGE
service/hello-devops-svc ClusterIP 172.21.246.13 <none> 8888/TCP 14d
NAME
HOSTS
ADDRESS
PORTS AGE
ingress.extensions/hello-devops-ingress devops.test.com 10.208.70.22 80, 443 14d
然后就可以用 https://devops.test.com 来访问应用程序了
$ curl -k -s https://devops.test.com
Hello DevOps, pod name is hello-devops-78dd67d9cc-jpx2z
此外,可以用 helm ls 查看已经部署了的Release
$ helm ls | grep devops
devops 1 Thu Jun 6 10:13:02 2019 DEPLOYED devops-0.1.0 1.0 devops
如果要删除已经安装了的Release,可以执行 helmdeletedevops--purge
$ helm delete devops --purgerelease "devops" deleted
来源:DevSecOps SIG
作者:小马哥
声明:文章获得作者授权在IDCF社区公众号(devopshub)转发。优质内容共享给思否平台的技术同伴,如原作者有其他考虑请联系小编删除,致谢。
7月每周四晚8点,【冬哥有话说】研发效能工具专场,公众号留言“研发效能”可获取地址
- 7月8日,前微软-周文洋《微软DevOps工具链的 "爱恨情仇"(Azure DevOps)》
- 7月15日,阿里云-陈逊《复杂型研发协作模式下的效能提升实践》
- 7月22日,极狐(GitLab)-张扬《基础设施即代码的⾃动化测试探索》
- 7月29日,字节跳动-胡贤彬《自动化测试,如何做到「攻防兼备」?》
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。