Bootstrap

Kubernetes——Helm(一)

一、介绍

Helm 是一个 Kubernetes 应用的包管理工具,用来管理 chart——预先配置好的安装包资源,有点类似于 Ubuntu 的 APT 和 CentOS 中的 YUM。2019 年 11 月 13 日,Helm 3 发布,2020 年 4 月 30 日,从 CNCF 中毕业。本文基于 Helm 3。

Helm chart 是用来封装 Kubernetes 原生应用程序的 YAML 文件,可以在你部署应用的时候自定义应用程序的一些 metadata,便与应用程序的分发。

二、安装

    1)、下载需要的版本:https://github.com/helm/helm/releases
    2)、解压:tar -zxvf helm-v3.15.2-linux-arm64.tar.gz
    3)、在解压目中找到helm程序,移动到需要的目录中
        mv linux-amd64/helm /usr/local/bin/helm

三、概念和Chart文档结构

3.1、Chart目录结构

chart是一个组织在文件目录中的集合。目录名称就是chart名称(没有版本信息)

mychart
├── Chart.yaml
├── charts                     # 该目录保存其他依赖的 chart(子 chart)
├── templates                  # chart 配置模板,用于渲染最终的 Kubernetes YAML 文件
│   ├── NOTES.txt              # 用户运行 helm install 时候的提示信息
│   ├── _helpers.tpl           # 用于创建模板时的帮助类
│   ├── deployment.yaml        # Kubernetes deployment 配置
│   ├── ingress.yaml           # Kubernetes ingress 配置
│   ├── service.yaml           # Kubernetes service 配置
│   ├── serviceaccount.yaml    # Kubernetes serviceaccount 配置
│   └── tests
│       └── test-connection.yaml
└── values.yaml                # 定义 chart 模板中的自定义配置的默认值,可以在执行 helm install 或 helm update 的时候覆盖

templates/ 目录包括了模板文件。当Helm评估chart时,会通过模板渲染引擎将所有文件发送到templates/目录中。 然后收集模板的结果并发送给Kubernetes。

value.yaml 这个文件包含了chart的 默认值 。这些值会在用户执行helm install 或 helm upgrade时被覆盖。

Chart.yaml 文件包含了该chart的描述。你可以从模板中访问它。charts/目录 可以 包含其他的chart(称之为 子chart)

3.2、创建第一个chart

使用命令helm create 创建一个chart

[root@master ~]# helm create mychart
[root@master ~]# tree mychart/
mychart/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl                 #放置可以通过chart复用的模板辅助对象
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml

