Kubernetes部署应用利器Helm详解


一、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 45 22:21 charts
-rw-r--r-- 1 root root 1143 45 22:21 Chart.yaml
drwxr-xr-x 3 root root  162 45 22:21 templates
-rw-r--r-- 1 root root 2252 45 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工作流程

在这里插入图片描述

  1. 从镜像仓库拉取chart,这个chart里会包含我们项目所需的各个yaml模板,例如deployment、service、ingress等;
  2. helm将values对象(chart保重values.yaml文件/helm install、helm upgrade的-f参数传入的自定义yaml文件/–set参数传入的值)合并渲染到我们的yaml模板中形成完整的yaml清单;
  3. helm再将应用发布到k8s里;



三、Chart模板

Helm核心是模板,即模板化k8s YAML文件。
通过模板实现Chart高效复用,当部署多个应用时,可以将差异化的字段进行模板化,在部署时使用-f或者–set动态覆盖默认值,从而适配多个应用
Helm模板由Go  Template编写,指令由于{​{ }}包裹

1.内置对象

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

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

内置描述
Release.Namerelease名称(helm install xxx 名称就是这个xxx)
Release.Timerelease的时间
Release.Namespacerelease的命名空间
Release.Servicerelease服务的名称
Release.Revisionrelease的修订版本号,从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:设置默认值,如果获取的值为空则使用默认值
  • indentnindent:缩进字符串
  • 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时会报如下错误
在这里插入图片描述

indentnindent:都是缩进字符串,主要区别在于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了,健康检查、资源限制、数据持久化、污点亲和性等等;

  • 17
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不知名运维:

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值