0
点赞
收藏
分享

微信扫一扫

第23章:Helm应用包管理器

倚然君 2022-08-31 阅读 79

Helm应用包管理器

3.1 为什么需要Helm

K8S上的应用对象,都是由特定的资源描述组成,包括deployment、service等。都保存各自文件中或者集中写到一个配置文件。然后kubectl apply –f 部署。

​​

第23章:Helm应用包管理器_nginx

​​

如果应用只由一个或几个这样的服务组成,上面部署方式足够了。 而对于一个复杂的应用,会有很多类似上面的资源描述文件,例如微服务架构应用,组成应用的服务可能多达十个,几十个。如果有更新或回滚应用的需求,可能要修改和维护所涉及的大量资源文件,而这种组织和管理应用的方式就显得力不从心了。 且由于缺少对发布过的应用版本管理和控制,使Kubernetes上的应用维护和更新等面临诸多的挑战,主要面临以下问题:

(1) 如何将这些服务作为一个整体管理 (2) 这些资源文件如何高效复用 (3) 不支持应用级别的版本管理

3.2 Helm介绍

Helm是一个Kubernetes的包管理工具,就像Linux下的包管理器,如yum/apt等,可以很方便的将之前打包好的yaml文件部署到kubernetes上。Helm有3个重要概念如下: (1) helm # 一个命令行客户端工具,主要用于Kubernetes应用chart的创建、打包、发布和管理。 (2) Chart # 应用描述,一系列用于描述 k8s 资源相关文件的集合。 (3) Release # 基于Chart的部署实体,一个 chart 被 Helm 运行后将会生成对应的一个 release;将在k8s中创建出真实运行的资源对象。

3.3 Helm v3 变化

Helm目前有两个大版本:v2和v3,2019年11月,Helm团队发布 v3 版本,v3版本相比v2版本最主要变化如下。

1 架构变化

最明显的变化是 ​​Tiller​​的删除,并大部分代码重构。

​​

第23章:Helm应用包管理器_mysql_02

​​

2 Release名称可以在不同命名空间重用

3 支持将 Chart 推送至 Docker 镜像仓库中

4 使用JSONSchema验证chart values

5 其他

(1) 为了更好地协调其他包管理者的措施 ​​Helm CLI​​个别更名

helm delete  更名为 helm uninstall
helm inspect 更名为 helm show
helm fetch 更名为 helm pull

但以上旧的命令当前仍能使用。

(2) 移除了用于本地临时搭建 ​​Chart Repository​​的 ​​helm serve​​ 命令。

(3) 自动创建名称空间 在不存在的命名空间中创建发行版时,Helm 2创建了命名空间。Helm 3遵循其他Kubernetes对象的行为,如果命名空间不存在则返回错误。 (4) 不再需要​​requirements.yaml​​, 依赖关系是直接在​​chart.yaml​​中定义。

3.4 Helm客户端

1 部署Helm客户端

使用helm很简单,你只需要下载一个二进制客户端包即可,会通过kubeconfig配置(通常$HOME/.kube/config)来连接Kubernetes。 Helm客户端下载地址:​​https://github.com/helm/helm/releases/​​

# 下载后解压移动到/usr/bin/目录即可
# wget https://get.helm.sh/helm-v3.7.1-linux-amd64.tar.gz
# tar -zxf helm-v3.7.1-linux-amd64.tar.gz
# mv linux-amd64/helm /usr/bin/

2 Helm常用命令

命令

描述

completion

命令补全,source <(helm completion bash)

create

创建一个chart并指定名字

dependency

管理chart依赖

get

下载一个release。可用子命令:all、hooks、manifest、notes、values

history

获取release历史

install

安装一个chart

list

列出release

package

将chart目录打包到chart存档文件中

pull

从远程仓库中下载chart并解压到本地 # helm pull stable/mysql --untar

repo

添加,列出,移除,更新和索引chart仓库。可用子命令:add、index、list、remove、update

rollback

从之前版本回滚

search

根据关键字搜索chart。可用子命令:hub、repo

show

查看chart详细信息。可用子命令:all、chart、readme、values

status

显示已命名版本的状态

template

本地呈现模板

uninstall

卸载一个release

