2. Helm Chart 基础回顾:Chart.yaml、values.yaml、templates 目录结构及渲染机制

在深入 values.schema.json 准入策略之前,必须牢固掌握 Helm Chart 的核心构成与渲染流水线。Helm 将 Kubernetes 资源打包为 Chart,通过模板引擎将静态 YAML 转化为参数化、可复用的交付制品。本节聚焦三个核心文件与模板渲染的完整链路。

2.1 Chart 目录结构总览

一个标准的 Helm Chart 目录遵循以下约定(以 my-app 为例):

my-app/
├── Chart.yaml          # Chart 元数据(名称、版本、依赖等)
├── values.yaml         # 默认配置值(用户可覆盖)
├── values.schema.json  # (可选)JSON Schema 校验 values 结构
├── charts/             # (可选)子 Chart 或依赖包
├── templates/          # Go 模板文件,渲染后生成 Kubernetes 资源
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── _helpers.tpl    # 模板辅助函数(不直接生成资源)
│   └── NOTES.txt       # 安装后的使用说明
└── .helmignore         # (可选)打包时忽略的文件模式
关键点:只有 templates/ 目录下的文件会经过模板引擎渲染并提交给 Kubernetes API;_helpers.tpl 以 _ 开头,不会被当作独立资源文件处理。

2.2 Chart.yaml:Chart 的身份证明

Chart.yaml 是每个 Chart 的入口文件,定义了 Chart 的元数据、版本约束和依赖关系。以下是一个生产级示例:

apiVersion: v2
name: my-app
description: A production-grade microservice deployment
type: application
version: 1.2.3
appVersion: "2.5.0"
kubeVersion: ">=1.21.0-0"
keywords:
  - microservice
  - web
maintainers:
  - name: DevOps Team
    email: devops@example.com
dependencies:
  - name: postgresql
    version: "12.x"
    repository: "https://charts.bitnami.com/bitnami"
    condition: postgresql.enabled
字段 说明 示例值
apiVersion Chart API 版本,v2 为 Helm 3+ 标准 v2
version Chart 自身的语义化版本,用于发布管理 1.2.3
appVersion 所部署应用的版本,与 Chart 版本解耦 "2.5.0"
kubeVersion 对 Kubernetes 集群版本的约束 >=1.21.0-0
dependencies 子 Chart 依赖列表,支持条件启用 postgresql
常见陷阱:version 与 appVersion 混淆会导致升级策略混乱。Chart 版本变化触发 Helm Release 升级,而 appVersion 仅作为标签信息,不参与版本比较。

2.3 values.yaml:配置的默认值锚点

values.yaml 是用户与 Chart 交互的主要界面。它定义了所有可配置参数的默认值,模板文件通过 .Values 对象引用这些值。良好的 values 设计应具备层次化结构和清晰注释。

# values.yaml
replicaCount: 3

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

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false
  host: ""

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

postgresql:
  enabled: true
  auth:
    database: myapp
    username: myapp

用户可通过 --set 或自定义 values-*.yaml 文件覆盖任意层级的值。覆盖优先级为:--set > 用户 values 文件 > values.yaml 默认值。

2.4 templates 目录与渲染机制

templates/ 目录下的文件使用 Go 模板语法({{ }}),结合 Sprig 函数库进行动态渲染。渲染流程分为三个阶段:

  1. 值合并:Helm 将 values.yaml、用户提供的 values 文件、--set 参数合并为一个统一的 .Values 对象。
  2. 模板解析:遍历 templates/ 目录(排除 _ 开头的文件),对每个文件执行 Go 模板引擎,生成纯 YAML/JSON 字符串。
  3. 资源验证:Helm 对渲染结果进行基本的 YAML 语法检查和 Kubernetes 资源校验(若启用 --validate)。
渲染核心公式:Chart 模板 + Values 数据 → 有效的 Kubernetes 资源清单。任何模板语法错误或值引用缺失都会导致渲染失败,阻止 Release 安装或升级。

以下是一个典型的 Deployment 模板片段:

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

2.5 渲染流程可视化

下图展示了从 Chart 源文件到最终 Kubernetes 资源的完整渲染链路:

Helm Chart 渲染流程 Helm Chart 渲染流程 Chart.yaml values.yaml 用户 values 覆盖 值合并(.Values 对象) Go 模板引擎渲染 Kubernetes 资源 YAML templates/ 目录 (含 _helpers.tpl)

2.6 模板函数与管道操作

Helm 模板支持丰富的内置函数和 Sprig 库,常用操作包括:

函数/操作 用途 示例
include 调用 _helpers.tpl 中定义的命名模板 {{ include "my-app.labels" . }}
nindent 换行并缩进指定空格数 {{ include "my-app.labels" . | nindent 4 }}
default 为缺失值提供默认值 {{ .Values.replicaCount | default 1 }}
quote 将值用双引号包裹 {{ .Values.image.tag | quote }}
required 强制要求某个值必须存在,否则报错 {{ required "ingress.host is required" .Values.ingress.host }}
toYaml 将结构体转为 YAML 字符串 {{ .Values.resources | toYaml | nindent 8 }}
最佳实践:使用 required 函数对安全敏感参数(如数据库密码、TLS 证书)进行强制校验,避免因遗漏配置导致集群安全风险。这是 values.schema.json 准入策略的补充手段。

2.7 子 Chart 与全局值

当 Chart 包含依赖(子 Chart)时,值传递遵循以下规则:

  • 父 Chart 的 values.yaml 中与子 Chart 同名的键会被自动传递给子 Chart。
  • 全局值(.Values.global) 可被所有子 Chart 共享,适用于跨 Chart 的公共配置(如全局域名、镜像仓库地址)。
  • 子 Chart 作用域隔离:子 Chart 无法直接访问父 Chart 的非全局值,必须通过显式传递或全局值。
# 父 Chart values.yaml
global:
  registry: docker.io
  domain: example.com

postgresql:
  auth:
    database: myapp
    username: myapp
  # 子 Chart 自动接收 postgresql 下的值

理解这些基础机制后,我们才能进一步探讨如何通过 values.schema.json 在渲染前对 values 进行结构化校验,从而拦截高风险变更——这正是本课程的核心主题。