侧边栏壁纸
博主头像
孔子说JAVA博主等级

成功只是一只沦落在鸡窝里的鹰,成功永远属于自信且有毅力的人!

  • 累计撰写 297 篇文章
  • 累计创建 134 个标签
  • 累计收到 4 条评论

目 录CONTENT

文章目录

Helm3入门教程-5:Helm Chart 的编写

孔子说JAVA
2022-04-15 / 0 评论 / 0 点赞 / 376 阅读 / 9,036 字 / 正在检测是否收录...

Helm3入门教程全系列,26小时轻松掌握Helm

在Kubernetes环境中使用Helm来管理应用颇为方便,在教程的这部分,我们一起来开发一个Chart(简单说就是一个软件包),这样的实战可加深对Chart的理解,今后在使用第三方的Chart时,不论学习还是修改都会更加得心应手。

  • 在k8s中,一般是通过yaml文件把要创建的service、pod等定义好,很可能会产生多个yaml文件,将这些文件放在一个目录中,就变成一个chart了。

1_20220415162558

环境的版本信息如下,请确保以下软件都已运行正常:

  1. 操作系统 :Ubuntu 20.04.3 LTS (查看命令:lsb_release -a
  2. Kubernetes:v1.23.5(查看命令:kubectl version
  3. Helm:v3.8.1(查看命令:helm version

1、创建并发布一个简单的Helm Chart

注意:yaml格式文件修改需要注意的几个地方:

  1. 使用2个空格作缩进;
  2. 确认数字为字符类型时,使用双引号引起来;
  3. 为了迎合helm3的规范,空定义最好将相关符号补上:string: ""list: []map: {}

1.1 构建一个Helm Chart模板

执行 helm create mychart命令,会得到一个 helm 自动生成的空 chart。这个 chart 里的名称是 mychart。 使用 tree mychart 命令可以查看mychart的目录结构。

  • 注意: Chart.yaml 里面的 name 名称需要和生成的 Chart 文件夹名称一致(本例是mychart)。如果修改 mychart,则需要做一致的修改。

1_20220415101528

mychart/
  Chart.yaml          # 用于描述 chart 信息的 yaml 文件
  LICENSE             # 可选:用于存储关于 chart 的 LICENSE 文件
  README.md           # 可选:README 文件
  values.yaml         # 用于存储 chart 所需要的默认配置
  values.schema.json  # 可选: 一个使用JSON结构的 values.yaml 文件
  charts/             # 包含 chart 所依赖的其他 chart
  crds/               # 自定义资源的定义
  templates/          # chart 模板文件,引入变量值后可以生成用于 Kubernetes 的 manifest 文件
  templates/NOTES.txt # 可选: 包含简短使用说明的纯文本文件,会在用户运行 `helm install` 时显示给用户。
  templates/_helpers.tpl 	# 放置可以通过chart复用的模板辅助对象(模板助手),所有模板都可以在这里定义,然后在任何yaml文件当中都可以调用这个文件下的模板。
  templates/deployment.yaml 	#kubernetes Deployment object,创建Kubernetes 工作负载的基本清单。
  templates/service.yaml 	#kubernetes Serivce,为你的工作负载创建一个service终端基本清单。

从这里开始,我们将在 mychart 目录中工作。由于创建的chart已经是一个nginx示例,所以它是可以运行的。至此,我们的创建的第一个chart就完成了,是不是很简单。

1.2 修改Chart.yaml

在根目录下的 Chart.yaml 文件内,声明了当前 Chart 的名称、版本等基本信息,这些信息会在该 Chart 被放入仓库后,供用户浏览检索。

  • apiVersion k8s api 版本
  • name chart名,英文开头,支持小写字母,数字,减号(-)
  • version chart 版本,也就是我们应用包的发布版本,版本必须遵循 SemVer 2 标准
  • appVersion 内部程序版本即代码版本(内部实际使用的应用版本)
  • description 描述
  • keywords 分类,关键词
  • home 应用程序官网
  • icon 图标,支持 url 和 base64
  • maintainers 作者
  • sources 应用程序来源

使用命令 vim mychart/Chart.yaml,编写mychart的应用描述信息。修改后的内容如下:

  • 如有必要可以修改app版本和包版本,一般情况不做修改
  • keywords、home、icon、maintainers、sources是加上去的属性(非必填),自动生成的脚本中没有。
root@xnzysq20210118001:~# vim mychart/Chart.yaml 
apiVersion: v2  		# 当前helm api版本,不需要修改
name: mychart			# 模板名,对应目录名 [*]
description: helm nginx demo    # 介绍此chart是干嘛的,按需求修改
type: application
version: 0.1.0			# 此chart版本号 [*]
appVersion: 1.16.0		# 此处为你应用程序的版本号 [*]
keywords:			# 关键字列表,可以有0到多个 [*]
  - Nginx
  - http
  - web
  - www
home: http://www.nginx.org  	# 应用程序官网 [*]
icon: http://nginx.org/nginx.png # 应用程序logo地址 [*]
maintainers:			# 维护人员列表 [*]
  - name: kongzi
    email: kongzi@demo.com
sources:  			# 应用程序来源 [-]
  - https://github.com/bitnami/bitnami-docker-nginx

1.3 校验打包

可以使用 Helm lint 来粗略地检查一下制作的 Chart 有没有什么语法上的错误。如果没有问题的话,就可以使用 helm package 命令对我们的 Chart 文件夹进行打包,打包后我们可以得到一个 mychart-0.1.0.tgz 的应用包。这个便是我们完成的应用了。

  • 打包好的 chart 可以上传到 chart 仓库中。
# 检查依赖和模板配置是否正确
helm lint mychart/

# 打包
helm package mychart/

1_20220415145153

1.4 安装/发布Chart

可以使用 helm install 命令尝试安装一下刚刚做好的应用包,使用 helm listhelm ls 命令查看 release(会列出所有被发布的Chart)。

  • 可以使用 helm uninstall 命令卸载 release 。
# 安装
helm install demo mychart-0.1.0.tgz

# 列出 release(所有被发布的Chart), 还可以用 helm ls
helm list

1_20220415145700

1.5 映射宿主机端口到pod端口

kubectl get pods 命令查看一下运行 pod 的状态,通过 kubectl port-forward 命令将该 pod 的端口映射到宿主机端口上,这个时候就可以通过访问 localhost 来访问部署好的应用了。

  • kubectl port-forward 通过端口转发映射宿主机端口到指定的应用端口,从而访问集群中的应用程序(Pod).
# 查看运行 pod 的状态, 找到pod的name
kubectl get pods 		

# 把pod或者其他资源的端口映射到宿主机端口,宿主机端口在前,81是宿主机端口,80是pod容器端口
# demo-mychart-6df56fb8df-w8x6l 为 pod 的 name
# 下面的命令只能使用localhost或127.0.0.1访问
kubectl port-forward demo-mychart-6df56fb8df-w8x6l 81:80

# kubectl port-forward 设置参数--address 0.0.0.0, K8S会监听任何地址,可以使用K8S节点的IP地址去访问
kubectl port-forward --address 0.0.0.0 demo-mychart-6df56fb8df-w8x6l 81:80

解决办法:
kubectl run nginx --image nginx:latest

1_20220415151853

从上图我们可以发现,端口转发报错unable to do port forwarding: socat not found,解决办法是在 k8s 所有node节点上安装socat,安装命令:apt-get install socat

  • socat是一个多功能的网络工具,名字来由是” Socket CAT”,可以看作是netcat的N倍加强版,socat的官方网站:http://www.dest-unreach.org/socat/

1_20220415152357

安装socat完成后,再次执行 kubectl port-forward 命令。

1_20220415152901

使用命令 curl 127.0.0.1:81访问,成功了,但是从别的主机使用浏览器无法访问!!!

1_20220415152940

kubectl port-forward 设置参数 --address 0.0.0.0, K8S会监听任何地址,可以使用K8S节点的IP地址去访问

运行命令:kubectl port-forward --address 0.0.0.0 demo-mychart-6df56fb8df-w8x6l 81:80

  • 该端口仅在kubectl进程运行时转发,因此您可以杀死转发端口的kubectl进程。在大多数情况下,这只是意味着在运行port-forward命令的终端中按CTRL + C.
  • 也可以使该命令在后台运行,即在末尾加 &, 完整命令 kubectl port-forward --address 0.0.0.0 demo-mychart-6df56fb8df-w8x6l 81:80 &,如果需要结束转发,使用ps -ef|grep port-forward 命令查看进程,再使用 kill -9 进程号 杀掉进程即可。

1_20220415153853

从别的主机使用浏览器访问:

1_20220415154112

1.6 卸载release

如果不需要的release,我们可以通过 helm uninstall RELEASE_NAME 命令卸载。可以通过 helm status 命令查看release状态。

# helm list 或 helm ls 命令会列出所有release
helm ls
# 查看名称为demo的release状态
helm status demo
# 卸载名称为demo的release
helm uninstall demo
#  查看名称为demo的release状态
helm status demo

1_20220415183158

2、编写Helm Chart模板

所有模板文件都存储在 chart 的 templates/ 文件夹中。当 Helm 渲染 charts 时,会通过模板引擎将所有文件发送到 templates/ 目录中,然后渲染模板并发送给Kubernetes。模板的值有两种提供方法:

  • chart 开发人员可能会在 chart 内部提供一个 values.yaml 文件。该文件可以包含默认值。
  • chart 用户可能会提供一个包含值的 YAML 文件。这可以通过命令行提供 helm install -f。

上例中的模板templates是自动生成的示例,看一下 mychart/templates/ 目录,发现如下几个文件:

  • NOTES.txt:chart 的 “帮助文件”。这会在用户运行 helm install 时显示给用户。
  • deployment.yaml:创建Kubernetes 工作负载的基本清单。
  • service.yaml:为你的工作负载创建一个service终端基本清单。
  • _helpers.tpl:放置可以通过chart复用的模板辅助对象(模板助手),所有模板都可以再这里定义,然后再任何yaml文件当中都可以调用这个文件下的模板。

为了方便我们从头开始学习,现在要做的就是… 全部删除它们!我们开始时会创建自己的 NOTES.txt 和_helpers.tpl。

  • 在编写生产级 chart 时,使用这些 chart 的基本版本可能非常有用。所以在你的日常 chart 制作中,可以不删除它们。
rm -rf mychart/templates/*

2.1 写一个chart模板

我们要创建的第一个模板将是一个 ConfigMap配置集。在 Kubernetes 中,ConfigMap 只是存储配置数据的地方。其他的东西,比如 Pod,可以访问 ConfigMap 中的数据。

由于 ConfigMaps 很简单,所以让我们入门简单很多。

1)创建一个名为 mychart/templates/configmap.yaml的文件

  • 提示: 模板名称不遵循严格的命名模式。但是建议: .yaml 为 YAML 文件后缀,.tpl 为模板助手后缀。
# 创建编辑文件
vim mychart/templates/configmap.yaml

# 查看文件内容
cat mychart/templates/configmap.yaml

configmap.yaml文件内容如下:

apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

1_20220416120852

  • 上面的 YAML 文件是一个简单的 ConfigMap,具有最少的必要字段。由于该文件位于 mychart/templates/ 目录中,因此将通过模板引擎发送。
  • 像这样将一个普通YAML文件放在mychart/templates/目录中是没问题的。当Helm读取这个模板时会按照原样传递给Kubernetes。

2)安装 chart

有了这个简单的模板,我们就有了一个可安装的 chart,chart安装好后,我们称其为一个release:

# release名称为hello
root@xnzysq20210118001:~# helm install hello mychart

# 以下为命令执行后终端的输出
NAME: hello
LAST DEPLOYED: Sat Apr 16 12:12:19 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

在上面的输出中,可以看到我们的 ConfigMap 已经创建。 注意hello这个名字是我们指定的,如果想要随机生成 name 需要用参数 --generate-name

3)查看release

使用 helm ls 命令查看release信息,可以看到 release namehello

root@xnzysq20210118001:~# helm ls
NAME 	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART        	APP VERSION
hello	default  	1       	2022-04-16 16:17:51.061166221 +0800 CST	deployed	mychart-0.1.0	1.16.0 

4)查看template

使用 helm get manifest hello 检索版本并查看 helm chart 实际加载的模板(hello为release的名称)。

root@xnzysq20210118001:~# helm get manifest hello
# 以下是输入指令后终端返回的结果
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

helm get manifest + release 名称(hello) 命令打印出了所有已经上传到服务器的Kubernetes 资源。

  • 每个文件以—开头,表示YAML文件的开头,然后是自动生成的注释行,表示哪个模板文件生成了这个YAML文档。
  • 从apiVerison那行开始,我们看到的YAML数据确实是configmap.yaml文件中的内容。

5)卸载release

现在卸载release: helm uninstall hello,命令中的hello为release的名称。

2.2 通过模板命令调用变量

通过上面的理解后,我们开始进一步定义一些变量,然后给变量赋值。

1)修改 configmap.yaml 文件

看一下下面的yaml文件。

apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

这个文件硬编码 name字段值为 mychart-configmap,这里的硬编码肯定是不好的做法。名称应该是唯一的一个版本。所以我们希望通过插入 release 名称来生成一个名称字段。

  • 提示: 由于 DNS 系统的限制,该name字段长度限制为 63 个字符。因此,release 名称限制为 53 个字符。Kubernetes 1.3 及更早版本仅限于 24 个字符(名称长度 14 个字符名称)。

让我们改一下 configmap.yaml。

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"

name值发生了变化 ,改成了 {{ .Release.Name }}-configmap

  • 模板命令要括在 {{ 和 }} 之间。
  • 模板命令 {{ .Release.Name }} 是将 release 名称注入模板。传递给模板的值可以认为是 namespace 对象,其中 dot(.)分隔每个 namespace 元素。
  • Release 前面的前一个小圆点表示作用域最顶层的命名空间开始。这样 .Release.Name"从顶层命名空间开始,找到 Release 对象,然后在里面查找名为 Name 的对象"。
  • 该 Release 对象是 Helm 的内置对象之一。但就目前而言,这足以说明这会显示 Tiller 分配给我们发布的 release 名称。

2)安装 chart

现在,当我们安装我们的资源时,我们会立即看到使用这个模板指令的结果:

root@xnzysq20210118001:~# helm install hello mychart
NAME: hello
LAST DEPLOYED: Sat Apr 16 16:34:41 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None

3)查看template

使用 helm get manifest hello 检索版本并查看生成的完整的YAML(hello为release的名称)。

root@xnzysq20210118001:~# helm get manifest hello
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: hello-configmap
data:
  myvalue: "Hello World"

从终端返回的结果可以看到,kubernetes内的配置映射名称是 hello-configmap,而不是之前的 mychart-configmap

  • 由此我们已经看到了最基本的模板:YAML文件有嵌入在{{ 和 }}之间的模板命令。

2.3 helm模板测试

写好了helm怎么做测试呢?有一个快捷的技巧可以加快模板的构建速度:当你想测试模板渲染的内容但又不想安装任何实际应用时,可以使用 helm install --debug --dry-run goodly-guppy mychart。这样就不会安装应用(chart)到你的kubenetes集群中,只会渲染模板内容到控制台(用于测试)。渲染后的模板如下:

  • 也可以使用命令 helm install solid-vulture ./mychart --dry-run --debug
root@xnzysq20210118001:~# helm install --debug --dry-run goodly-guppy ./mychart
install.go:178: [debug] Original chart version: ""
install.go:195: [debug] CHART PATH: /root/mychart

NAME: goodly-guppy
LAST DEPLOYED: Sat Apr 16 16:45:31 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
affinity: {}
autoscaling:
  enabled: false
  maxReplicas: 100
  minReplicas: 1
  targetCPUUtilizationPercentage: 80
fullnameOverride: ""
image:
  pullPolicy: IfNotPresent
  repository: nginx
  tag: ""
imagePullSecrets: []
ingress:
  annotations: {}
  className: ""
  enabled: false
  hosts:
  - host: chart-example.local
    paths:
    - path: /
      pathType: ImplementationSpecific
  tls: []
nameOverride: ""
nodeSelector: {}
podAnnotations: {}
podSecurityContext: {}
replicaCount: 1
resources: {}
securityContext: {}
service:
  port: 80
  type: ClusterIP
serviceAccount:
  annotations: {}
  create: true
  name: ""
tolerations: []

HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  myvalue: "Hello World"
  • 使用 --dry-run 可以更容易地测试代码,但不能确保 Kubernetes 本身会接受生成的模板。最好不要假定你的 chart 只要 --dry-run 成功而被安装。
0

评论区