upgrade

更新一个release

version

查看helm客户端版本

3 配置Chart仓库

(1) 常用仓库 1)官方仓库网址: ​​https://hub.kubeapps.com/​​​ 2)其它仓库网址: ​​​https://artifacthub.io/​​

(2) 添加存储库并更新

# 添加阿里云chart存储仓库,版本比较老
# helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
# 更新仓库
# helm repo update

(3) 查看配置的存储库

# helm repo list

(4) 查找chart应用

helm search repo <应用名>

(5) 删除存储库

# helm repo remove <仓库名>

3.5 Helm基本使用

1 Helm管理应用生命周期

(1) 创建Chart应用示例
# helm create
(2) 部署
# helm install
(3) 更新
# helm upgrade
(4) 回滚
# helm rollback
(5) 卸载
# helm uninstall

2 使用chart部署一个应用

(1) 查找chart

# helm search repo mysql
NAME CHART VERSIONAPP VERSIONDESCRIPTION
aliyun/mysql 0.3.5 Fast, reliable, scalable, and easy to use open-...
aliyun/percona 0.3.0 free, fully compatible, enhanced, open source d...
aliyun/percona-xtradb-cluster0.0.2 5.7.19 free, fully compatible, enhanced, open source d...
aliyun/gcloud-sqlproxy 0.2.3 Google Cloud SQL Proxy
aliyun/mariadb 2.1.6 10.1.31 Fast, reliable, scalable, and easy to use open-...
# 为什么mariadb也在列表中,因为他和mysql有关。

(2) 查看chart的基本信息

# helm show chart aliyun/mysql

(3) 安装chart应用

# helm install db aliyun/mysql -n default

(4) 安装后查看chart帮助信息

# helm status db -n default

3 安装前自定义chart配置选项

(1) chart

上面部署的mysql并没有成功,这是因为并不是所有的 chart 都能按照默认配置运行成功,可能会需要一些环境依赖,例如PV。 所以我们需要自定义 chart 配置选项(覆盖values.yaml),安装过程中有两种方法可以传递配置数据: --values 或 -f # 指定带有覆盖的YAML文件,这可以多次指定,最右边的文件优先。 --set # 在命令行上指定替代,如果两者都用,​​--set优先级高​​。

# 把chart包下载下来查看详情
# helm pull aliyun/mysql --untar
# tree mysql/
mysql/
├── Chart.yaml
├── README.md
├── templates
│ ├── configmap.yaml
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── NOTES.txt
│ ├── pvc.yaml
│ ├── secrets.yaml
│ └── svc.yaml
└── values.yaml

1 directory, 10 files

# helm show values ./mysql <=> # cat mysql/values.yaml # 查看yaml模板变量
# helm show chart ./mysql/ <=> # cat mysql/Chart.yaml # 查看chart基本信息

# 由于我这里使用的是k8s版本为1.20,Deployment yaml配置文件需要进行修改,否则无法部署
# vim mysql/templates/deployment.yaml

​​

第23章:Helm应用包管理器_回滚_03

​​

# cat > config.yaml << EOF
persistence:
enabled: true
accessMode: ReadWriteOnce
size: 8Gi
mysqlUser: "k8s"
mysqlPassword: "123456"
mysqlDatabase: "k8s"
EOF

# kubectl create namespace mysql-db

# 创建MySQL用户k8s,并授予此用户访问新创建的k8s数据库的权限,并指定资源所在的名称空间,
# --set使用命令行替代变量,未指定的使用默认值。
# helm install db -f config.yaml -n mysql-db --set persistence.storageClass="managed-nfs-storage" ./mysql/

# kubectl get pod -n mysql-db
NAME READY STATUS RESTARTS AGE
db-mysql-5c695fcdfb-g6jt6 1/1 Running 0 77s

# helm list -n mysql-db
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
db mysql-db 1 2021-10-22 17:17:32.401870823 +0800 CST deployed mysql-0.3.5

# kubectl get svc -n mysql-db
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
db-mysql ClusterIP 172.28.104.81 <none> 3306/TCP 2m38s

