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 管理依赖组件,提升集成效率。

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

相关推荐
就叫飞六吧3 小时前
Kubernetes弹性伸缩:让应用自动应对流量洪峰与低谷
云原生·容器·kubernetes
Ares-Wang5 小时前
私有仓库 Harbor、GitLab
kubernetes
瑟王6 小时前
Kubernetes笔记(1)Kubernetes入门
容器·kubernetes
格桑阿sir7 小时前
Kubernetes控制平面组件:Controller Manager详解
kubernetes·controller·informer·manager·控制器·ccm·leaderelection
bing_1589 小时前
微服务中怎么获取请求头信息
微服务·云原生·架构
大米74511 小时前
kubeadm部署k8s
云原生·容器·kubernetes
开心码农1号14 小时前
K8s 资源分类
大数据·容器·kubernetes
北漂老男孩14 小时前
深入理解高性能网络通信:从内核源码到云原生实践
云原生
hwj运维之路15 小时前
基于k8s的Jenkins CI/CD平台部署实践(三):集成ArgoCD实现持续部署
ci/cd·kubernetes·jenkins
AWS官方合作商16 小时前
AWS云服务深度技术解析:架构设计与最佳实践
云原生·云计算·aws·aws架构设计