1. 概述

Helm 是 Kubernetes 应用的包管理工具。在本教程中,我们将了解 Helm 的基础知识,以及它如何成为操作 Kubernetes 资源的强大工具。

近年来,Kubernetes 的使用迅速增长,其生态系统也随之扩展。Helm 也得到了 CNCF(Cloud Native Computing Foundation)的认可并进入毕业项目,这表明它在 Kubernetes 用户中的受欢迎程度持续上升。

2. 背景知识

尽管这些术语如今已经相当常见,尤其是对从事云技术开发的人来说,但为了帮助尚未熟悉的朋友理解,我们还是快速回顾一下:

  1. **容器 (Container)**:指的是操作系统级别的虚拟化。多个容器运行在同一个操作系统中,但彼此隔离。容器内的程序只能访问分配给它的资源。
  2. **Docker**:是一个流行的创建和运行容器的工具。它包含 Docker Daemon(负责管理容器)和 Docker CLI(通过 Docker Engine API 与 Daemon 交互)。这篇文章详细介绍了 Docker 的使用
  3. **Kubernetes**:是一个流行的容器编排工具。虽然它支持多种容器运行时,但最常用的是 Docker。它提供部署自动化、弹性伸缩和跨主机集群操作等功能。这篇文章详细介绍了 Kubernetes 的使用

3. Helm 架构演进

Helm 3 对其架构进行了重大改进,相较于 Helm 2 有很多期待已久的改动。除了新增功能外,内部机制也发生了变化,我们来看看这些变化。

Helm 2 架构

Helm 2 采用的是客户端-服务器架构:

Helm 2 Architecture

  • Tiller Server:Helm 通过在 Kubernetes 集群中安装 Tiller Server 来管理应用。Tiller 与 Kubernetes API Server 交互,用于安装、升级、查询和删除资源。
  • Helm Client:Helm 提供命令行接口供用户操作,负责与 Tiller Server 通信执行安装、升级、回滚等操作。

Helm 3 架构

Helm 3 采用纯客户端架构,移除了 Tiller Server:

Helm 3 Architecture

客户端直接与 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 之前,你需要准备以下环境:

  1. Kubernetes 集群:本教程使用 Minikube 搭建本地单节点集群
  2. kubectl:Kubernetes 命令行工具,用于与集群交互
  3. 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

搜索 Chart:

helm search repo <KEYWORD>

支持在本地仓库或 Artifact Hub 中搜索。

10. 从 Helm 2 迁移到 Helm 3

Helm 3 与 Helm 2 有以下主要区别:

✅ Helm 3 移除了 Tiller,更安全
✅ 默认不再自动创建命名空间
✅ Release 信息以 Secret 形式存储
✅ 使用三向合并策略进行升级

迁移建议:

11. 总结

在本教程中,我们学习了 Helm 的核心概念、安装方法、Chart 的创建与管理、模板语法、以及如何分发 Chart。我们还对比了 Helm 2 与 Helm 3 的主要区别。

Helm 作为 Kubernetes 的包管理工具,极大地简化了应用的部署与维护,是现代云原生开发中不可或缺的一环。熟练掌握 Helm,可以显著提升你在 Kubernetes 上部署应用的效率与灵活性。


原始标题:Using Helm and Kubernetes