K8S - Helm 入门与实战 - 应用部署与依赖治理

一、引言

在 Kubernetes 应用部署实践中,开发者常面临三大核心挑战:

1. 环境配置漂移

开发、测试、生产环境需维护多套高度相似的 Kubernetes 资源声明文件(YAML)。同步修改时易出现人工遗漏与配置失准。

2.版本回退失控

组件升级后因兼容性问题需快速回滚时,缺乏原子化的版本快照与变更追踪机制。

3.依赖治理低效

应用依赖的中间件(如 Redis/MySQL)需人工管理启动顺序与版本耦合,维护成本高且易引发环境不一致。

Helm作为 Kubernetes 的包管理工具,通过以下机制实现应用部署的标准化治理:

• 声明式模板与参数解耦

将 Kubernetes 资源抽象为可复用的 Chart 模板,通过 Values 文件实现多环境配置动态注入。

• 版本控制与发布追踪

基于 Release 记录每次部署的全量状态,支持原子化回滚至任意历史版本。

• 依赖声明与生命周期编排

通过子 Chart 声明式定义组件依赖关系,实现版本锁定与启动顺序自动编排。

二、Helm 的核心机制解析

2.1 Helm 架构与核心要素

Helm 是 Kubernetes 的包管理器,其核心逻辑可以类比为:将一组 Kubernetes 资源模板(Chart)+ 一组参数配置(Values),组合生成标准的资源清单,然后交由 Kubernetes 创建或更新对象。

Helm 核心概念

Chart 项目结构

一个典型的 Chart 项目结构如下:

java 复制代码
myapp-chart/            # 主chart,负责部署应用
├── Chart.yaml          # 元数据:名称、版本、依赖声明
├── values.yaml         # 默认参数配置
├── charts/             # 子Chart的存放目录(用于依赖管理)
└── templates/          # 资源模板目录
    ├── deployment.yaml
    ├── service.yaml
    └── _helpers.tpl    # 模板辅助函数

Helm 工作流程

1.模板渲染:解析模板文件(Go Template 语法),将 values.yaml中的参数动态注入,生成标准 manifest YAML 文件。

2.依赖处理:读取 Chart.yaml中的依赖配置,递归拉取子 Chart,构建完整依赖树。

3.资源部署:通过 Kubernetes API 与集群通信,创建或更新资源,并记录为一个新的 Release。

每一次 install或 upgrade操作,都会生成一条 Release 记录,支持随时回滚。

2.2 Helm 的标准化设计范式

1.模板抽象机制

Helm 使用 Go Template 模板语法将参数与资源分离,实现资源模板的复用和定制。

(1) 动态变量注入

通过 .Values.xxx引用配置项:

java 复制代码
# templates/deployment.yaml
spec:
  replicas: {{ .Values.replicaCount }}
  image: {{ .Values.image.repository }}:{{ .Values.image.tag }}

(2) 条件渲染控制

支持按条件渲染资源(如是否启用 Ingress):

java 复制代码
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ .Chart.Name }}
{{- end }}

2.多环境配置策略

为了适配开发、测试、生产等不同环境,Helm 支持灵活的参数覆盖机制。

(1) 配置文件叠加

可以使用多个 -f参数指定多个配置文件,实现层级覆盖:

java 复制代码
helm install myapp ./chart \
  -f values-base.yaml \
  -f values-prod.yaml

例如,values-base.yaml设置通用配置,values-prod.yaml只需覆盖部分生产环境特有参数。

最终生效的配置 = values-base.yaml被values-prod.yaml覆盖后的结果。

(2) 参数优先级规则

Helm 的参数解析优先级如下(从高到低):

命令行 --set > 指定的 values 文件 > 默认 values.yaml

可临时通过命令行 --set key=value快速覆盖任何配置项,适用于调试或自动化脚本场景。

3.Chart 版本管理体系

(1) Chart 版本号(version)

用于控制模板自身的版本,遵循语义化版本规范(SemVer):

java 复制代码
# Chart.yaml
version: 2.1.5        # 模板版本(每次结构变更需更新)
appVersion: "3.8.0"   # 被部署应用的版本(非必需同步)

(2) Release 回滚机制

每次部署会生成新的 Release,可通过命令回退到任意版本:

