文章目录
- 一、helm概述&安装
- 1.为什么需要Helm
- 2.Helm介绍
- 3.Helm架构
- 4.部署Helm客户端
- 5.Helm基本使用
- 5.1 创建Chart示例
- 二、Helm 应用部署、升级
- 1.创建项目(chat所需目录、文件)
- 2.创建/拷贝项目的yaml文件到templates目录下
- 3.使用Helm进行部署项目
- 4.Helm升级/更新项目
- 5.Helm回滚/卸载项目
- 5.1回滚到上一个版本
- 5.2回滚到指定版本
- 5.3卸载项目
- 6.Helm工作流程
- 三、Chart模板
- 1.内置对象
- 2.调试
- 3.函数与管道
- 4.动态读取文件内容
- 5.流程控制-if/else判断
- 6.流程控制-range循环
- 7.流程控制-with变量作用域
- 8.变量
- 9.命名模板
- 四、使用Harbor私有仓库集中管理Chart
- 1.启用Harbor的Chart仓库服务
- 2.安装push插件
- 3.添加repo仓库
- 4.推送
- 5.部署chart
- 五、公共Chart仓库
- 1.本地添加dashborad的库
- 2.直接部署dashboard
- 3.将dashboard的chart下载到本地进行修改
- 六、一步步编写Chart模版
一、helm概述&安装
1.为什么需要Helm
(为了更高效的部署管理我们的应用)
由于kubernetes缺少对发布的应用版本控制和管理,使得部署的应用维护和更新等方面面临诸多的挑战,主要面临以下问题;
- 目前YAML资源文件分散,如何将这些YAML作为一个整体进行管理?
- 这些YAML资源文件如何高效的复用?
- 不支持应用级别的版本管理!例如回滚,目前只支持单个Depolyment
2.Helm介绍
Helm是一个Kubernetes的 包 管理工具,就像Linux下的包管理器,如yum/apt等,可以很方便的将之前打好的yaml文件部署到kubernetes上。
Helm有3个重要概念:
- Helm:一个命令行客户端工具,主要用于Kubernetes应用chart的创建、打包、发布和管理;
- Chart:应用描述,一系列用于描述k8s资源相关文件的集合(一堆yaml的集合);
- Release:基于Chart的部署实体,一个chart被Helm运行后将会生成对应的一个release;将在k8s中创建出真实运行的资源对象;
3.Helm架构
Helm目前有两个大版本:V2和V3
2019年11月Heml团队发布V3版本,相比于V2版本最大的变化是将Tiller删除,并大部分代码重构
V2工作流程:
helm客户端通过yaml将chart部署到k8s里面,会经过一个组件Tiller,这个组件起到了一个承上启下的作用,它负责接收客户端的请求,再调用K8s的api完成部署;
V3工作流程:
helm客户端通过kubeconfig去连接k8s集群去完成应用的部署,跟kubectl一样;
4.部署Helm客户端
使用Helm很简单,只需要下载一个二进制的客户端包即可,它会通过kubeconfig配置(默认是在$HOME/.kube/config)来链接kubernetes。
项目地址:
下载Helm客户端:https://github.com/helm/helm
Helm官网:https://helm.sh/
[root@k8s-master ~]# wget -c https://get.helm.sh/helm-v3.13.3-linux-amd64.tar.gz
[root@k8s-master ~]# tar -zxf helm-v3.13.3-linux-amd64.tar.gz
#解压完之后直接将二进制文件helm丢到 二进制目录下即可执行helm命令
[root@k8s-master ~]# mv linux-amd64/helm /usr/bin/
[root@k8s-master ~]# helm --help
5.Helm基本使用
Helm管理应用生命周期:
- helm create 创建Chart示例
- helm install 部署
- helm upgrade 更新
- helm rollback 回滚
- helm uninstall 卸载
5.1 创建Chart示例
创建chart:
helm create mychart #示例中默认是部署一个nginx服务
打包chart:
helm package mychart
[root@k8s-master ~]# helm create mychart
Creating mychart
[root@k8s-master ~]# cd mychart/
[root@k8s-master mychart]# ll
总用量 8
drwxr-xr-x 2 root root 6 4月 5 22:21 charts
-rw-r--r-- 1 root root 1143 4月 5 22:21 Chart.yaml
drwxr-xr-x 3 root root 162 4月 5 22:21 templates
-rw-r--r-- 1 root root 2252 4月 5 22:21 values.yaml
- charts:目录里存放这个chart依赖的所有子chart;
- Chart.yaml:用于描述这个Chart的基本信息,包括名字、描述信息及版本等;
- values.yaml:用于存储templates目录中模板文件中用到的 变量 的值;
- templates:目录里面存放所有的yaml模板文件,例如deployment,service,ingress等;
- NOTES.txt:用于介绍Chart的帮助信息,helm install部署后展示给用户,例如:如何使用这个Chart、列出缺省的设置等;
- _helpers.tpl:放置模板的地方,可以在整个chart中重复使用;
[root@k8s-master mychart]# helm install demo /root/mychart/
#部署信息
NAME: demo
LAST DEPLOYED: Fri Apr 5 22:33:10 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
#部署提示(NOTES.txt中的内容)
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=demo" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
#列出之前的部署情况
[root@k8s-master mychart]# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
demo default 1 2024-04-05 22:33:10.226678647 +0800 CST deployed mychart-0.1.0 1.16.0
#然后使用kubectl就可以看到使用chart部署的这个pod示例了
[root@k8s-master mychart]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/demo-mychart-6fd7f6cd64-fjnwc 0/1 ContainerCreating 0 2s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/demo-mychart ClusterIP 10.97.197.171 <none> 80/TCP 2s
#卸载chart
[root@k8s-master mychart]# helm uninstall demo
release "demo" uninstalled
二、Helm 应用部署、升级
命令 | 描述 |
---|---|
completion | 命令补全,source <(helm completion bash) |
create | 创建一个chart并指定名字 |
dependency | 管理chart依赖 |
get | 下载一个release。可用子命令:all、hooks、manifest、notes、values |
help | 命令的帮助文档 |
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客户端版本 |
接下来我们先使用helm自定义创建部署一个chant应用
1.创建项目(chat所需目录、文件)
[root@k8s-master ~]# mkdir chart-prod
[root@k8s-master ~]# cd chart-prod/
[root@k8s-master chart-prod]# touch Chart.yaml
#这里需要编辑Chart.yaml文件里的内容,否则在使用helm部署项目时候会报错(可以直接复制helm create xxx 生成的Chart.yaml模板内容进行修改)
[root@k8s-master chart-prod]# vim Chart.yaml
apiVersion: v2
#chart的名称
name: chart-prod
#chart的描述
description: This is chart-prod
#类型默认
type: application
#chart的版本随便写
version: 0.1.0
#应用的版本随便写即可
appVersion: "1.16.0"
[root@k8s-master chart-prod]# touch values.yaml
[root@k8s-master chart-prod]# mkdir templates
[root@k8s-master chart-prod]# touch templates/_helpers.tpl
[root@k8s-master chart-prod]# touch templates/NOTES.txt
#最终目录结构如下
[root@k8s-master ~]# tree chart-prod/
chart-prod/
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── NOTES.txt
│ └── service.yaml
└── values.yaml
1 directory, 6 files
2.创建/拷贝项目的yaml文件到templates目录下
这里就是将我们项目的deployment/service/ingress的yaml文件拷贝或创建到我们的templates目录下
Ps:我这里直接创建一个nginx的deployment/service
[root@k8s-master ~]# kubectl create deployment web --image=nginx:1.16 --dry-run=client -o yaml > deployment.yaml
[root@k8s-master ~]# kubectl create service nodeport web --tcp=80:80 --dry-run=client -o yaml > service.yaml
[root@k8s-master ~]# mv deployment.yaml chart-prod/templates/
[root@k8s-master ~]# mv service.yaml chart-prod/templates/
#以上的操作只是将原本就可以部署的yaml文件移动到templates目录下,并不能发挥到helm的能力,解决我们的痛点(痛点是第一步,为什么使用helm)
#接下来才是真正的使用helm 修改 deployment的值 使用 valumes.yaml文件中的变量(这样可以方便后期一个yaml部署多个项目)
[root@k8s-master chart-prod]# vim templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web
#使用内置变量.Release.Name 动态的来生成资源名称 这个名称使用的是 "heml install xxx" 时的 xxx
#如果不修改为这个内置变量的话在使用同一套chart创建多个项目的时候会报已经有这个deployemnt资源的错,因为k8s的资源名称必须是唯一的!
name: {{ .Release.Name }}
spec:
#使用在values.yaml文件中自定义的变量replicas的值
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
#使用在values.yaml文件中自定义的变量image的值
- image: {{ .Values.image }}
name: nginx
#service也是同理
[root@k8s-master chart-prod]# vim templates/service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: web
name: {{ .Release.Name }}
spec:
ports:
- name: 80-80
port: 80
protocol: TCP
targetPort: 80
selector:
app: web
type: NodePort
#在values.yaml中添加要在templates目录下yaml文件中要修改的值
[root@k8s-master chart-prod]# vim values.yaml
replicas: 3
image : nginx:1.16
#现目录结构如下
[root@k8s-master chart-prod]# tree templates/
templates/
├── deployment.yaml
├── _helpers.tpl
├── NOTES.txt
└── service.yaml
0 directories, 4 files
3.使用Helm进行部署项目
使用helm部署/更新等操作时候,可以用 -n 来指定命名空间
[root@k8s-master ~]# helm install web /root/chart-prod/ -n default
NAME: web
LAST DEPLOYED: Sat Apr 6 00:28:41 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
[root@k8s-master ~]# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
web default 1 2024-04-06 00:28:41.408736547 +0800 CST deployed chart-prod-0.1.0 1.16.0
[root@k8s-master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/web-96d5df5c8-hw5cj 1/1 Running 0 80s
pod/web-96d5df5c8-spqvn 1/1 Running 0 80s
pod/web-96d5df5c8-w7lzm 1/1 Running 0 80s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 86d
service/web NodePort 10.104.133.20 <none> 80:30451/TCP 81s
[root@k8s-master ~]# curl -I 10.104.133.20
HTTP/1.1 200 OK
Server: nginx/1.16.1
...
4.Helm升级/更新项目
使用Chart升级应用有两种方法:
- –values,-f:指定YAML对原有的templates目录下的yaml中的值进行覆盖以达到升级效果
- –set:在命令行上直接指定覆盖值进行升级
示例:将上面部署的 nginx1.16.1版本 升级为 nginx1.17版本,副本数从3修改为1
第一种方式(指定yaml文件进行覆盖):
[root@k8s-master ~]# vim abc.yaml #在任意路径都行
replicas: 1
image : nginx:1.17
[root@k8s-master ~]# helm upgrade web /root/chart-prod/ -f abc.yaml
Release "web" has been upgraded. Happy Helming!
NAME: web
LAST DEPLOYED: Sat Apr 6 01:04:43 2024
NAMESPACE: default
STATUS: deployed
#可以发现这里版本已经变成升级为2了
REVISION: 2
TEST SUITE: None
#此时去验证nginx是否升级为1.17
[root@k8s-master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE 1/1 Running 1 10d
pod/web-5899d78c9-wff2z 1/1 Running 0 79s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 86d
service/web NodePort 10.99.157.130 <none> 80:30457/TCP 9m45s
[root@k8s-master ~]# curl -I 10.99.157.130
HTTP/1.1 200 OK
Server: nginx/1.17.10
第二种方式(在命令行使用–set进行覆盖):
[root@k8s-master ~]# helm upgrade web /root/chart-prod/ --set image=nginx:1.17 --set replicas=1
Release "web" has been upgraded. Happy Helming!
NAME: web
LAST DEPLOYED: Sat Apr 6 01:11:06 2024
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
5.Helm回滚/卸载项目
heml查看历史版本
[root@k8s-master ~]# helm history web
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sat Apr 6 01:11:58 2024 superseded chart-prod-0.1.0 1.16.0 Install complete
2 Sat Apr 6 01:12:05 2024 deployed chart-prod-0.1.0 1.16.0 Upgrade complete
5.1回滚到上一个版本
#现在版本nginx1.17 副本数为1,回滚到nginx1.16 副本数为3
[root@k8s-master ~]# helm rollback web
Rollback was a success! Happy Helming!
[root@k8s-master ~]# kubectl get pods,svc
NAME READY STATUS RESTARTS AGE
pod/web-6bc4dfc596-dgrck 1/1 Running 0 16s
pod/web-6bc4dfc596-njf9d 1/1 Running 0 18s
pod/web-6bc4dfc596-prtl9 1/1 Running 0 14s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 86d
service/web NodePort 10.103.75.187 <none> 80:31867/TCP 4m37s
[root@k8s-master ~]# curl -I 10.103.75.187
HTTP/1.1 200 OK
Server: nginx/1.16.1
...
5.2回滚到指定版本
回滚到指定版本的话需要指定 历史版本的版本号
[root@k8s-master ~]# helm rollback web 1
Rollback was a success! Happy Helming!
Ps:
我们可以在每次部署/升级的时候使用 –description 来添加描述,例如:当前的版本是多少,这样可以方便我们后期回滚时查看到我们的版本记录
[root@k8s-master ~]# helm install web /root/chart-prod/ --description v1.17
[root@k8s-master ~]# helm upgrade web /root/chart-prod/ --set image=nginx:1.18 --set replicas=1 --description v1.18
5.3卸载项目
[root@k8s-master ~]# helm uninstall web
6.Helm工作流程
- 从镜像仓库拉取chart,这个chart里会包含我们项目所需的各个yaml模板,例如deployment、service、ingress等;
- helm将values对象(chart保重values.yaml文件/helm install、helm upgrade的-f参数传入的自定义yaml文件/–set参数传入的值)合并渲染到我们的yaml模板中形成完整的yaml清单;
- helm再将应用发布到k8s里;
三、Chart模板
Helm核心是模板,即模板化k8s YAML文件。
通过模板实现Chart高效复用,当部署多个应用时,可以将差异化的字段进行模板化,在部署时使用-f或者–set动态覆盖默认值,从而适配多个应用
1.内置对象
在上面示例中,模板文件中.Release、.Values是Helm的内置对象,顶级开头写。
Release对象:获取发布记录信息
内置 | 描述 |
---|---|
Release.Name | release名称(helm install xxx 名称就是这个xxx) |
Release.Time | release的时间 |
Release.Namespace | release的命名空间 |
Release.Service | release服务的名称 |
Release.Revision | release的修订版本号,从1开始累加 |
Values对象:为Chart模板提供值,这个对象的值有3个来源:
- chat包中的values.yaml文件
- helm install或者helm upgrade的-f或者–values参数传入的自定义yaml文件
- –set参数传入值
Chart对象:可以通过Chart对象访问Chart.yaml文件的内容,例如:{{ .Chart.AppVersion }}
2.调试
作用:当使用从网上下载的chart时,想知道它都使用了那些资源,资源的配置是什么,这个时候就能用–dry-run 或者 --template来列出来查看;
本地呈现渲染结果(查看下载后默认渲染的资源文件)
#helm template mychart
还可以在helm install 时使用 –dry-run和**–debug**进行调试参数,帮助验证模版的正确性,并把渲染后的模版打印出来,而不去真正的去部署;
如下:
–dry-run和–template的区别在于前者会经过k8s校验,使用时可以加-f或者–set参数,后者不会经过校验也不能使用参数 只能查看下载后默认的资源配置;
3.函数与管道
常用函数:
- quote:将值转换为字符串,也就是加上双引号
- default:设置默认值,如果获取的值为空则使用默认值
- indent和nindent:缩进字符串
- toYaml:引用一块YAML内容
- 其他函数:upper、title等
quota:将值转换为字符串,也就是加上双引号
示例:nodeSelector标签的值用了true 正常使用的话会报错,这是因为true它是关键字,需要加引号才可以
#values.yaml
nodeSelector:
gpu: true
#templates/deployment.yaml
...
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
可以用–dry-run调试命令查看会发现true 加上了双引号
[root@k8s-master templates]# helm upgrade web /root/chart-prod/ --dry-run
default:设置默认值,如果获取的值为空则使用默认值
示例:以防止忘记定义而导致模版文件缺少字段无法创建资源,这时可以为字段定义一个默认值;
image: {{ .Values.image }}:{{ .Values.tag | default “1.19” }}
这里会用到管道符"|",前面的值传递后函数验证是否为空;
#values.yaml
image : nginx
tag: ""
#templates/deployment.yaml
...
containers:
- image: {{ .Values.image }}:{{ .Values.tag | default "1.19" }}
或者使用Chart的版本号作为默认值
- image: {{ .Values.image }}:{{ .Values.tag | default .Chart.AppVersion }}
如果不设置默认值的话,在install / upgrade时会报如下错误
indent和nindent:都是缩进字符串,主要区别在于nindent会在缩进前多添加一个换行符
示例
#templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
#indent 6 代表缩进6个空格
#nindent 6 代表换行并缩进6个空格
app: {{ .Release.Name | indent 6 }}
app: {{ .Release.Name | nindent 6 }}
效果为:
indent和nindent的使用场景:
经常会在引用一个块Yaml的时候使用,例如下面要看的toYaml
toYaml:引用一块YAML内容
普遍{{ .Values.xxx.xxx }}这种key value格式适合不变化的字段,而toYaml可以适用于经常变化的字段,不管选中的块yaml里有没有变化的字段,都可以直接按一个整体传入到模版里
示例
#values.yaml
...
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
#templates/deployment
...
containers:
#使用在values.yaml文件中自定义的变量image的值
- image: {{ .Values.image }}:{{ .Values.tag | default .Chart.AppVersion }}
name: nginx
resources: {{ toYaml .Values.resources | nindent 10}}
#也可以使用indent
#resources:
#{{ toYaml .Values.resources | indent 10}}
其他函数:upper、title等
upper:将引用的值大写
title:将引用的值首字母大写
例如
upper
#values.yaml
nodeSelector:
gpu: true
#templates/deployment.yaml
...
metadata:
labels:
app: {{ upper .Release.Name }}
...
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu | upper}}
例如:
title
#values.yaml
nodeSelector:
gpu: true
#templates/deployment.yaml
...
metadata:
labels:
app: {{ title .Release.Name }}
...
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu | title}}
4.动态读取文件内容
有时想从文件中(例如a.txt)导入内容,可以通过.Files对象进行实现
.Files.Get可以获取文件的内容传到configmap里
.Files.Glob方法返回所有匹配的文件路径列表,当做个文件时,可以更灵活的提取某些文件(多个)
示例:configmap动态读取文件内容
普遍的configmap如下
.Files.Get可以获取文件的内容传到configmap里
例如单独创建一个redis的配置文件
[root@k8s-master chart-prod]# pwd
/root/chart-prod
[root@k8s-master chart-prod]# mkdir files
[root@k8s-master chart-prod]# vim files/config.yaml
name: fandaoshuai
host: 192.168.1.1
port: 6379
[root@k8s-master chart-prod]# vim templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
config.yaml: |
#"files/config.yaml为文件所在的绝对目录"
{{ .Files.Get "files/config.yaml" | indent 4}}
#若有多个文件且文件名称固定的话,可以用这种方式继续往下写
#config.yaml: |
#{{ .Files.Get "files/config2.yaml" | indent 4}}
然后保存调试一下
上面是将单个文件的内容传到configmap中,其实也可以同时将多个文件都传入configmap中;
.Files.Glob方法返回所有匹配的文件路径列表,当做个文件时,可以更灵活的提取某些文件
#files/config.yaml
name: fandaoshuai
host: 192.168.1.1
port: 6379
#files/config2.yaml
name: zt
javajdbc: http://192.168.1.2:3306
#templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
{{- $root := . }}
{{- range $path, $bytes := .Files.Glob "files/*.yaml" }}
{{ base $path }}: |
{{ $root.Files.Get $path | indent 4 }}
{{- end }}
配置完成后进行–dry-run调试
5.流程控制-if/else判断
Helm模版语言提供一下流程控制语句
- if/else:条件判断
- range:循环
- with:指定变量作用域
if/else
条件判断:根据不同的条件做不同的行为
语法:
{{ if <表达式> }}
#做某事
{{ else if <表达式> }}
#做某事
{{ else }}
#默认
{{ end }}
示例:部署一个应用,在没明确启用ingress时,默认情况下不启用
#values.yaml
ingress:
enabled: false
#templates/ingress.yaml
{{ if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}
#annotations:
#nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: "web.study.com"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}
port:
number: 80
{{ end }}
这样是默认不启用的,除非在部署更新调试时将enabled的值改为true,–set ingress.enabled=true 或者 直接修改values.yaml文件里enabled的值才可以启用
ps:
如果值为以下几种情况则为false(按照上面这个例子,是不会启用ingress的):
- 一个布尔类型 false
- 一个数字 0
- 一个空的字符串
- 一个nil(空或null)
- 一个空的集合(map、slice、tuple、dict、array)
条件表达式也支持操作符:
- eq 等于
- ne 不等于
- lt 小于
- gt 大于
- and 逻辑与
- or 逻辑或
例如 标签的值eq等于456话,输出123,否则输出456
#values.yaml
label:
test: "123"
#templates/deployment.yaml
...
labels:
{{ if eq .Values.label.test "456" }}
test: "123"
{{ else }}
test: "456"
{{ end }}
现在调试的话输出的值为456
修改values.yaml的值为456的话在此调试这个test标签的值会变为123
在我们配置完进行调试/渲染的时候,会发现有多余的空行,这是因为模版渲染时会将指令删除,所以原有的位置就空白了。可以使用横杠"-"消除空行;
例如:
#templates/deployment.yaml
...
{{- if eq .Values.label.test "456" }}
test: "123"
{{- else }}
test: "456"
{{- end }}
6.流程控制-range循环
循环:一般用于遍历序列结构的数据。例如序列、键值等
语法:
{{ range <值> }}
#引用内容
{{ end }}
示例:将values里的内容遍历出来
#values.yaml
test:
- 1
- 2
- 3
#templates/config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
test: |
{{- range.Values.test }}
{{ . }} #引用当前内容
{{- end }}
然后进行调试
7.流程控制-with变量作用域
指的是指定变量的生效范围(简化代码)
with语句可以允许将当前范围.设置为特定的对象,比如前面一直使用的.Values.nodeSelector 我们可以使用with来将 . 范围指向.Values.nodeSelector:
示例:指定nodeSelector为作用域
#values.yaml
nodeSelector:
gpu: "true"
disktype: ssd
#templates/deployment.yaml
...
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
#gpu: {{ .Values.nodeSelector.gpu }}
#在正常不使用作用域的情况下需要这样进行引用values.yaml中的值,当把values.yaml中的nodeSelector做成作用域的话即可直接引用相应的值,如下:
#调试时,需要把这几行的注释给删掉,要不然会报错
gpu: {{ .gpu }}
disktype: {{ .disktype }}
{{- end }}
containers:
这样看with块是限制了变量作用域,也就是无法直接引用模版对象,例如.Values、.Release,如果还想使用这种方式的话,可以定义变量来解决这个问题
示例:在with作用域中引用模版对象
#values.yaml
nodeSelector:
gpu: true
disktype: ssd
#templates/deployment.yaml
...
spec:
#定义变量$disktype来引用.Values.nodeSelector.disktype
{{- $disktype := .Values.nodeSelector.disktype }}
{{- with .Values.nodeSelector }}
nodeSelector:
gpu: {{ .gpu }}
#这里来使用变量即可
disktype: {{ $disktype }}
{{- end }}
containers:
8.变量
变量在实际应用中不多,但有时候结合with、range能够更好的处理数据;
示例:在k8s中变量是键值 ,可以range遍历生成并引用
#values.yaml
env:
SERVER_NAME: protal
PORT: 80
HOST: 127.0.0.1
#templates/deployment.yaml
...
resources: {{ toYaml .Values.resources | nindent 10}}
env:
{{- range $k,$v := .Values.env }}
- name: {{ $k }}
value: {{ quote $v }}
{{- end }}
调试查看yaml效果
9.命名模板
命名模板类似于开发语言中的函数,指一段可以直接被另一段程序或代码引用的程序或代码。在编写Chart时,可以将一些重复使用的内容写在命名模板文件中供公共使用,这样可以减少重复编写程序段和简化代码结构。
命名模板使用define定义,template(不支持管道)或include引入,在templates目录中默认下划线开头的文件为公共模板(_helpers.tpl)
示例:我们可以在template目录下的所有yaml资源中找到共同使用的字段配置,这里用"name"和"labels"字段来举例,把它加入模板 供我们引用;
ps:#只有使用命名模板的时候会在右边产生空行,所以也需要在开头右边加上"-"
#templates/_helpers.tpl
#name
{{- define "fullname" -}}
{{ .Chart.Name }}-{{ .Release.Name }}
{{- end -}}
#templates/service.yaml
apiVersion: v1
kind: Service
metadata:
#使用template 进行引用模板中的键获取值
name: {{ template"fullname" . }}
...
dry-run调试结果如下
helm install web /root/chart-prod/ --dry-run
template指令是将一个模板包含在另一个模板中的方法(yaml资源可以引用模板中的键获取值),但是template函数不能用于Go模板通道。为了解决这个问题,引入include指令,如下lables:
#labels
#values.yaml
label:
project: www
app: nginx
#templates/_helpers.tpl
#labels
{{- define "labels" -}}
project: {{ .Values.label.project }}
app: {{ .Values.label.app }}
chartname: {{ .Chart.Name }}
{{- end -}}
#templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
labels: {{ include "labels" . | nindent 4 }}
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels: {{ include "labels" . | nindent 6 }}
#templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: {{ include "fullname" .}}
spec:
...
selector: {{ include "labels" . | nindent 4}}
dry-run调试结果如下
helm install web /root/chart-prod/ --dry-run
四、使用Harbor私有仓库集中管理Chart
Harbor是一个主流的镜像仓库系统,在v1.6版本以后的harbor中新增加了helm charts的管理功能,可以存储Chart文件。使用步骤:
前置条件:
#给编写好的helm进行打包
[root@k8s-master ~]# helm package chart-dev
[root@k8s-master ~]# ll
drwxr-xr-x 5 root root 4096 Apr 16 16:04 chart-dev
-rw-r--r-- 1 root root 3982 Apr 16 17:18 chart-dev-0.1.0.tgz
1.启用Harbor的Chart仓库服务
[root@iZbp1j85tynrpi0u439x2cZ harbor]# pwd
/hqtbj/hqtwww/harbor_workspace/harbor
[root@iZbp1j85tynrpi0u439x2cZ harbor]# ./install.sh --with-chartmuseum
启用后,默认创建的项目就带有helm charts功能了
2.安装push插件
[root@k8s-master ~]# helm plugin install https://github.com/chartmuseum/helm-push
也可以直接将二进制包下载下来解压然后把解压过后的 bin目录以及/plugin.yaml放在helm的plugin目录下即可
[root@k8s-master ~]# tar -zxf helm-push_0.10.4_linux_amd64.tar.gz
[root@k8s-master ~]# ls
bin plugin.yaml
[root@k8s-master ~]# ls bin/
helm-cm-push
[root@k8s-master helm]# cd $HOME/.cache/helm
[root@k8s-master helm]# mkdir plugins/cm-push
[root@k8s-master helm]# mv /root/plugin.yaml /root/bin plugins/cm-push/
3.添加repo仓库
[root@k8s-master ~]# helm repo add --username admin --password xxxxxx myrepo https://dev-registry.hqxxx.net/chartrepo/library
"myrepo" has been added to your repositories
[root@k8s-master ~]# helm repo update
[root@k8s-master ~]# helm repo list
NAME URL
myrepo https://dev-registry.hqxxx.net/chartrepo/library
4.推送
[root@k8s-master ~]# helm cm-push chart-dev-0.1.0.tgz --username admin --password xxxx https://dev-registry.hqxxx.net/chartrepo/library
Pushing chart-dev-0.1.0.tgz to https://dev-registry.hqtong.net/chartrepo/library...
Done.
5.部署chart
当我们把打包好的chart上传至harbor仓库后,后续进行部署时就可以直接在仓库里拉取进行部署,类似于镜像一样
[root@k8s-master ~]# helm repo list
NAME URL
myrepo https://dev-registry.hqtong.net/chartrepo/library
[root@k8s-master ~]# helm install energy-order-api --version 0.1.0 myrepo/chart-dev
–version:这里的version是chart的版本号,在打包时可以修改chart目录里的Chart.yaml文件进而改变上传到harbor的版本
# chart-dev/Chart.yaml
version: 0.1.0
五、公共Chart仓库
官方维护了一个公共的仓库,可直接使用它们制作好的包
官方仓库:https://artifacthub.io/
例如使用Chart部署Kubernetes Dashboard:https://artifacthub.io/packages/helm/k8s-dashboard/kubernetes-dashboard
1.本地添加dashborad的库
[root@k8s-master ~]# helm repo add kubernetes-dashboard https://kubernetes.github.io/dashboard/
[root@k8s-master ~]# helm repo list
NAME URL
kubernetes-dashboard https://kubernetes.github.io/dashboard
[root@k8s-master ~]# helm repo update
2.直接部署dashboard
#因为我的集群版本是v1.20.11 最新的dashboard不支持这个版本,所以我直接指定的老版本进行的部署
[root@k8s-master ~]# helm install kubernetes-dashboard --version 6.0.8 kubernetes-dashboard/kubernetes-dashboard
#使用edit修改svc的类型为NodePort来访问试下
[root@k8s-master ~]# kubectl edit service/kubernetes-dashboard
...
type: NodePort
[root@k8s-master ~]# kubectl get pod,svc
NAME READY STATUS RESTARTS AGE 1/1 Running 0 251d
pod/kubernetes-dashboard-7bfccf4c5b-gglnq 1/1 Running 0 5m52s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 296d
kubernetes-dashboard NodePort 10.97.23.85 <none> 443:31502/TCP 15m
后续获取个token就可以了,这里略过 可以参考:https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md
3.将dashboard的chart下载到本地进行修改
上面我们是直接对公共仓库里的chart进行部署的,我们可以将它的chart下载下来查看都使用了哪些资源并可以自己修改;
[root@k8s-master ~]# helm pull kubernetes-dashboard/kubernetes-dashboard --version 6.0.8
[root@k8s-master ~]# ll
total 27972
-rw-r--r-- 1 root root 18717 Apr 17 11:18 kubernetes-dashboard-6.0.8.tgz
[root@k8s-master ~]# tar -zxf kubernetes-dashboard-6.0.8.tgz
[root@k8s-master kubernetes-dashboard]# ll
total 36
-rw-r--r-- 1 root root 247 May 19 2023 Chart.lock
drwxr-xr-x 3 root root 4096 Apr 17 11:22 charts
-rw-r--r-- 1 root root 602 May 19 2023 Chart.yaml
-rw-r--r-- 1 root root 7068 May 19 2023 README.md
drwxr-xr-x 2 root root 4096 Apr 17 11:22 templates
-rw-r--r-- 1 root root 11605 May 19 2023 values.yaml
#可以使用dry-run查看渲染后使用的资源
[root@k8s-master ~]# helm install kubernetes-dashboard /root/kubernetes-dashboard --dry-run
#修改service的类型为Nodeport类型
[root@k8s-master ~]# vim kubernetes-dashboard/values.yaml
...
service:
直接将ClusterIP改为需要的Nodeport类型即可
#type: ClusterIP
type: NodePort
# Dashboard service port
externalPort: 443
六、一步步编写Chart模版
详情可见:https://download.csdn.net/download/qq_44930876/89155278
总结:以上就是关于helm的学习与总结,到这里我们就可以一步步的编写我们服务所用到的chart了,健康检查、资源限制、数据持久化、污点亲和性等等;