# yum install mysql -y
# mysql -uk8s -p123456 -h172.28.104.81 k8s
MySQL [k8s]> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| k8s |
+--------------------+
2 rows in set (0.00

​​

第23章:Helm应用包管理器_nginx_04

​​

# 卸载helm应用(pvc,pv,存储资源被删除)
# helm uninstall db -n mysql-db

(2) values.yaml参数格式对应set变量格式表

​​

第23章:Helm应用包管理器_回滚_05

​​

helm install命令可以从多个来源安装:chart存储库、本地chart存档(helm install mysql-0.3.5.tgz)、chart目录(helm install path/to/mysql)、完整的URL(helm install ​​https://example.com/charts/mysql-0.3.5.tgz​​)

4 构建一个Helm Chart

(1) 自动生成目录

# helm create mychart
# tree mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── NOTES.txt
│ ├── serviceaccount.yaml
│ ├── service.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml

3 directories, 10 files

1)charts # 目录里存放这个chart依赖的所有子chart。

2)​​Chart.yaml # 用于描述这个Chart的基本信息,包括名字、描述信息以及版本等。​

3)​​Templates # 目录里面存放所有yaml模板文件。​

4)NOTES.txt # 用于介绍Chart帮助信息,helm install 部署后展示给用户。例如:如何使用这个 Chart、列出缺省的设置等。 5)_helpers.tpl # 放置模板助手的地方,可以在整个 chart 中重复使用。 6)​​values.yaml # 用于存储 templates 目录中模板文件中用到变量的值。​

(2) 创建Chart后,接下来就是将其部署

# 修改service的type为NodePort,方便实验
# vim mychart/values.yaml
service:
type: NodePort
port: 80

# helm install

(3) 查看Release

# helm list -n default
NAMENAMESPACEREVISIONUPDATED STATUS CHART APP VERSION
web default 1 2021-10-23 23:11:12.33497844 +0800 CSTdeployedmychart-0.1.01.16.0

(4) 查看部署的pod

# kubectl get pod,svc -n default
NAME READY STATUS RESTARTS AGE
pod/nfs-client-provisioner-666969576d-k2pgw 1/1 Running 1 31h
pod/web-mychart-5b58c47cd6-nsk4r 1/1 Running 0 57s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 172.28.0.1 <none> 443/TCP 33d
service/web-mychart NodePort 172.28.48.236 <none> 80:31644/TCP 57s

(5) 打包推送到chart仓库共享给别人使用

# helm package mychart/
Successfully packaged chart and saved it to: /root/helm_dir/mychart-0.1.0.tgz

5 升级、回滚和删除

(1) 升级

1)使用Chart升级应用有两种方法:

--values,-f # 指定yaml文件覆盖values.yaml文件中的值,没有覆盖的保持默认 --set # 在命令行上指定覆盖values.yaml文件中的值,没有覆盖的保持默认 注: 如果两种方法一起使用,--set优先级高 2)发布新版本的chart时,或者当您要更改发布的配置时,可以使用该​​helm upgrade​​ 命令

# 第一种方式,将nginx服务升级到1.18版本
# vim values.yaml
image:
tag: "1.18"
# helm upgrade -f values.yaml web mychart/ -n default

# 第二种方式,将nginx服务升级到1.19版本
# helm upgrade --set image.tag=1.19

(2) 回滚

如果在发布后没有达到预期的效果,则可以使用​​helm rollback​​回滚到之前的版本。

1)查看历史版本

# helm history web -n default
REVISIONUPDATED STATUS CHART APP VERSIONDESCRIPTION
1 Sat Oct 23 23:28:45 2021supersededmychart-0.1.01.16.0 Install complete
2 Sat Oct 23 23:30:22 2021supersededmychart-0.1.01.16.0 Upgrade complete
3 Sat Oct 23 23:33:15 2021deployed mychart-0.1.01.16.0 Upgrade complete

注:
REVISION 1 表示的是nginx:1.16版本
REVISION 2 表示的是nginx:1.18版本
REVISION 3 表示的是nginx:1.19版本

2)将应用回滚到指定版本

# helm rollback web 2 -n default
Rollback was a success! Happy Helming!

注: 回滚到上一个版本使用如下命令
helm rollback web -n default

(3) 卸载chart应用