删除templates文件方便后面学习测试用

 rm -rf mychart/templates/*

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

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

测试chart运行


[root@master ~]# helm install  --dry-run goodly-guppy ./mychart       
NAME: goodly-guppy
LAST DEPLOYED: Tue Jul  2 17:21:53 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"

在configmap.yaml中添加一个引用然后运行

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
[root@master ~]# helm install  --dry-run goodly-guppy ./mychart
NAME: goodly-guppy
LAST DEPLOYED: Tue Jul  2 17:23:43 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  myvalue: "Hello World"

{{ .Release.Name }} 将发布名称注入了模板,Release是一个Helm的内置对象

Release前面的点表示从作用域最顶层的命名空间开始,.Release.Name就可解读为“通顶层命名空间开始查找 Release对象,然后在其中找Name对象”。

通过上面的实验我们可以看到最基本的模板:YAML文件有嵌入在{{ 和 }}之间的模板命令

命令helm install --debug --dry-run goodly-guppy,可以测试模板渲染的内容,在不想安装任何实际应用时,可以使用这样不会安装应用(chart)到你的kubenetes集群中,只会渲染模板内容到控制台(用于测试)。

四、内置对象

4.1、Release

在上面我们用{{ .Release.Name }}在模板中插入版本名称。

Release是模板的顶层对象之一,Release对象描述了版本发布本身。它包含以下对象:

Release.Name: release名称

Release.Namespace:版本中包含的命名空间

Release.IsUpgrade:当前操作是升级或回滚的话,该值为true,否则为false

Release.IsIntall:如果当前操作是安装,该值为true,否则为false

Release.Revision:此次修订的版本号,安装时是1,每次升级或者回滚都会自动加1

Release.Service:该service用来渲染当前模板。Helm里始终是Helm

测试如下:

[root@master ~]# vim mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  name: {{ .Release.Name }}
  Namespace: {{ .Release.Namespace }}
  IsUpgrade: {{ .Release.IsUpgrade }}
  IsInstall: {{ .Release.IsInstall }}
  Revision:  {{ .Release.Revision }}
  Service:   {{ .Release.Service }}

[root@master ~]# helm install  --dry-run goodly-guppy ./mychart
NAME: goodly-guppy
LAST DEPLOYED: Tue Jul  2 17:47:50 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  name: goodly-guppy    #实例名
  Namespace: default    #安装的命名空间
  IsUpgrade: false      #此次操作不是升级或者回滚
  IsInstall: true       #此次是安装
  Revision:  1          #第一个版本
  Service:   Helm       #始终为Helm

4.2、Value对象

Values对象是从values.yaml文件和用户提供的文件传进模板的。默认为空

取值方式

name1:test1       #获取方式 .Values.name1
info:
    name2: test2   #获取方式  .Values.info.name2
[root@master mychart]# vim values.yaml 
name1: test1
info:
   name2: test2

[root@master ~]# vim mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  name1: {{ .Values.name1 }}
  name2: {{ .Values.info.name2 }}
~             

[root@master ~]# helm install  --dry-run goodly-guppy ./mychart
NAME: goodly-guppy
LAST DEPLOYED: Tue Jul  2 21:19:34 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  name1: test1
  name2: test2                      

4.3、Chart对象

Chart.yaml文件内容。 Chart.yaml里的所有数据在这里都可以可访问的。比如 {{ .Chart.Name }}-{{ .Chart.Version }}

    .Chart.Name   获取Chart的名称
    .Chart.Version  获取Chart的版本

[root@master ~]# helm install  --dry-run goodly-guppy ./mychart
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  ChartName: {{ .Chart.Name }}
  ChartVersion: {{ .Chart.Version }}

[root@master ~]# helm install  --dry-run goodly-guppy ./mychart
NAME: goodly-guppy
LAST DEPLOYED: Tue Jul  2 21:31:07 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  ChartName: mychart
  ChartVersion: 0.1.0

4.4、Files对象

File对象:在chart中提供访问所有的非特殊文件的对象。你不能使用它访问Template对象,只能访问其他文件

Files.Get通过文件名获取文件内容的方法

Files.GetBytes:用二进制字节数组代替字符串获取文件内容的方法。 对图片之类的文件很有用

Files.Glob返回符合给定shell glob pattern的文件数组,例: {{ .Files.Glob "*.yaml" }}

Files.Lines:逐行读取文件内容的方法。迭代文件中每一行时很有用

Files.AsSecrets:使用Base 64编码字符串返回文件体的方法

Files.AsConfig:使用YAML格式返回文件体的方法

[root@master ~]# vim mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  {{- $files := .Files }}
  {{- range tuple "config1.yaml" "config2.yaml" "config3.yaml" }}
  {{ . }}: |-
        {{ $files.Get . }}
  {{- end}}
[root@master ~]# helm install  --dry-run goodly-guppy ./mychart
NAME: goodly-guppy
LAST DEPLOYED: Tue Jul  2 21:46:57 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  config1.yaml: |-
        message = Hello from config1

  config2.yaml: |-
        message = This is config2

  config3.yaml: |-
        message = This is config3

我们创建了一个 $files 变量来引用 .Files 对象。 然后我们打印每个文件的名字( {{ . }}: |-),通过 {{ $files.Get . }} 打印文件内容。

4.5、Capabilities对象

提供关于Kubernetes集群支持功能的信息

Capabilities.APIVersions:返回kubernetes 集群API版本信息集合

Capabilities.APIVersions.Has $version:说明集群中的版本 (比如,batch/v1) 或是资源 (比如, apps/v1/Deployment) 是否可用

Capabilities.KubeVersion 和Capabilities.KubeVersion.Version:是Kubernetes的版本号

Capabilities.KubeVersion.Major:Kubernetes的主版本

Capabilities.KubeVersion.Minor:Kubernetes的次版本

Capabilities.HelmVersion:包含Helm版本详细信息的对象,和 helm version 的输出一致

Capabilities.HelmVersion.Version:是当前Helm语义格式的版本

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  APIVersion: {{ .Capabilities.APIVersions }}
  KubeVersion: {{ .Capabilities.KubeVersion }}
  Major: {{ .Capabilities.KubeVersion.Major }}
  Minor: {{ .Capabilities.KubeVersion.Minor }}

4.6、Template对象

包含当前被执行的当前模板信息

Template.Name: 当前模板的命名空间文件路径 (e.g. mychart/templates/mytemplate.yaml

Template.BasePath: 当前chart模板目录的路径 (e.g. mychart/templates)

[root@master ~]# vim mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  TempName: {{ .Template.Name }}
  TempBasePath: {{ .Template.BasePath }}

[root@master ~]# helm install --dry-run goodly-guppy ./mychart
NAME: goodly-guppy
LAST DEPLOYED: Wed Jul  3 14:54:57 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  TempName: mychart/templates/configmap.yaml
  TempBasePath: mychart/templates

五、Values文件

5.1、values值来源

上一部分了解了Helm模板提供的内置对象。其中一个是Values对象。该对象提供了传递值到chart的方法。

其内容来自对个位置:

  • chart中的values.yaml文件
  • 如果是子chart,就是父chart中的values.yaml文件
  • 使用-f参数(helm install -f myvals.yaml ./mychart)传递到 helm install 或 helm upgrade的values文件
  • 使用--set (比如helm install --set foo=bar ./mychart)传递的单个参数

顺序:默认使用values.yaml,可以被父chart的values.yaml覆盖,继而被用户提供values文件覆盖, 最后会被--set参数覆盖,优先级为values.yaml最低,--set参数最高。

values文件是普通的YAML文件。现在编辑mychart/values.yaml然后编辑配置映射ConfigMap模板。

[root@master ~]# vim mychart/values.yaml
name1: test1

在模板中使用它

[root@master ~]# helm install --dry-run goodly-guppy ./mychart --debug
install.go:222: [debug] Original chart version: ""
install.go:239: [debug] CHART PATH: /root/mychart

NAME: goodly-guppy
LAST DEPLOYED: Wed Jul  3 15:07:01 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
USER-SUPPLIED VALUES:
{}

COMPUTED VALUES:
name1: test1

HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  name: test1

可以在调用helm install时设置--set,很容易就能覆盖这个值。

[root@master ~]# helm install --dry-run goodly-guppy ./mychart --set name1=test2
NAME: goodly-guppy
LAST DEPLOYED: Wed Jul  3 15:08:12 2024
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: goodly-guppy-configmap
data:
  name: test2

由于--set比默认的values.yaml文件优先级更高,模板就生成了 name: test2

5.2、删除默认的key

如果需要从默认的value中删除key,可以将key设置为null,Helm将在覆盖的value合并时删除这个key。

比如,稳定的Drupal允许在配置自定义镜像时配置活动探针。默认值为httpget

livenessProbe:
  httpGet:
    path: /user/login
    port: http
  initialDelaySeconds: 120

替换掉httpGetexec重写活动探针,使用--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt]

Helm会把默认的key和重写的key合并在一起,从而生成以下YAML:

livenessProbe:
  httpGet:
    path: /user/login
    port: http
  exec:
    command:
    - cat
    - docroot/CHANGELOG.txt
  initialDelaySeconds: 120

为了解决这个问题,Helm可以指定通过设定null来删除livenessProbe.httpGet

helm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null

;