有了 kubectl yaml , 还要 helm 做什么呢?
在微服务场景中,使用同一模式开发的应用会变的很多,我们会使用相同的 docker 基础镜像进行应用打包。但对于部署场景,我们需要写很多类似的 yaml 文件,由此,我们希望将不同之处使用变量抽取出来,并与通用模板进行整合。
目前使用 kubectl yaml 的这种方式是无法完成这一功能的。
我们可以使用 helm 来批量部署同类应用,并彻底将部署代码从程序中解耦。在同一类部署中,不同的值是:应用名称,应用当前版本,镜像地址,我们将这些参数提取出来,从命令行中指定进去。
下面我们来展示这一过程。
写在前面 - 关于腾讯云 TKE 和 helm
腾讯云的 TKE 已经安装了 helm 的 tiller 了,所以在本地使用 helm 的时候,只需要使用 helm 的命令行工具即可。 helm 默认会操作 ~/.kube/config 对应的集群。
如果要操作不同的集群,我习惯加上 --kubeconfig=xxx 来操作,建议将他做成一个别名放在你的 .bashrc 或 .zshrc 中,如:
代码语言:txt复制alias helm2="helm --kubeconfig ~/.kube/config2"
创建一个 helm chart
使用命令创建一个chart
代码语言:txt复制helm create chart-demo
创建出来的目录结构
代码语言:txt复制./chart-demo
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
只需将共用的基础部署脚本写在 templates 里面的文件中,把可变量写到 values.yaml 中。
开始写一个简单 Chart
使用 helm create 出来的模板文件,看起来很复杂,所以,咱们不用他的那些模板,从 kubectl 的 yaml 开始。删掉 templates 下的所有文件。用自己熟悉的方式,先创建部署,目录结构如下:
代码语言:txt复制./chart-demo
├── Chart.yaml
├── templates
│ └── deploy.yaml
└── values.yaml
deploy.yaml
代码语言:txt复制apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app: {{ .Release.Name }}
spec:
replicas: 2
selector:
matchLabels:
app: {{ .Release.Name }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: {{ .Release.Name }}
image: ccr.ccs.tencentyun.com/axlyzhang-images/xyzdemo-product:v1.10
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-8-openjdk-amd64
- name: JAVA_VERSION
value: 8u111
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 256Mi
假装安装一下,看看输出的结果:
代码语言:txt复制helm install --debug --dry-run xyz-product .
代码语言:txt复制---
# Source: chart-demo/templates/deploy.yaml
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: xyz-product
labels:
app: xyz-product
spec:
replicas: 2
selector:
matchLabels:
app: xyz-product
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: xyz-product
spec:
containers:
- name: xyz-product
image: ccr.ccs.tencentyun.com/axlyzhang-images/xyzdemo-product:v1.10
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-8-openjdk-amd64
- name: JAVA_VERSION
value: 8u111
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 256Mi
上面就是合成结果,我们已经放入了一个内置变量 {{ .Release.Name }}
。
很简单吧。接下来,就是要把更多的变量(appName, version)放进去。
Values
helm 支持变量,函数,模板和一些流控编程。现在我们不使用 Release 这个内置变量了,我们使用 Values 变量。Values 变量一般有 2 个来源,一个是 yaml 文件,一个是命令行参数。在 Jenkins 自动化 部署的场景,我们更希望通过命令行来把参数指定进去。
我们改写 deploy.yaml 一下:
代码语言:txt复制apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: {{ required "应用名称 appName 必须指定" .Values.appName }}
namespace: {{ default "default" .Values.ns}}
labels:
app: {{ .Values.appName }}
version: {{ required "版本号 version 必须指定" .Values.version }}
spec:
replicas: {{ default 2 .Values.replicas }}
selector:
matchLabels:
app: {{ .Values.appName }}
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: {{ .Values.appName }}
spec:
containers:
- name: {{ .Values.appName }}
image: ccr.ccs.tencentyun.com/axlyzhang-images/{{ .Values.appName }}:{{ .Values.version }}
env:
- name: PATH
value: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
- name: LANG
value: C.UTF-8
- name: JAVA_HOME
value: /usr/lib/jvm/java-8-openjdk-amd64
- name: JAVA_VERSION
value: 8u111
resources:
limits:
cpu: 500m
memory: 1Gi
requests:
cpu: 250m
memory: 256Mi
我们通过命令行,将参数指定进去,如下:
代码语言:txt复制helm install --debug --dry-run springboot-app . --set appName=xyzdemo-product --set version=v1.10
看到结果,已经按照我们想要的结果输出了。去掉 --debug --dry-run
就可以直接执行到 K8S 环境了。
上传到 Chart “私服”
有多种方法可以搭建自己的私服,如:ChartMuseum, Github Pages, JFrog Artifactory 等。目前使用 coding.net 的制品库已经可以完美支持 helm charts 。只需要创建仓库即可。
在本地设置你的仓库(下面这些命令在 coding 中会自动帮你生成):
代码语言:txt复制helm plugin install https://e.coding.net/coding-public/helm-push
helm repo add --username <userName> --password <pwd> charts "https://your-repo-url"
推送步骤:
- 打包:
helm package .
- 推送
helm push chart-demo-0.1.0.tgz charts
现在搜一下 coding 的 helm 仓库:
代码语言:txt复制helm search repo charts
便有了你的图样。
现在远程的 repo 已经设置到本地了。可以使用远程图样,直接部署同环境的应用了。
代码语言:txt复制helm install microservice1 charts/chart-demo --set appName=microservice1 --set version=1.0
helm install microservice2 charts/chart-demo --set appName=microservice2 --set version=1.1
...
在 Jenkins 的脚本中,无法多次 install 同一个,可以使用 helm upgrade --install
。
More
到这里,我们只是应用了 helm 很少的功能,便实现了应用的批量部署。
其实,helm 的功能很强大,他的模板系统可以支持更多的变量,模板,流控,函数等,并可以支持很多部署操作命令,这些可以去他的官网研究一下。
总结
helm 可以理解为一套 YAML 的模板系统,按照 helm 特定的模板语法编写 yaml,他就可以“智能地”将这些模板合成为正确的 Yaml 部署文件,并可以通过简单的命令部署到 K8S 环境中。
当然,Helm 也可以是你的应用的“包管理系统”。
参考:
HELM 官网
CODING制品库