# helm uninstall web -n default
release "web" uninstalled

6 Helm工作流程

​​

第23章:Helm应用包管理器_mysql_06

​​

3.6 Chart模板

1 介绍

Helm最核心的就是模板,即模板化的K8S YAML文件,它本质上就是一个Go的template模板,Helm在Go template模板的基础上,还会增加 很多东西,如一些自定义的元数据信息、扩展的库以及一些类似于编程形式的工作流,例如条件语句、管道等等,这些东西都会使得我们的 模板变得更加丰富。

​通过模板实现Chart的高效复用,当部署多个应用时,可以将差异化的字段进行模板化,在部署时使用 -f 或者 --set 动态覆盖默认值,从而适配多个应用。​

​​

第23章:Helm应用包管理器_nginx_07

​​

# cd /root/helm_dir/mychart/
# cat > values.yaml << EOF
replicas: 1
label:
project: ms
app: nginx
image: nginx
imageTag: "1.20"
EOF

# rm -rf templates/*
# cat > templates/deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deployment
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
project: {{ .Values.label.project }}
app: {{ .Values.label.app }}
template:
metadata:
labels:
project: {{ .Values.label.project }}
app: {{ .Values.label.app }}
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
EOF

2 内置对象

Release对象获取发布记录信息。

在上面示例中,模板文件中​​.Release​​、​​.Values​​是Helm内置对象,顶级开头写。(1) Release对象

使用 ​​{{.Release.Name}}​​将 release 的名称插入到模板中,下面是一些常用的内置对象。

Release.Name

release 名称

Release.Name

release 的名称

Release.Time

release 的时间

Release.Namespace

release 的命名空间

Release.Service

release 的服务名称

Release.Revision

release 的修订版本号,从1开始累加

(2) Values对象

1)Values对象是为Chart模板提供值,这个对象的值有3个来源:

A、chart 包中的 values.yaml 文件 B、通过 helm install 或者 helm upgrade 的 ​​-f​​或者 ​​--values​​参数传入的自定义的 yaml 文件

C、通过 ​​--set​​ 参数传入的值

2)chart 的 values.yaml 提供的值可以被用户提供的 values 文件覆盖,而该文件同样可以被 ​​--set​​提供的参数所覆盖。

(3) Chart对象

可以通过Chart对象访问Chart.yaml文件的内容,例如: {{ .Chart.AppVersion }}

3 调试

Helm也提供了​​--dry-run --debug​​调试参数,帮助你验证模板正确性,在执行​​helm install​​时候带上这两个参数就可以把对应的

values值和渲染的资源清单打印出来,而不会真正的去部署一个release。

比如我们来调试上面创建的 chart 包:

# helm install --dry-run --debug web ./mychart/ -n default
install.go:178: [debug] Original chart version: ""
install.go:199: [debug] CHART PATH: /root/helm_dir/mychart

NAME: web
LAST DEPLOYED: Sun Oct 24 19:46:42 2021
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
image: nginx
imageTag: "1.20"
label:
app: nginx
project: ms
replicas: 1

HOOKS:
MANIFEST:
---
# Source: mychart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 1
selector:
matchLabels:
project: ms
app: nginx
template:
metadata:
labels:
project: ms
app: nginx
spec:
containers:
- image: nginx:1.20
name: nginx

4 函数与管道

前面讲的模块,其实就是将变量值传给模板引擎进行渲染,模板引擎还支持对拿到数据进行二次处理。 (1) 常用函数

quote    
default
indent、nindent# 缩进字符串
toYaml

其他函数:
upper、title等

(2) quote,将值转换为字符串,即加双引号

例如:从 .Values 中读取的值变成字符串,可以使用​​quote​​函数实现。

nodeSelector标签的值用了true正常使用会报错,这是因为它是关键字,需要加引号才可以。

# vim values.yaml
nodeSelector:
gpu: true

# vim templates/deployment.yaml
......
nodeSelector:
disktype: {{ quote .Values.nodeSelector.gpu }}

(3) default,设置默认值,如果获取的值为空则为默认值 示例:以防止忘记定义而导致模板文件缺少字段无法创建资源,这时可以为字段定义一个默认值。

# vim templates/deployment.yaml
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}