java 复制代码
helm history myapp -n prod    # 查看历史记录
helm rollback myapp 2         # 回滚到第 2 个版本

2.3 依赖治理机制解析

在实际项目中,很多应用依赖数据库、缓存等第三方组件。Helm 提供了完整的依赖管理方案。

1.子 Chart 管理

(1) 依赖声明

在主 Chart 的 Chart.yaml中声明依赖:

java 复制代码
# Chart.yaml
dependencies:
  - name: mysql
    version: "9.8.0"
    repository: "https://charts.bitnami.com/bitnami"
    condition: mysql.enabled # 可通过配置控制启动

(2) 下载依赖

使用如下命令更新并下载 mysql 子 Chart 到 charts/目录下:

java 复制代码
helm dependency update ./chart

2.版本约束策略

3.命名冲突与依赖隔离

如果多个子 Chart 使用了相同的名称,可以使用 alias重命名避免冲突:

java 复制代码
dependencies:
  - name: postgresql
    alias: user-db
    version: "11.6.12"

此时在模板中可通过 .Values.user-db引用该组件的参数配置。

三 、Helm 多环境部署管理实战

3.1 环境准备

1.安装必要工具

Mac/Linux 用户

java 复制代码
# 安装 Docker 并启动服务(容器运行时基础)
brew install --cask docker
open /Applications/Docker.app  # macOS 需手动启动 Docker Desktop

# 安装 Kubernetes 工具链(仅 Helm 相关)
brew install kubectl kind helm

# 验证核心工具版本
echo "🔧 关键工具版本:"
docker --version           # 预期输出: Docker version 24.x+
kubectl version --client   # 预期输出: Client Version: v1.28.x
helm version --short       # 预期输出: v3.12.x

2.创建本地 Kubernetes 集群

java 复制代码
# 使用 Kind 快速创建单节点集群(轻量级)
kind create cluster --name helm-lab --image=kindest/node:v1.28.0
# 验证集群基础状态
kubectl cluster-info

3.配置实验命名空间

java 复制代码
# 创建隔离环境(避免污染 default 命名空间)
kubectl create ns helm-demo

# 设置默认操作空间(后续命令自动作用于此空间)
kubectl config set-context --current --namespace=helm-demo

4.一键环境验证

java 复制代码
echo " 环境健康检查:"
kubectl get nodes          # 预期输出 STATUS=Ready
helm list -A               # 确认无残留 Helm Release
docker ps                  # 查看 Kind 容器是否运行

关键工具说明

3.2 场景与目标

使用 Helm 实现典型微服务系统的多环境部署。该系统包含以下服务及其依赖:

• frontend:前端服务,负责与用户交互,独立部署

• backend:后端服务,负责处理业务逻辑,依赖 Redis 缓存

• Redis:缓存服务,作为子 Chart 引入

通过 Helm 实现以下目标:

• 配置标准化:通过父 Chart 统一管理 frontend和 backend的部署模板

• 环境隔离:使用 values-dev.yaml和 values-prod.yaml管理环境差异

• 依赖治理:通过子 Chart 管理 Redis 依赖

• 版本控制:支持 Helm 版本回滚

3.3 项目目录结构

如下为典型 Helm 多环境部署结构图

java 复制代码
myapp/
├── Chart.yaml          # 父 Chart 元数据
├── values.yaml         # 全局默认配置
├── values-dev.yaml     # 开发环境覆盖配置
├── values-prod.yaml    # 生产环境覆盖配置
├── charts/             # 子 Chart 目录(存放 Redis 依赖)
└── templates/          # 核心模板
    ├── frontend.yaml   # 前端服务模板
    ├── backend.yaml    # 后端服务模板
    └── _helpers.tpl    # 模板函数库

主要文件说明:

• Chart.yaml:Helm Chart 元数据,定义应用的基本信息。

• values.yaml:通用配置文件,提供默认值。

• values-dev.yaml:开发环境配置,覆盖默认值。

• values-prod.yaml:生产环境配置,覆盖默认值。

• charts/:存放子 Chart(如 Redis)的目录。

• templates/:存放 Kubernetes 资源模板,定义具体的服务部署配置。

3.4 实战步骤

步骤 1:创建 Helm Chart

