3. Chart 结构详解

Helm Chart 是 Kubernetes 应用的打包格式,其目录结构、元数据文件、模板引擎和依赖管理共同构成了 Helm 的资源模型基础。理解 Chart 的每一层结构,是编写可维护、可参数化 Helm 包的前提。

3.1 标准 Chart 目录结构

一个标准的 Helm Chart 遵循以下目录布局。每个文件和目录都有明确的职责:

路径 / 文件 必需 说明
mychart/ 是 Chart 根目录,名称与 Chart 名称一致
Chart.yaml 是 Chart 元数据文件,包含名称、版本、描述等
values.yaml 是 默认配置值文件,定义所有可参数化的变量
templates/ 是 Go 模板文件目录,渲染后生成 Kubernetes 资源清单
charts/ 否 子 Chart 依赖目录,存放被依赖的 Chart 包
crds/ 否 自定义资源定义(CRD)目录,优先于模板安装
README.md 否 Chart 使用说明文档
.helmignore 否 打包时忽略的文件模式列表,类似 .gitignore
最佳实践:即使 charts/ 和 crds/ 不是必需目录,但任何生产级 Chart 都应至少包含 charts/ 来管理依赖,或使用 crds/ 来安装 CRD。

3.2 Chart.yaml 文件

Chart.yaml 是 Chart 的“身份证”,Helm 通过它识别 Chart 的身份、版本和依赖关系。以下是一个标准示例:

apiVersion: v2
name: mychart
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: "1.16.0"
kubeVersion: ">=1.19.0-0"
keywords:
  - web
  - database
home: https://example.com
sources:
  - https://github.com/example/mychart
maintainers:
  - name: John Doe
    email: john@example.com
    url: https://example.com
dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
    tags:
      - database
    alias: db
icon: https://example.com/icon.svg
annotations:
  category: Infrastructure
字段 说明 示例值
apiVersion Chart API 版本,v2 是当前标准 v2
name Chart 名称,必须与目录名一致 mychart
version Chart 语义化版本,用于发布和回滚 0.1.0
appVersion 所打包应用的版本,与 Chart 版本独立 "1.16.0"
dependencies 依赖的子 Chart 列表,支持条件、标签、别名 见上例
type Chart 类型:application 或 library application
注意:version 和 appVersion 是两个不同的概念。version 控制 Chart 本身的迭代,appVersion 标记内部应用的版本。升级应用代码时只改 appVersion,修改 Chart 模板或配置时改 version。

3.3 values.yaml 文件

values.yaml 是 Chart 的配置中心,定义了所有可被模板引用的默认参数。Helm 通过 .Values 对象在模板中访问这些值。

# values.yaml
replicaCount: 3

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

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  className: ""
  hosts:
    - host: chart-example.local
      paths:
        - path: /
          pathType: ImplementationSpecific

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 250m
    memory: 256Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 10
  targetCPUUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

Values 的层级结构直接映射到模板中的访问路径:

  • .Values.replicaCount → 3
  • .Values.image.repository → nginx
  • .Values.service.port → 80
  • .Values.ingress.enabled → false
参数映射原则:模板中所有可变的值都应在 values.yaml 中定义默认值。用户通过 --set 或自定义 values 文件覆盖这些默认值,实现“一次编写,多处部署”。

3.4 templates 目录

templates/ 目录存放 Go 模板文件,Helm 将 values.yaml 中的参数注入模板,渲染出最终的 Kubernetes 资源清单。模板文件使用 .yaml 或 .tpl 扩展名。

一个典型的 Deployment 模板示例:

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "mychart.fullname" . }}
  labels:
    {{- include "mychart.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "mychart.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "mychart.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - containerPort: {{ .Values.service.port }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}

模板中常用的内置对象:

对象 来源 示例
.Values values.yaml + 用户覆盖 .Values.replicaCount
.Chart Chart.yaml .Chart.Name, .Chart.Version
.Release Helm 命令行参数 .Release.Name, .Release.Namespace
.Files Chart 中的非模板文件 .Files.Get "config.ini"
.Capabilities 目标 Kubernetes 集群信息 .Capabilities.KubeVersion

3.5 charts 依赖目录

charts/ 目录用于存放子 Chart 依赖。当你在 Chart.yaml 的 dependencies 中声明依赖后,执行 helm dependency update 会将依赖 Chart 下载到此目录。

依赖管理的三种方式:

  • 直接存放:手动将子 Chart 的 .tgz 包或目录放入 charts/
  • 声明式管理:在 Chart.yaml 的 dependencies 中声明,通过 helm dep update 自动下载
  • 条件依赖:使用 condition 和 tags 控制依赖是否启用

依赖声明示例:

# Chart.yaml 中的 dependencies 段
dependencies:
  - name: postgresql
    version: "12.x.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
    tags:
      - database
    alias: db

对应的 values.yaml 控制:

# values.yaml
postgresql:
  enabled: true
  postgresqlDatabase: myapp
  postgresqlUsername: admin
依赖别名(alias)的作用:当同一个 Chart 需要被多次引用时(例如两个不同的数据库实例),使用 alias 可以避免命名冲突。子 Chart 的所有值将通过别名访问,如 .Values.db.postgresqlDatabase。

3.6 Chart 结构全景图

下图展示了 Chart 各组件之间的数据流和依赖关系:

Helm Chart 结构全景图 Helm Chart 结构全景图 mychart/ (Chart 根目录) Chart.yaml values.yaml templates/ charts/ (依赖目录) deployment.yaml service.yaml _helpers.tpl 注入参数 元数据 子 Chart (tgz) Kubernetes 资源清单 核心数据流 Chart.yaml + values.yaml → templates/ 渲染 → 输出 Kubernetes 资源

3.7 参数映射流程

下图展示了从 values.yaml 到最终 Kubernetes 资源的完整参数映射链路:

Values 参数映射流程 Values 参数映射流程 values.yaml 默认参数定义 --set / -f 用户覆盖值 .Values 对象 合并后的参数树 Go 模板引擎 渲染资源清单 参数映射示例 values.yaml 定义: image.repository: nginx image.tag: "1.25.3" 模板引用: image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" → 渲染结果:image: nginx:1.25.3 用户覆盖:helm install myapp ./mychart --set image.tag=1.26.0 → 渲染结果:image: nginx:1.26.0

3.8 关键实践要点

  • 目录命名一致性:Chart 目录名必须与 Chart.yaml 中的 name 字段完全一致,否则 Helm 会报错。
  • 模板文件组织:按 Kubernetes 资源类型拆分模板文件(如 deployment.yaml、service.yaml、ingress.yaml),避免将所有资源写在一个大文件中。
  • Values 层级扁平化:避免过深的嵌套层级(超过 3 层),否则会降低可读性。使用 --set 覆盖时,深层路径容易出错。
  • 依赖版本锁定:执行 helm dependency update 后会生成 Chart.lock 文件,锁定所有依赖的精确版本,确保可重复构建。
  • 忽略非必要文件:使用 .helmignore 排除 .git/、.DS_Store、测试文件等,减小 Chart 包体积。
总结:Chart 结构是 Helm 资源模型的骨架。Chart.yaml 定义身份,values.yaml 提供参数,templates/ 负责渲染,charts/ 管理依赖。掌握这四者的协作关系,是编写高质量 Helm Chart 的基础。