注:
这里用到了管道符"|",前面的值传递后函数验证是否为空。

(4) indent和nindent函数都是缩进字符串,主要区别在于nindent会在缩进前多添加一个换行符 示例:

# vim templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ .Release.Name | indent 0 }}
......

(5) toYaml,引用一块YAML内容

示例:在values.yaml里写结构化数据,引用内容块

# vim values.yaml
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi

# vim templates/deployment.yaml
......
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
resources: {{ toYaml .Values.resources | nindent 10

(6) 其他函数

# vim templates/deployment.yaml
......
{{ upper .Values.resources }}# 大写
{{ title .Values.resources }}# 首字母大写

5 流程控制

流程控制是为模板提供了一种能力,满足更复杂的数据逻辑处理,Helm模板语言提供的控制语句有,​​if/else​​ 条件判断、​​range​​ 循环、​​with​​ 指定变量作用域。

(1) 流程控制之 if/else 1)if/else 块是用于在模板中有条件的包含文本块的方法

​​

第23章:Helm应用包管理器_回滚_08

​​

条件判断,根据不同的条件做不同的行为,语法如下:
{{ if <表达式> }}
# 做某事
{{ else if <表达式> }}
# 做某事
{{ else }}
# 默认
{{ end }}

2)示例 部署一个应用,在没明确启用ingress时,默认情况下不启用。

# vim values.yaml
ingress:
enabled: false
annotations:
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true"
hosts:
host: www.lc.com
path: /
tls:
secretName: chart-example-tls
hosts: www.lc.com

# vim templates/ingress.yaml
{{ if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels: {{ include "labels" . | nindent 4 }}
name: {{ include "fullname" . }}
annotations: {{ toYaml .Values.ingress.annotations | nindent 4 }}
spec:
{{- if .Values.ingress.tls }}
tls:
- hosts:
- {{ .Values.ingress.tls.hosts }}
secretName: {{ .Values.ingress.tls.secretName }}
{{- end }}
rules:
- host: {{ .Values.ingress.hosts.host }}
http:
paths:
- path: {{ .Values.ingress.hosts.path }}
pathType: Prefix
backend:
service:
name: {{ include "fullname" . }}
port:
number: {{ .Values.service.port }}
{{ end }}

# 测试
# helm install test --set ingress.enabled=true --dry-run ./mychart/

# 如果值为以下几种情况则为false
一个布尔类型 false
一个数字 0
一个空的字符串
一个 nil(空或 null)
一个空的集合( map、 slice、 tuple、 dict、 array)
除了上面的这些情况外,其他所有条件都为真。

# 条件表达式也支持操作符
eq 等于
ne 不等于
lt 小于
gt 大于
and 逻辑与
or 逻辑或

3)消除判断空格

示例:如果是一个空的集合则不启用资源配额

# vim values.yaml
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi

# vim templates/deployment.yaml
......
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
{{ if .Values.resources }}
resources: {{ toYaml .Values.resources | nindent 10 }}
{{ end }}

验证渲染结果:
# helm install test --dry-run ./mychart/
渲染结果会发现有多余的空行,这是因为模板渲染时会将指令删除,所以原有的位置就空白了,可以使用横杠"-"消除空行。
"{{-" 表示删除左边的所有空格,直到非空格字符,"-}}" 表示删除右边的所有空格,还包括换行符、TAB字符。

示例:
# vim templates/deployment.yaml
......
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
{{- if .Values.resources }}
resources: {{ toYaml .Values.resources | nindent 10 }}
{{- end }}

4)判断一个空的数组

# vim values.yaml
resources: {}

# vim templates/deployment.yaml
......
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
{{- if .Values.resources }}
resources:
{{ toYaml .Values.resources | indent 10 }}
{{- end }}

(2) range

​​

第23章:Helm应用包管理器_mysql_09

​​

循环: 一般用于遍历序列结构的数据,例如序列、键值。

语法:
{{ range <值> }}
# 引用内容
{{ end }}

示例: 遍历数据
在 Helm 模板语言中,使用 range 关键字来进行循环操作,我们在 values.yaml 文件中添加上一个变量列表
# cat values.yaml
env:
- 1
- 2
- 3