java 复制代码
# 初始化 Chart 结构
helm create myapp
rm -rf myapp/templates/*  # 清空默认模板(从头开始)

步骤 2:定义 Chart 元数据

java 复制代码
# myapp/Chart.yaml
apiVersion: v2          # Helm Chart API 版本(v2 是当前稳定版)
name: myapp             # Chart 名称(必须全小写,无空格)
description: 多环境Web应用示例
version: 1.0.0          # Chart 版本(必须遵循 SemVer 规范)
appVersion: "1.0"       # 应用本身的版本(字符串类型)

# 定义依赖组件(可包含多个子Chart)
dependencies:
  - name: redis          # 官方Redis Chart名称
    version: "17.0.0"    # 严格指定版本号(避免版本漂移)
    repository: "https://charts.bitnami.com/bitnami"  # 官方仓库地址
    condition: redis.enabled  # 是否启用此依赖(由values.yaml中的redis.enabled控制)
依赖操作演示
# 执行后会在 charts/ 目录生成 redis-17.0.0.tgz
helm dependency update myapp

# 查看目录结构
tree myapp/charts/
myapp/charts/
└── redis-17.0.0.tgz  # 下载的依赖包(二进制格式)

步骤 3:编写模板文件

前端服务模板

java 复制代码
# myapp/templates/frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Chart.Name }}-frontend
  labels:
    app: frontend
spec:
  replicas: {{ .Values.frontend.replicas }}
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
        ports:
        - containerPort: 80
        env:
        - name: REDIS_HOST
          value: {{ .Chart.Name }}-redis-master  # 引用 Redis 服务名称

---
apiVersion: v1
kind: Service
metadata:
  name: {{ .Chart.Name }}-frontend
spec:
  type: {{ .Values.frontend.service.type }}
  ports:
  - port: 80
    targetPort: 80
  selector:
    app: frontend

后端服务模板

java 复制代码
# myapp/templates/backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Chart.Name }}-backend
spec:
  replicas: {{ .Values.backend.replicas }}
  strategy:
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0 
  template:
    spec:
      containers:
      - name: backend
        image: "{{ .Values.backend.image }}"
        resources:
          requests:
            cpu: {{ .Values.backend.resources.requests.cpu }}

---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: {{ .Chart.Name }}-backend-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: {{ .Chart.Name }}-backend
  minReplicas: {{ .Values.backend.hpa.minReplicas }}
  maxReplicas: {{ .Values.backend.hpa.maxReplicas }}
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: {{ .Values.backend.hpa.cpuUtilization }}

步骤 4:配置参数文件

默认参数

java 复制代码
# myapp/values.yaml
frontend:
  replicas: 2
  image:
    repository: nginx
    tag: stable
  service:
    type: ClusterIP

backend:
  image: myapp/backend:v1
  replicas: 3
  resources:
    requests:
      cpu: 100m
  hpa:
    minReplicas: 2
    maxReplicas: 5
    cpuUtilization: 50

redis:
  enabled: true

开发环境覆盖

java 复制代码
# myapp/values-dev.yaml
frontend:
  replicas: 1
  service:
    type: NodePort  # 开发环境暴露 NodePort

backend:
  hpa:
    cpuUtilization: 80  # 开发环境提高扩缩容阈值
生产环境覆盖
# myapp/values-prod.yaml
frontend:
  replicas: 3
  image:
    tag: latest  # 生产使用最新镜像

backend:
  replicas: 5
  resources:
    requests:
      cpu: 500m  # 生产环境增加资源

步骤 5:安装部署开发环境

java 复制代码
helm install myapp ./myapp -n helm-demo \
  -f myapp/values.yaml \
  -f myapp/values-dev.yaml \
  --set backend.image=myapp/backend:dev-latest  # 命令行覆盖镜像标签

步骤 6:验证部署

1.验证 Helm Release 状态

java 复制代码
helm list -n helm-demo
NAME    NAMESPACE   REVISION    UPDATED                                 STATUS      CHART         APP VERSION
myapp   helm-demo    1           2023-08-20 14:30:15.123456 +0800 CST    deployed    myapp-1.0.0   1.0

关键点验证

• STATUS = deployed:Release 成功部署

• CHART = myapp-1.0.0:Chart 版本与定义一致

2.验证 Kubernetes 资源生成

java 复制代码
kubectl get all -n helm-demo
NAME                            READY   STATUS    RESTARTS   AGE
pod/myapp-frontend-7c5d8f8bdf   1/1     Running   0          2m
pod/myapp-backend-5d7d6c8b5f    1/1     Running   0          2m

NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/myapp-frontend  ClusterIP   10.96.123.45    <none>        80/TCP    2m

NAME                       READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/frontend   1/1     1            1           2m
deployment.apps/backend    1/1     1            1           2m

NAME                                                REFERENCE             TARGETS    MINPODS   MAXPODS   REPLICAS   AGE
horizontalpodautoscaler.autoscaling/myapp-backend-hpa   Deployment/backend   0%/50%     2         5         1          2m

关键点验证

• Pod:所有应用容器处于 Running 状态

• Service:前端服务类型为 NodePort(来自 values-dev.yaml覆盖)。

• HPA:CPU 利用率阈值为 80%(来自dev 覆盖)。

3.验证参数注入效果

java 复制代码
检查前端副本数(来自 values-dev.yaml覆盖)

kubectl get deployment myapp-frontend -n helm-demo -o=jsonpath='{.spec.replicas}'
1  # 开发环境覆盖为 1 个副本(默认为 2)
检查后端镜像标签(命令行动态覆盖)

kubectl get deployment myapp-backend -n helm-demo -o=jsonpath='{.spec.template.spec.containers[0].image}'
myapp/backend:dev-latest  # 来自 --set 参数覆盖

4.验证依赖管理(子 Chart 状态)

java 复制代码
检查 Redis 子 Chart 启用情况

helm get values myapp -n helm-demo | grep redis.enabled
redis.enabled: true
查看 Redis 服务状态

kubectl get svc -n helm-demo | grep redis
myapp-redis-master   ClusterIP   10.96.234.56   <none>        6379/TCP   2m

关键点验证

• Redis 服务名称包含 myapp前缀(Chart 名称隔离)

• 端口 6379正常开放(来自子 Chart 默认配置)

至此,我们已通过 Helm 实现了一个典型微服务系统的多环境部署流程。

注:_helpers.tpl 函数模版库 将在下篇讲解。

3.5 Helm 实践小结

关键经验:

• 配置隔离:使用 values-dev.yaml/ values-prod.yaml实现环境差异。

• 依赖管理:子 Chart 引入 Redis,实现服务与数据库的一体化部署。

• 模板复用:借助 _helpers.tpl统一标签与命名,提升可维护性。

• 版本控制:每次部署生成独立 Release,可回滚、追踪,保障发布安全。

注意事项:

• 避免配置文件冗余,保持差异项聚焦。

• 固定依赖版本,防止不兼容风险。

• 使用 --namespace保持资源隔离。

• 配置文件建议纳入 Git,支持多人协作与变更追踪。

四、总结

4.1 核心重点

Helm 在 Kubernetes 应用管理中的价值:

• 标准化封装:通过 Chart 实现跨环境部署的统一打包。

• 灵活配置管理:支持多套 Values 实现环境差异与个性化控制。

• 依赖与复用机制:通过子 Chart 管理依赖组件,提升集成效率。

• 版本控制体系:支持版本回滚、差异对比与发布历史追踪,增强发布安全性。

相关推荐
BUTCHER51 小时前
Docker镜像使用
java·docker·容器
一只 Lemon2 小时前
K8s存储系统(通俗易懂版)
云原生·容器·kubernetes
澜兮子2 小时前
k8s-高级调度(一)
云原生·容器·kubernetes
无敌糖果2 小时前
K8S的Helm包管理器
docker·容器·kubernetes·helm·helm安装包
筱小虾米2 小时前
Docker配置国内镜像源
运维·docker·容器
爱吃芝麻汤圆3 小时前
k8s之Snapshots 详解
云原生·容器·kubernetes
开挖掘机上班5 小时前
基于Alpine构建MySQL镜像
mysql·docker·容器
todoitbo5 小时前
docker搭建freeswitch实现点对点视频,多人视频
docker·容器·音视频·freeswitch·视频聊天
William一直在路上7 小时前
回顾一下Docker的基本操作
docker·容器·eureka
阿里云云原生7 小时前
Nacos 开源 MCP Router,加速 MCP 私有化部署
云原生