Helm快速开始
文章目录
- Helm快速开始
- 背景
- 什么是Helm
- Helm基础概念
- Chart 包托管平台
- Docker和Helm Chart区别
- 安装 Helm
- helm使用
- 'helm search':查找 Charts
- 'helm install':安装一个 helm 包
- helm upgrade 怎么知道要操作那个k8s?
- 安装前自定义 chart
- 'helm uninstall':卸载 release
- 'helm repo':使用仓库
- 创建你自己的 charts
- values.yaml
- Chart.yaml 和 values.yaml
- Chart
- `templates/`目录
- Chart Types
- 父子chart
- 使用'tpl'方法
- **`values.yaml`**
- **模板文件**
- **渲染过程**
- **最终结果**
- 结合 `with` 语句、`tpl` 函数和 `nindent` 函数
- **`values.yaml`**
- **模板文件**
- **最终结果**
- **什么是“当前上下文(`.`)”?**
- **什么是“全局上下文(`$`)”?**
- **为什么需要“全局上下文(`$`)”?**
- **`values.yaml`**
- **模板文件**
- **渲染过程**
Helm快速开始
背景
传统的K8s部署方式,随着引用增多,需要维护大量的yaml文件,并且不能根据一套yaml文件来创建多个环境,需要手动修改。
那么对于一个大型的应用,如果基于 YAML 文件一个一个地部署 Kubernetes 资源,是非常繁琐、低效的,而且这些 YAML 文件维护起来极其复杂,还容易出错。那么,有没有一种更加高效的方式?
Helm 可以帮我们解决上面这些问题,用来来维护和管理这些 YAML 文件和 Kubernetes 中部署的应用。
什么是Helm
官网:https://helm.sh/
Helm 是 Kubernetes 的包管理器,类似于 Python 的 pip ,centos 的 yum 。Helm 主要用来管理 Chart 包。Helm Chart 包中包含一系列 YAML 格式的 Kubernetes 资源定义文件,以及这些资源的配置,可以通过 Helm Chart 包来整体维护这些资源。
Helm 最新的版本是 v3,Helm3 以 Helm2 的核心功能为基础,对 Chart repo、发行版管理、安全性和 library Charts 进行了改进。和 Helm2 比起来,Helm3 最明显的变化是删除了 Tiller(Helm2 是一种 Client-Server 结构,客户端称为 Helm,服务器称为 Tiller)。 Helm3 还新增了一些功能,并废弃或重构了 Helm2 的部分功能,与 Helm2 不再兼容。此外,Helm3 还引入了一些新的实验功能,包括 OCI 支持。
Helm 可以类比于 Linux 系统中的 apt 或 yum,它可以搜索、安装、升级和卸载软件包。Helm 的软件包称为 Chart。
Helm是一款强大而灵活的 Kubernetes 软件包管理和运维工具,类似于apt、yum等包管理工具。运用Helm可以极大的简化Kubernetes应用部署。
Helm基础概念
作为Kubernetes的包管理工具,有三个概念:Chart、Repository、Release。
-
Chart: 一个helm程序包;就是 Helm 的一个包(package),包含一个应用所有的 Kubernetes manifest 模版,类似于 YUM 的 RPM 或者 APT 的 dpkg 文件。
-
Helm CLI: Helm 的客户端组件,负责和 Kubernetes API 通信
-
Repository:Charts仓库,https/http服务器。用于发布和存储 Chart 的仓库。
-
Release: Release 是运行在 Kubernetes 集群中的 chart 的实例。通过 Chart 在 Kubernetes 中部署的应用都会产生一个唯一的 Release,即使是同一个 Chart,部署多次就会产生多个 Release。
以 MySQL chart为例,如果你想在你的集群中运行两个数据库,你可以安装该chart两次。每一个数据库都会拥有它自己的 release 和 release name。
Chart 代表着 Helm 包。
Repository(仓库) 是用来存放和共享 charts 的地方。
Release 是 Helm 管理的 Chart 实例,代表在 Kubernetes 中运行的一个应用。更新特定的 Release 可以使用 helm upgrade 命令,只需指定要更新的 Release 名称和相关 Chart 路径。通过这种方式,您可以在 Kubernetes 环境中灵活地管理多个 Release,而不影响其他 Release 的状态。
子 Chart 作为独立的 Release 安装,您确实可以对各个服务进行独立控制和管理。这种方式非常适合微服务架构
在了解了上述这些概念以后,我们就可以这样来解释 Helm:
Helm 安装 charts 到 Kubernetes 集群中,每次安装都会创建一个新的 release。你可以在 Helm 的 chart repositories 中寻找新的 chart。
Chart 包托管平台
Chart 包有一个托管平台,当前比较流行的 Chart 包托管平台是Artifact Hub。
Docker和Helm Chart区别
Docker是一种容器化技术,用于打包和运行应用程序及其依赖项,而Helm Chart则是一种管理Kubernetes应用程序的工具,用于打包和部署应用程序及其依赖项。
序列图展示了Docker和Helm Chart在应用程序开发和部署中的使用流程。
安装 Helm
官方文档:https://helm.sh/zh/docs/intro/install/
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh
helm使用
- 使用Helm,需要一个Kubernetes集群。对于Helm的最新版本,我们建议使用Kubernetes的最新稳定版, 在大多数情况下,它是倒数第二个次版本。
- 您也应该有一个本地的 kubectl.
不推荐将Helm用于比编译它所依赖的版本更高的Kubernetes版本,因为Helm并没有做出任何向前兼容的保证。
请参考下表来确定哪个版本的Helm与您的集群兼容:https://helm.sh/zh/docs/topics/version_skew/
‘helm search’:查找 Charts
Helm 自带一个强大的搜索命令,可以用来从两种来源中进行搜索:
helm search hub
从 Artifact Hub 中查找并列出 helm charts。 Artifact Hub中存放了大量不同的仓库。
helm search repo
从你添加(使用 helm repo add)到本地 helm 客户端中的仓库中进行查找。该命令基于本地数据进行搜索,无需连接互联网。
‘helm install’:安装一个 helm 包
使用 helm install 命令来安装一个新的 helm 包。最简单的使用方法只需要传入两个参数:你命名的release名字和你想安装的chart的名称。
$ helm install happy-panda bitnami/wordpress
现在wordpress chart 已经安装。注意安装chart时创建了一个新的 release 对象。上述发布被命名为 happy-panda。 (如果想让Helm生成一个名称,删除发布名称并使用–generate-name。)
Helm 客户端不会等到所有资源都运行才退出。许多 charts 需要大小超过 600M 的 Docker 镜像,可能需要很长时间才能安装到集群中。
你可以使用 helm status 来追踪 release 的状态,或是重新读取配置信息
$ helm status happy-panda
helm upgrade 怎么知道要操作那个k8s?
在使用 helm upgrade
时,Helm 需要知道要操作哪个 Kubernetes 集群。Helm 通过 Kubernetes 配置文件(kubeconfig) 来确定目标集群。
Kubernetes 配置文件(kubeconfig)
Kubernetes 使用 kubeconfig 文件来管理集群的访问信息,包括:
集群的 API 地址。
用户认证信息(如证书、令牌等)。
上下文(context),用于指定当前使用的集群和命名空间。
默认情况下,kubeconfig 文件位于 ~/.kube/config
。
指定 kubeconfig 文件
如果你的 kubeconfig 文件不在默认位置,或者你需要使用不同的 kubeconfig 文件,可以通过 --kubeconfig 参数指定文件路径。例如:
helm upgrade my-release ./my-chart --kubeconfig=/path/to/my-kubeconfig
安装前自定义 chart
上述安装方式只会使用 chart 的默认配置选项。很多时候,我们需要自定义 chart 来指定我们想要的配置。
使用 helm show values 可以查看 chart 中的可配置选项:
$ helm show values bitnami/wordpress
## Global Docker image parameters
## Please, note that this will override the image parameters, including dependencies, configured to use the global value
## Current available global Docker image parameters: imageRegistry and imagePullSecrets
##
# global:
# imageRegistry: myRegistryName
# imagePullSecrets:
# - myRegistryKeySecretName
# storageClass: myStorageClass
## Bitnami WordPress image version
## ref: https://hub.docker.com/r/bitnami/wordpress/tags/
##
image:
registry: docker.io
repository: bitnami/wordpress
tag: 5.6.0-debian-10-r35
[..]
然后,你可以使用 YAML 格式的文件覆盖上述任意配置项,并在安装过程中使用该文件。
$ echo '{mariadb.auth.database: user0db, mariadb.auth.username: user0}' > values.yaml
$ helm install -f values.yaml bitnami/wordpress --generate-name
上述命令将为 MariaDB 创建一个名称为 user0 的默认用户,并且授予该用户访问新建的 user0db 数据库的权限。chart 中的其他默认配置保持不变。
安装过程中有两种方式传递配置数据:
–values (或 -f):使用 YAML 文件覆盖配置。可以指定多次,优先使用最右边的文件。
–set:通过命令行的方式对指定项进行覆盖。
‘helm uninstall’:卸载 release
使用 helm uninstall 命令从集群中卸载一个 release:
$ helm uninstall happy-panda
该命令将从集群中移除指定 release。你可以通过 helm list 命令看到当前部署的所有 release。
‘helm repo’:使用仓库
Helm 3 不再附带一个默认的 chart 仓库。helm repo 提供了一组命令用于添加、列出和移除仓库。
使用 helm repo list
来查看配置的仓库:
$ helm repo list
NAME URL
stable https://charts.helm.sh/stable
mumoshu https://mumoshu.github.io/charts
使用 helm repo add 来添加新的仓库:
$ helm repo add dev https://example.com/dev-charts
因为 chart 仓库经常在变化,在任何时候你都可以通过执行 helm repo update 命令来确保你的 Helm 客户端是最新的。
使用 helm repo remove 命令来移除仓库。
创建你自己的 charts
chart 开发指南 介绍了如何开发你自己的chart。 但是你也可以通过使用 helm create
命令来快速开始:
$ helm create deis-workflow
Creating deis-workflow
现在,./deis-workflow
目录下已经有一个 chart 了。你可以编辑它并创建你自己的模版。
在编辑 chart 时,可以通过 helm lint 验证格式是否正确。
当准备将 chart 打包分发时,你可以运行 helm package 命令:
$ helm package deis-workflow
deis-workflow-0.1.0.tgz
然后这个 chart 就可以很轻松的通过 helm install 命令安装:
$ helm install deis-workflow ./deis-workflow-0.1.0.tgz
打包好的 chart 可以上传到 chart 仓库中。
values.yaml
values.yaml 是 Kubernetes Helm Chart 使用的配置文件之一。
自定义配置
在安装或升级 Helm Chart 时,用户可以通过命令行或指定其他 YAML 文件来覆盖 values.yaml 中的默认值。例如:
helm install my-release my-chart -f custom-values.yaml
这将使用 custom-values.yaml 中的配置覆盖默认的 values.yaml。
Chart.yaml 和 values.yaml
Chart.yaml 用于描述 Chart 的基本信息和依赖关系,而 values.yaml 用于提供可定制的配置信息,使得用户能够调整 Chart 的行为。
Chart
官方文档:https://helm.sh/zh/docs/topics/charts/
Helm使用的包格式称为 chart。如果你想下载和查看一个发布的chart,但不安装它,你可以用这个命令: helm pull chartrepo/chartname。
Chart 文件结构
描述WordPress的chart可以存储在wordpress/目录中。
wordpress/
Chart.yaml # 包含了chart信息的YAML文件
LICENSE # 可选: 包含chart许可证的纯文本文件
README.md # 可选: 可读的README文件
values.yaml # chart 默认的配置值
values.schema.json # 可选: 一个使用JSON结构的values.yaml文件
charts/ # 包含chart依赖的其他chart
crds/ # 自定义资源的定义
templates/ # 模板目录, 当和values 结合时,可生成有效的Kubernetes manifest文件
templates/NOTES.txt # 可选: 包含简要使用说明的纯文本文件
Helm保留使用 charts/
,crds/
, templates/
目录,以及列举出的文件名。其他文件保持原样。
- templates/ 目录包括了模板文件。当Helm评估chart时,会通过模板渲染引擎将所有文件发送到templates/目录中。 然后收集模板的结果并发送给Kubernetes。
- values.yaml 文件也导入到了模板。这个文件包含了chart的 默认值 。这些值会在用户执行
helm install
或helm upgrade
时被覆盖。 - Chart.yaml 文件包含了该chart的描述。你可以从模板中访问它。charts/目录 可以 包含其他的chart(称之为 子chart)。
templates/
目录
NOTES.txt: chart的"帮助文本"。这会在你的用户执行helm install时展示给他们。
apiVersion 字段
对于至少需要Helm 3的chart,apiVersion 字段应该是 v2。Chart支持之前apiVersion 设置为 v1 的Helm 版本, 并且在Helm 3中仍然可安装。
v1 到 v2的改变:
dependencies字段定义了chart的依赖,针对于v1 版本的chart被放置在分隔开的requirements.yaml 文件中 (查看 Chart 依赖).
type字段, 用于识别应用和库类型的chart(查看 Chart 类型).
Chart Types
type字段定义了chart的类型。有两种类型: application 和 library。
application 表示这是一个用于部署应用程序的 Chart,另一种类型是 library,用于提供共享功能或模板的库。
父子chart
在 Helm 中,父 Chart 是一个整体,它会将所有子 Chart 的内容打包为一个 Release。在这种情况下,如果您已经将父 Chart 发布为一个 Release,您不能直接只更新这个 Release 下的某个子 Chart 而不影响其他子 Chart。
在 Helm 中,当您对父 Chart 进行发布后,您无法单独更新该 Release 下的某个子 Chart;更新必须通过重新发布父 Chart 来完成。如果您希望独立更新子 Chart,可以考虑将它们解耦为独立的 Release,或通过遵循版本控制对父 Chart 进行维护。
在 Helm/Chart 的部署模型中,所有子 Chart(Subchart)会作为依赖被打包进同一个父 Chart 中,最终在执行 helm install/upgrade 操作时,父 Chart 与所有子 Chart 会一起渲染并更新到集群。
如果仅仅想更新子 Chart 对应的某个服务(或其他资源模板),但又不动其他子 Chart,对应的常见做法有以下几种思路:
-
将子 Chart 拆分为独立的 Release
• 最“干净”的方案是把需要独立运维的子 Chart 单独发布为一个独立 Chart(或者仍旧是子 Chart,但使用单独的 Release Name),这样就可以针对这部分服务单独执行 helm upgrade。
• 这种拆分方式能够最大程度减少对其他不需要更新服务的影响,因为不同 Release 之间可以完全独立进行升级、回滚,也可分开指定 values。
• 需要注意拆分后的命名冲突、依赖管理,以及公共配置如何共享(可通过一些共享 ConfigMap、Runtime Config 等模式实现)。 -
保持同一个 Release,但只修改对应子 Chart 的 values
• 如果不想拆分 Release,也可以在现有父 Chart 的 values.yaml(或者通过 --set、-f 方式)里只调整特定子 Chart 的 values(如镜像版本、tag 或者其他关键配置),然后 helm upgrade 整个父 Chart。
• 理论上,这样做可以让仅有的差异仅体现在对应子 Chart 的部分资源上,从而只影响某个服务。但实际上,Helm 在执行渲染和对比时,会对所有资源进行 diff,一旦父 Chart 或其他子 Chart 的模板、依赖版本也发生任何改动(包括默认值、依赖库版本等),仍然有可能导致其他子 Chart 资源或公共资源被动更新。
• 因此,这种方法无法完全“保证”其他子 Chart 100% 不会变动,只能说在所有其他配置、模板都不变的前提下,理论上只会更新需要更新的子 Chart 资源。 -
只替换服务镜像或指定容器标签(若仅限镜像替换)
• 如果你更新的目标单纯只是服务镜像(如镜像 tag),较常见的方法是直接通过修改容器镜像标签或拉取策略来实现“热更新”,这一类操作有时可以利用 Kubernetes 的滚动更新机制来最小化影响。
• 这种做法通常还是会调用 helm upgrade 并带上对应 .Values 子 Chart 配置,比如:
helm upgrade <release-name> .
--reuse-values
--set subchartA.image.tag=<new-tag>
• 只要其他子 Chart 相关配置和模板没有发生改变(包括 Chart 本身版本也保持不变),就能尽可能地减少对别的子 Chart 的影响。
使用 使用 --reuse-values保留当前 Release 的配置值,仅应用你明确指定的修改。
–reuse-values 是关键。它的作用是保留当前 Helm Release 的配置值,而不是使用新的 values.yaml 文件中的默认值。这意味着:
无论你的 values.yaml 文件内容是什么,–reuse-values 都会忽略它,保留当前 Release 的配置。
在父 Chart 的 Chart.yaml 文件中,子 Chart 的依赖关系也会通过 dependencies 字段定义,其中每个子 Chart 会有一个 name 字段,这个 name 通常与 values.yaml 中的键名一致。
helm upgrade 会更新 Kubernetes 中的 Pod,但具体是否更新 Pod 取决于你的修改内容。
修改镜像配置:如果你修改了子 Chart 的镜像(如 image.repository 或 image.tag),Helm 会触发 Deployment 的更新。Kubernetes 会重新创建 Pod,以使用新的镜像。
通过 helm upgrade 修改子 Chart 的镜像配置是一种常见的操作方式,尤其适合在开发和测试环境中快速验证镜像的修改。
优点:
快速生效:修改后,Kubernetes 会立即重新部署 Pod。
灵活性:可以只修改子 Chart 的配置,而不影响父 Chart 和其他子 Chart。
使用’tpl’方法
使用 tpl
函数渲染模板字符串。tpl
方法允许开发者在模板中使用字符串作为模板。将模板字符串作为值传给chart或渲染额外的配置文件时会很有用。
{{ tpl "模板字符串" . }}
模板字符串
:包含模板语法的字符串。.
:当前上下文,用于提供模板语法中需要的变量(如.Values
、.Release
等)。
tpl
函数会将模板字符串中的 {{ }}
语法解析为实际的值。
假设 values.yaml
中有以下内容:
values.yaml
config: |
server:
port: {{ .Values.port }}
host: {{ .Values.host }}
port: 8080
host: "localhost"
模板文件
config: {{- tpl .Values.config $ | nindent 8 }}
渲染过程
-
tpl .Values.config $
:-
tpl
函数会渲染.Values.config
这个字符串。 -
.Values.config
的内容是:
server: port: {{ .Values.port }} host: {{ .Values.host }}
-
tpl
会将{{ .Values.port }}
替换为8080
,将{{ .Values.host }}
替换为"localhost"
。 -
渲染后的结果是:
server: port: 8080 host: localhost
-
-
| nindent 8
:- 对渲染后的字符串进行格式化,在每一行前添加 8 个空格的缩进,并在第一行前添加一个换行符。
-
{{- ... }}
:- 去除渲染结果左侧的空白字符。
最终结果
config:
server:
port: 8080
host: localhost
结合 with
语句、tpl
函数和 nindent
函数
假设 values.yaml
中有以下内容:
values.yaml
extraEnv: |
- name: DB_HOST
value: {{ .Values.db.host }}
- name: DB_PORT
value: {{ .Values.db.port }}
db:
host: "localhost"
port: 3306
模板文件
env:
{{- with .Values.extraEnv }}
{{- tpl . $ | nindent 12 }}
{{- end }}
-
with .Values.extraEnv
:- 检查
.Values.extraEnv
是否存在且非空。 - 如果存在,将
.Values.extraEnv
作为新的上下文(.
)。
- 检查
-
tpl . $
:
-
渲染
.Values.extraEnv
中的模板语法。 -
将
{{ .Values.db.host }}
替换为"localhost"
,将{{ .Values.db.port }}
替换为3306
。 -
渲染后的结果是:
- name: DB_HOST value: localhost - name: DB_PORT value: 3306
| nindent 12
:
- 对渲染后的字符串进行格式化,在每一行前添加 12 个空格的缩进,并在第一行前添加一个换行符。
{{- end }}
:
- 结束
with
块。
最终结果
env:
- name: DB_HOST
value: localhost
- name: DB_PORT
value: 3306
- 检查
.Values.extraEnv
是否存在且非空。 - 如果存在,将
.Values.extraEnv
作为模板字符串渲染,并使用全局上下文($
)作为数据源。 - 对渲染后的字符串进行格式化:
- 在每一行前添加 12 个空格的缩进。
- 在第一行前添加一个换行符。
- 去除渲染结果左侧的空白字符。
什么是“当前上下文(.
)”?
在 Helm 模板中,.
表示当前上下文,它是一个对象,包含了当前模板中可以访问的所有变量和数据。例如:
.Values
:values.yaml
文件中定义的值。.Release
:当前发布(Release)的信息,如名称、命名空间等。.Chart
:当前 Chart 的元数据,如名称、版本等。
当你使用 .
时,实际上是在引用这个上下文对象。
什么是“全局上下文($
)”?
在 Helm 模板中,$
是一个特殊的变量,表示全局上下文。它指向最外层的上下文对象,包含了当前模板中可以访问的所有变量和数据。例如:
.Values
:values.yaml
文件中定义的值。.Release
:当前发布(Release)的信息,如名称、命名空间等。.Chart
:当前 Chart 的元数据,如名称、版本等。
无论你在模板的哪个层级(例如在 range
或 with
块中),$
始终指向最外层的上下文。
为什么需要“全局上下文($
)”?
在某些情况下,模板的当前上下文(.
)可能会被覆盖或改变。例如:
- 在
range
循环中,当前上下文(.
)会指向循环中的每个元素。 - 在
with
块中,当前上下文(.
)会指向with
指定的对象。
如果你在这些情况下仍然需要访问全局的变量(如 .Values
或 .Release
),就需要使用 $
来显式地引用全局上下文。
假设 values.yaml
中有以下内容:
values.yaml
extraEnv: |
- name: DB_HOST
value: {{ .Values.db.host }}
- name: DB_PORT
value: {{ .Values.db.port }}
db:
host: "localhost"
port: 3306
模板文件
env:
{{- with .Values.extraEnv }}
{{- tpl . $ | nindent 12 }}
{{- end }}
渲染过程
-
with .Values.extraEnv
:- 进入
with
块,当前上下文(.
)变为.Values.extraEnv
。
- 进入
-
tpl . $
:-
tpl
函数会渲染.Values.extraEnv
这个字符串。.Values.extraEnv的内容是:
- name: DB_HOST value: {{ .Values.db.host }} - name: DB_PORT value: {{ .Values.db.port }}
-
由于当前上下文(
.
)是.Values.extraEnv
,直接使用.
无法访问.Values.db.host
和.Values.db.port
。 -
因此,使用
$
作为数据源,tpl
函数会从全局上下文($
)中解析{{ .Values.db.host }}
和{{ .Values.db.port }}
。 -
渲染后的结果是:
- name: DB_HOST value: localhost - name: DB_PORT value: 3306
-
-
| nindent 12
:
- 对渲染后的字符串进行格式化,在每一行前添加 12 个空格的缩进,并在第一行前添加一个换行符。
{{- end }}
:
- 结束
with
块。
- 使用全局上下文(
$
)作为数据源适用场景:当前上下文(.
)被覆盖时,仍然需要访问全局变量(如.Values
、.Release
等)。