# vim templates/deployment.yaml
......
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
env:
{{- range $k,$v := .Values.env }}
- name: {{ $k }}
value: {{ quote $v }}
{{- end }}

# 循环打印该列表
# vim templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
test: |
{{- range .Values.env }}
{{ . }}
{{- end }}

注:
循环内部我们使用的是一个".",这是因为当前的作用域就在当前循环内,这个"."引用的是当前读取的元素。

(3) with

with: 控制变量作用域 之前我们的 ​​{{ .Release.xxx }}​​或者 ​​{{ .Values.xxx }}​​,其中的 ​​.​​就是表示对当前范围的引用, ​​.Values​​就是告诉模板在当

前范围中查找 ​​Values​​对象的值,而 ​​with​​语句就可以来控制变量的作用域范围。

语法:
{{ with <值> }}
# 限制范围
{{ end }}

​with​​语句可以允许将当前范围 ​​.​​ 设置为特定的对象,比如使用​​.Values.nodeSelecotr​​,我们可以使用 ​​with​​来将​​.​​ 范围指向

​.Values.nodeSelecotr​​。

# vim values.yaml
nodeSelector:
team: a
gpu: yes

# vim templates/deployment.yaml
......
spec:
{{- $ReleaseName := .Release.Name -}}
{{- with .Values.nodeSelector }}
nodeSelector:
team: {{ .team }}
gpu: {{ .gpu }}
test: {{ $ReleaseName }}
{{- end }}
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
......
注:
上面增加了一个"{{- with .Values.label }} xxx {{- end }}"的一个块,这样的话就可以在当前的块里面直接引用".team"
和".gpu"了。"with"是一个循环构造,使用".Values.nodeSelector"中的值,将其转换为Yaml。
with 块限制了变量作用域,也就是无法直接引用模板对象,例如".Values"、".Release",with 语句块内不能再使用
".Release.Name"对象,否则报错,我们可以将该对象赋值给一个变量来解决这个问题,可以在 with 语句上面增加一句
"{{- $ReleaseName := .Release.Name -}}",其中"$ReleaseName"就是后面的对象的一个引用变量,它的形式就
是"$name",赋值操作使用":=",这样 with 语句块内部的"$ReleaseName"变量仍然指向的是".Release.Name"。

# 优化一下
# vim templates/deployment.yaml
......
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
......
注: toYaml之后的点是循环中".Values.nodeSelector"的当前值

6 变量

变量在实际应用中不多,但有时候结合​​with​​、​​range​​能更好的处理数据。

获取列表键值

# vim values.yaml
env:
NAME: "gateway"
JAVA_OPTS: "-Xmx1G"
hello: world

# vim templates/deployment.yaml
......
spec:
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
env:
{{- range $k,$v := .Values.env }}
- name: {{ $k }}
value: {{ quote $v }}
{{- end }}
注: 上面在 range 循环中使用 "$key" 和 "$value" 两个变量来接收后面列表循环的键和值。
# 输出结果
env:
- name: JAVA_OPTS
value: "-Xmx1G"
- name: NAME
value: "gateway"


# vim templates/deployment.yaml
......
containers:
- image: {{ .Values.image }}:{{ .Values.imageTag }}
name: nginx
env:
- name: NAME
{{- if eq .Values.env.hello "world" }}
value: true
{{- else }}
value: false
{{- end }}
# 输出结果
env:
- name: NAME
value: true

7 命名模板 命名模板类似于开发语言中的函数,指一段可以直接被另一段程序或代码引用的程序或代码。在编写chart时,可以将一些重复使用的内容 写在命名模板文件中供公共使用,这样可减少重复编写程序段和简化代码结构。命名模块使用define字段定义,模板中使用template字段 或include字段引入,在templates目录中默认下划线开头的文件为公共模板(_helpers.tpl)。

示例: 将资源名称生成指令放到公共模板文件中作为所有资源名称
# vim templates/_helpers.tpl
{{- define "fullname" -}}
{{- .Chart.Name }}-{{ .Release.Name }}
{{- end }}

{{- define "labels" -}}
app: {{ template "fullname" . }}
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
release: {{ .Release.Name }}
{{- end }}

