第 10 章:K8s Helm:从手动部署到企业级包管理

5 阅读3分钟

第 10 章:K8s Helm:从手动部署到企业级包管理

上一章讲了 HPA。本章讲 Helm。它把 K8s 应用打包成 Chart,解决手动部署、配置管理、版本回退的问题。

10.1 为什么需要 Helm

手动管理 K8s 应用时,经常遇到这些问题:

  • 一个应用由十几个 YAML 文件组成,部署时容易漏掉
  • 不同环境(开发、测试、生产)要改一堆配置
  • 版本升级和回滚没有统一管理
  • 团队内部想复用已有的部署模板

Helm 就是 K8s 世界的包管理器,类似 Linux 的 apt/yum、macOS 的 Homebrew。

Helm 把一个应用的所有 K8s 资源打包成一个 Chart,可以一键安装、升级、回滚、卸载。

helm install myapp ./mychart
helm upgrade myapp ./mychart
helm rollback myapp 1
helm uninstall myapp

10.2 Chart 目录结构

Helm 把一个应用的所有 K8s 资源打包成一个 Chart:

Helm Chart 结构

mychart/
  Chart.yaml          # Chart 元数据
  values.yaml         # 默认配置值
  values-dev.yaml     # 开发环境覆盖值(可选)
  templates/          # YAML 模板
    _helpers.tpl      # 辅助模板函数
    deployment.yaml
    service.yaml
    ingress.yaml
    hpa.yaml
  charts/             # 依赖的 Chart(可选)
  README.md

10.2.1 Chart.yaml

apiVersion: v2
name: myapp
description: A Helm chart for my application
type: application
version: 1.0.0
appVersion: "v1.2.3"
字段含义
versionChart 本身的版本
appVersion应用的版本
typeapplicationlibrary

10.2.2 values.yaml

定义可配置项的默认值:

replicaCount: 2

image:
  repository: nginx
  tag: "1.27"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  host: app.example.com

resources:
  requests:
    cpu: 100m
    memory: 128Mi

10.2.3 templates/

模板文件使用 Go template 语法。例如 deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "myapp.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ include "myapp.name" . }}
  template:
    metadata:
      labels:
        app: {{ include "myapp.name" . }}
    spec:
      containers:
      - name: {{ include "myapp.name" . }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        resources:
          {{- toYaml .Values.resources | nindent 10 }}

{{ .Values.xxx }} 读取 values.yaml 中的值。{{ include }} 调用 _helpers.tpl 中定义的函数。

10.3 安装、升级、回滚、卸载

10.3.1 安装

# 安装本地 Chart
$ helm install myapp ./mychart

# 从仓库安装
$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm install mynginx bitnami/nginx

10.3.2 查看已安装应用

$ helm list
NAME    NAMESPACE  REVISION  UPDATED                  STATUS    CHART
myapp   default    1         2024-05-01 10:00:00      deployed  myapp-1.0.0

10.3.3 升级

$ helm upgrade myapp ./mychart

每次升级都会生成一个新的 revision。

10.3.4 回滚

# 查看历史
$ helm history myapp
REVISION  UPDATED                   STATUS
1         2024-05-01 10:00:00      deployed
2         2024-05-01 11:00:00      failed

# 回滚到版本 1
$ helm rollback myapp 1

10.3.5 卸载

$ helm uninstall myapp

Helm 会删除所有通过它创建的资源。

10.4 用 --set 和 -f 覆盖配置

10.4.1 --set 命令行覆盖

$ helm install myapp ./mychart \
  --set replicaCount=5 \
  --set image.tag=1.28

适合临时修改少量参数。

10.4.2 -f 指定 values 文件

# 开发环境
$ helm install myapp ./mychart -f values-dev.yaml

# 生产环境
$ helm install myapp ./mychart -f values-prod.yaml

values-prod.yaml 示例:

replicaCount: 5
image:
  tag: "1.27"

resources:
  requests:
    cpu: 500m
    memory: 512Mi
  limits:
    cpu: 1000m
    memory: 1Gi

ingress:
  enabled: true
  host: app.example.com

这样同一个 Chart 可以服务多个环境,不需要复制模板。

10.5 实战:通过 Helm 安装 Nginx

先添加仓库并搜索:

$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm repo update

$ helm search repo nginx
NAME            CHART VERSION   APP VERSION
bitnami/nginx   15.0.0          1.27.0

安装:

$ helm install mynginx bitnami/nginx \
  --set service.type=NodePort \
  --set service.nodePorts.http=30080

查看:

$ helm list
$ kubectl get pod,svc

在浏览器或 curl 访问:

$ curl http://192.168.0.201:30080

升级版本:

$ helm upgrade mynginx bitnami/nginx --set image.tag=1.28

回滚:

$ helm rollback mynginx 1

10.6 打包自己的应用为 Chart

下面从零创建一个最简单的 Chart:

$ helm create myapp

Helm 会生成一个模板工程。我们修改 values.yaml

replicaCount: 2

image:
  repository: nginx
  tag: "1.27"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

resources:
  requests:
    cpu: 100m
    memory: 128Mi

安装测试:

$ helm install myapp ./myapp

$ kubectl get pod,svc
NAME                       READY   STATUS
pod/myapp-xxx              1/1     Running

NAME           TYPE        CLUSTER-IP
service/myapp  ClusterIP   10.96.12.34

打包为 tgz 文件:

$ helm package ./myapp
Successfully packaged chart and saved it to: myapp-1.0.0.tgz

这个文件可以上传到 Helm 仓库或私有的 Chart Museum。

10.7 最佳实践

建议原因
不要用 latest 标签升级时 Helm 可能认为镜像没变,不触发滚动更新
使用语义化版本版本号清晰,方便回滚
用 values 文件管理环境差异不复制模板,减少维护成本
配置 resources避免 Pod 占用过多资源
使用 helm linthelm template安装前检查模板语法
敏感信息用 Secret不要把密码写进 values.yaml 明文提交

10.8 helm lint 和 helm template

安装前可以先本地检查:

# 检查 Chart 语法
$ helm lint ./myapp

# 渲染模板但不安装
$ helm template myapp ./myapp

helm template 是排查模板问题的好工具。它会把 values 注入模板,输出最终 YAML,方便检查字段是否正确。

10.9 本章小结

  • Helm 是 K8s 的包管理器,管理应用安装、升级、回滚
  • Chart 由 Chart.yaml、values.yaml、templates/ 组成
  • --set-f 可以灵活覆盖配置
  • 同一个 Chart 配合不同 values 文件服务多环境
  • 不要写 latest 标签,要用语义化版本
  • helm linthelm template 是本地检查利器

10.10 课后练习

  1. helm create 创建一个自己的 Chart,安装并查看生成的资源。
  2. --set 把副本数改成 5,验证 Deployment 是否同步更新。
  3. 为同一个 Chart 创建 values-dev.yamlvalues-prod.yaml,分别安装到不同命名空间。
  4. 升级 Chart 版本后执行回滚,观察 helm history 的变化。