1. 概述
Helm 是 Kubernetes 应用的包管理工具。在本教程中,我们将了解 Helm 的基础知识,以及它如何成为操作 Kubernetes 资源的强大工具。
近年来,Kubernetes 的使用迅速增长,其生态系统也随之扩展。Helm 也得到了 CNCF(Cloud Native Computing Foundation)的认可并进入毕业项目,这表明它在 Kubernetes 用户中的受欢迎程度持续上升。
2. 背景知识
尽管这些术语如今已经相当常见,尤其是对从事云技术开发的人来说,但为了帮助尚未熟悉的朋友理解,我们还是快速回顾一下:
- **容器 (Container)**:指的是操作系统级别的虚拟化。多个容器运行在同一个操作系统中,但彼此隔离。容器内的程序只能访问分配给它的资源。
- **Docker**:是一个流行的创建和运行容器的工具。它包含 Docker Daemon(负责管理容器)和 Docker CLI(通过 Docker Engine API 与 Daemon 交互)。这篇文章详细介绍了 Docker 的使用。
- **Kubernetes**:是一个流行的容器编排工具。虽然它支持多种容器运行时,但最常用的是 Docker。它提供部署自动化、弹性伸缩和跨主机集群操作等功能。这篇文章详细介绍了 Kubernetes 的使用。
3. Helm 架构演进
Helm 3 对其架构进行了重大改进,相较于 Helm 2 有很多期待已久的改动。除了新增功能外,内部机制也发生了变化,我们来看看这些变化。
Helm 2 架构
Helm 2 采用的是客户端-服务器架构:
- Tiller Server:Helm 通过在 Kubernetes 集群中安装 Tiller Server 来管理应用。Tiller 与 Kubernetes API Server 交互,用于安装、升级、查询和删除资源。
- Helm Client:Helm 提供命令行接口供用户操作,负责与 Tiller Server 通信执行安装、升级、回滚等操作。
Helm 3 架构
Helm 3 采用纯客户端架构,移除了 Tiller Server:
客户端直接与 Kubernetes API Server 通信。这一改动简化了架构,也更安全地利用了 Kubernetes 的权限机制。
4. Helm Chart、Release 与 Repository
Helm 通过 Chart 来管理 Kubernetes 资源包。Chart 是 Helm 的打包格式。
Chart
- Chart 是一组按特定目录结构组织的文件
- Chart 的配置信息保存在
values.yaml
中 - 一个 Chart 的运行实例称为 Release
Library Chart
Helm 3 引入了 Library Chart 的概念,用于定义通用模板片段,可以在多个 Chart 中复用。
Release 存储方式
在 Helm 2 中,Release 信息以 ConfigMap 或 Secret 的形式保存在 Tiller 所在的命名空间中。Helm 3 则默认将 Release 信息以 Secret 的形式保存在对应命名空间中。
Repository
Chart 可以以压缩包形式共享,存储在 Chart 仓库中。最知名的社区仓库是 Artifact Hub,你也可以搭建私有仓库。
5. 前置条件
在开发第一个 Helm Chart 之前,你需要准备以下环境:
- Kubernetes 集群:本教程使用 Minikube 搭建本地单节点集群
- kubectl:Kubernetes 命令行工具,用于与集群交互
- Docker 应用:我们使用一个简单的 Spring Boot 应用作为示例,已打包为 Docker 镜像
6. 安装 Helm
Helm 提供了多种安装方式,详见其官方安装页面。
Windows 上安装 Helm
推荐使用 Chocolaty:
choco install kubernetes-helm
确保 Kubernetes 集群已启动:
kubectl cluster-info
⚠️ Helm 3 不再需要初始化(helm init
),该命令已被移除。
7. 开发第一个 Chart
7.1 创建 Chart
使用 Helm CLI 创建一个名为 hello-world
的 Chart:
helm create hello-world
生成的目录结构如下:
hello-world/
Chart.yaml
values.yaml
templates/
charts/
.helmignore
Chart.yaml
:Chart 的元信息values.yaml
:模板默认值templates/
:Kubernetes 资源模板charts/
:子 Chart(可选).helmignore
:打包时忽略的文件规则
7.2 编写模板
编辑 templates/deployment.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "hello-world.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "hello-world.name" . }}
helm.sh/chart: {{ include "hello-world.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "hello-world.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
template:
metadata:
labels:
app.kubernetes.io/name: {{ include "hello-world.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 8080
protocol: TCP
编辑 templates/service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: {{ include "hello-world.fullname" . }}
labels:
app.kubernetes.io/name: {{ include "hello-world.name" . }}
helm.sh/chart: {{ include "hello-world.chart" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: {{ include "hello-world.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
这些模板使用了 Helm 的模板语言(基于 Go 模板语法),通过 {{}}
插入变量。
7.3 提供值
编辑 values.yaml
文件:
replicaCount: 1
image:
repository: "hello-world"
tag: "1.0"
pullPolicy: IfNotPresent
service:
type: NodePort
port: 80
这些值将通过 .Values
对象注入模板。
8. 管理 Chart
8.1 Helm Lint
验证 Chart 是否格式正确:
helm lint ./hello-world
==> Linting ./hello-world
1 chart(s) linted, no failures
8.2 Helm Template
本地渲染模板:
helm template ./hello-world
输出渲染后的 Kubernetes 资源清单,便于调试。
8.3 Helm Install
安装 Chart:
helm install --name hello-world ./hello-world
⚠️ Helm 3 默认不再自动生成 Release 名称,需使用 --generate-name
或手动指定。
8.4 Helm Get
查看已安装的 Release:
helm ls --all
8.5 Helm Upgrade
升级 Release:
helm upgrade hello-world ./hello-world
Helm 3 使用三向合并策略(old manifest + live state + new manifest),更安全地处理集群外的变更。
8.6 Helm Rollback
回滚 Release:
helm rollback hello-world 1
8.7 Helm Uninstall
卸载 Release:
helm uninstall hello-world
9. 分发 Chart
9.1 Helm Package
打包 Chart:
helm package ./hello-world
输出文件为 hello-world-0.1.0.tgz
,可用于发布或共享。
9.2 Helm Repo
创建 Chart 仓库:
helm repo index my-repo/ --url https://example.com/my-repo
添加远程仓库:
helm repo add my-repo https://example.com/my-repo
安装远程 Chart:
helm install my-repo/hello-world --name=hello-world
9.3 Helm Search
搜索 Chart:
helm search repo <KEYWORD>
支持在本地仓库或 Artifact Hub 中搜索。
10. 从 Helm 2 迁移到 Helm 3
Helm 3 与 Helm 2 有以下主要区别:
✅ Helm 3 移除了 Tiller,更安全
✅ 默认不再自动创建命名空间
✅ Release 信息以 Secret 形式存储
✅ 使用三向合并策略进行升级
迁移建议:
- 新项目直接使用 Helm 3
- 旧项目可使用 helm-2to3 插件 进行迁移
11. 总结
在本教程中,我们学习了 Helm 的核心概念、安装方法、Chart 的创建与管理、模板语法、以及如何分发 Chart。我们还对比了 Helm 2 与 Helm 3 的主要区别。
Helm 作为 Kubernetes 的包管理工具,极大地简化了应用的部署与维护,是现代云原生开发中不可或缺的一环。熟练掌握 Helm,可以显著提升你在 Kubernetes 上部署应用的效率与灵活性。