# vim templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "fullname" . }}
labels:
{{- include "labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicas }}
......

# 得到的结果为
apiVersion: apps/v1
kind: Deployment
metadata:
name: mychart-test
labels:
app: mychart-test
chart: mychart-0.1.0
release: test
spec:
replicas: 1
......

template指令是将一个模板包含在另一个模板中的方法,但是template函数不能用于Go模板管道,为了解决该问题,引入了 include 指令。
上面包含一个名为 labels 的模板,然后将值 "."

3.7 写一个通用的Chart

1 创建步骤

(1) 先创建模板示例 helm create demo
(2) 修改Chart.yaml,Values.yaml,参考示例预留变动的字段值
(3) 在templates目录下准备部署应用所需的yaml文件,并添加指令引用Values.yaml字段
(4) 将重复使用的内容放到命名模板文件中
(5) 使用Chart结合参数部署多个同类服务

2 查看Chart的目录结构

# tree demo
demo
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ └── service.yaml
└── values.yaml

1 directory, 7 files

3 Chart.yaml

# cat demo/Chart.yaml
apiVersion: v2
appVersion: 0.1.0
description: java demo
name: demo
type: application
version: 0.1.0


创建Chart时的默认配置:
# egrep -v "^$|^#" mychart/Chart.yaml
apiVersion: v2
# Chart的api版本

name: mychart
# Chart的名称

description: A Helm chart for Kubernetes
# Chart的描述信息

type: application
# Chart可以是"应用程序"或"库"Chart。
# 应用程序Chart是一组模板,可以打包到要部署的版本化归档中。
# 库为Chart开发人员提供了有用的实用程序或函数。
# 它们作为应用程序Chart的依赖项包含在其中,用于将这些实用程序和函数注入渲染管道。
# 库Chart不定义任何模板,因此无法部署。

version: 0.1.0
# 这是Chart版本。
# 每次更改Chart及其模板(包括应用程序版本)时,此版本号应增加。
# 版本应遵循语义版本控制(https://semver.org/)。

appVersion: "1.16.0"
# 这是正在部署的应用程序的版本号。
# 每次更改应用程序时,此版本号都应递增。
# 版本不应遵循语义版本控制。
# 它们应该反映应用程序正在使用的版本。
# 建议将其与引号一起使用。

4 values.yaml

# cat demo/values.yaml
image:
pullPolicy: IfNotPresent
repository: lizhenliang/java-demo
tag: latest
imagePullSecrets: []
ingress:
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: 100m
nginx.ingress.kubernetes.io/proxy-connect-timeout: "600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "600"
enabled: true
host: example.lc.com
tls:
secretName: example-lc-com-tls
nodeSelector: {}
replicaCount: 3
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 100m
memory: 128Mi
service:
port: 80
type: ClusterIP
tolerations: []

5 templates

(1) deployment.yaml
# cat demo/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "demo.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "demo.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}

(2) _helpers.tpl
# cat demo/templates/_helpers.tpl
{{- define "demo.fullname" -}}
{{- .Chart.Name -}}-{{ .Release.Name }}
{{- end -}}

{{/*
公用标签
*/}}
{{- define "demo.labels" -}}
app: {{ template "demo.fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
{{- end -}}

{{/*
标签选择器
*/}}
{{- define "demo.selectorLabels" -}}
app: {{ template "demo.fullname" . }}
release: "{{ .Release.Name }}"
{{- end -}}

(3) ingress.yaml
# cat demo/templates/ingress.yaml
{{- if .Values.ingress.enabled -}}
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if .Values.ingress.tls }}
tls:
- hosts:
- {{ .Values.ingress.host }}
secretName: {{ .Values.ingress.tls.secretName }}
{{- end }}
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /
backend:
serviceName: {{ include "demo.fullname" . }}
servicePort: {{ .Values.service.port }}
{{- end }}

(4) NOTES.txt
# cat demo/templates/NOTES.txt
访问地址:
{{- if .Values.ingress.enabled }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.host }}
{{- end }}
{{- if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "demo.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
{{- end }}

(5) service.yaml
# cat demo/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "demo.selectorLabels" . | nindent 4




举报

相关推荐

0 条评论