2. values.schema.json 基础:JSON Schema 标准简介、Helm 中 schema 文件的位置与命名规则、基础 schema 结构示例

在 Helm 中,values.schema.json 是 Chart 开发者用来约束用户输入值的“契约文件”。它基于 JSON Schema 标准,允许你在用户执行 helm install 或 helm upgrade 之前,对 values.yaml 中的数据结构、类型、取值范围进行校验。本章将介绍 JSON Schema 的核心概念、Helm 中 schema 文件的放置规则,并通过一个基础示例展示其结构。

2.1 JSON Schema 标准简介

JSON Schema 是一种基于 JSON 格式的声明式语言,用于描述 JSON 数据的结构、类型和约束。它类似于 XML Schema 对 XML 的作用,但更轻量且广泛用于 API 校验、配置验证等场景。Helm 使用 JSON Schema Draft-07 作为校验标准。

核心概念:JSON Schema 通过定义 type、properties、required、minimum/maximum、pattern 等关键字,来描述一个 JSON 对象应该长什么样。如果实际数据不符合 schema,校验就会失败。

关键字 作用 示例
type 指定值的类型(string、number、object、array、boolean、null) "type": "string"
properties 定义对象中每个字段的 schema "properties": { "name": { "type": "string" } }
required 列出必须存在的字段 "required": ["name", "port"]
minimum / maximum 数值范围约束 "minimum": 1, "maximum": 65535
pattern 正则表达式匹配字符串 "pattern": "^[a-z]+$"
enum 限定值只能从枚举列表中选取 "enum": ["dev", "staging", "prod"]
$ref 引用 schema 内部或外部的定义,实现复用 "$ref": "#/definitions/port"

提示:Helm 只校验 values.yaml 中提供的值,不会校验 Chart 内部硬编码的默认值。如果用户未提供某个字段且该字段在 schema 中被标记为 required,校验会失败。

2.2 Helm 中 schema 文件的位置与命名规则

Helm 对 schema 文件的位置和命名有严格约定,必须遵循以下规则才能被自动识别:

  • 文件名固定:必须命名为 values.schema.json,大小写敏感。
  • 存放位置:必须位于 Chart 包的根目录,与 Chart.yaml、values.yaml 同级。
  • 文件格式:必须是合法的 JSON 文件,不能是 YAML 或其他格式。
  • 可选性:如果 Chart 根目录下不存在 values.schema.json,Helm 会跳过 schema 校验,仅依赖模板渲染时的类型推断。

注意:不要将 schema 文件放在 templates/ 或 charts/ 子目录中。Helm 只在 Chart 根目录查找 values.schema.json。如果放错位置,校验将不会生效。

以下是一个典型 Chart 目录结构,展示了 schema 文件的位置:

my-chart/
├── Chart.yaml
├── values.yaml
├── values.schema.json          <-- 必须在此位置
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── _helpers.tpl
└── charts/                     <-- 子 Chart 目录,不放置 schema

2.3 基础 schema 结构示例

下面是一个完整的 values.schema.json 示例,它定义了一个包含 replicaCount、image、service 和 ingress 的典型应用配置结构。该示例展示了类型约束、必填字段、嵌套对象和枚举值的使用。

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": ["replicaCount", "image", "service"],
  "properties": {
    "replicaCount": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100,
      "description": "Pod 副本数量,范围 1-100"
    },
    "image": {
      "type": "object",
      "required": ["repository", "tag"],
      "properties": {
        "repository": {
          "type": "string",
          "pattern": "^[a-z0-9]+(?:[._-][a-z0-9]+)*(?:/[a-z0-9]+(?:[._-][a-z0-9]+)*)*$",
          "description": "镜像仓库地址,如 nginx、myregistry.io/myapp"
        },
        "tag": {
          "type": "string",
          "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]*$",
          "description": "镜像标签,如 latest、v1.0.0"
        },
        "pullPolicy": {
          "type": "string",
          "enum": ["Always", "IfNotPresent", "Never"],
          "default": "IfNotPresent",
          "description": "镜像拉取策略"
        }
      }
    },
    "service": {
      "type": "object",
      "required": ["port"],
      "properties": {
        "type": {
          "type": "string",
          "enum": ["ClusterIP", "NodePort", "LoadBalancer"],
          "default": "ClusterIP",
          "description": "Service 类型"
        },
        "port": {
          "type": "integer",
          "minimum": 1,
          "maximum": 65535,
          "description": "Service 暴露的端口"
        }
      }
    },
    "ingress": {
      "type": "object",
      "properties": {
        "enabled": {
          "type": "boolean",
          "default": false,
          "description": "是否启用 Ingress"
        },
        "hostname": {
          "type": "string",
          "pattern": "^([a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,}$",
          "description": "Ingress 域名"
        }
      }
    }
  }
}

对应的 values.yaml 文件可能如下:

replicaCount: 3
image:
  repository: nginx
  tag: "1.25.0"
  pullPolicy: IfNotPresent
service:
  type: ClusterIP
  port: 80
ingress:
  enabled: false
  hostname: ""

当用户执行 helm install my-release ./my-chart --set replicaCount=200 时,Helm 会检测到 replicaCount 的值 200 超出了 schema 中定义的 maximum: 100,从而拒绝安装并返回错误信息。

校验流程:Helm 在渲染模板之前,会先读取 values.schema.json,将用户提供的 values(包括 --set 和 --values 传入的值)与 schema 进行比对。如果校验失败,Helm 会立即终止并输出详细的错误路径和原因,不会继续执行模板渲染。

values.schema.json 校验流程与结构 用户输入 values --set / --values / values.yaml Schema 校验引擎 values.schema.json 校验通过 继续模板渲染 校验失败 返回错误信息,终止安装 Schema 结构分解(基础示例) 顶层对象 type: object required: [replicaCount, image, service] 嵌套属性 image.repository: string + pattern service.port: integer + min/max 枚举与默认值 image.pullPolicy: enum ingress.enabled: boolean + default

2.4 常见校验场景与错误示例

为了帮助你快速理解 schema 校验的实际效果,下表列出了几种常见的用户输入错误以及 Helm 返回的典型错误信息:

用户输入 Schema 约束 Helm 错误信息(简化)
--set replicaCount=abc "type": "integer" replicaCount: Invalid type. Expected: integer, Given: string
--set replicaCount=200 "maximum": 100 replicaCount: Must be less than or equal to 100
--set image.tag="" "pattern": "^[a-zA-Z0-9][a-zA-Z0-9._-]*$" image.tag: Does not match pattern '^[a-zA-Z0-9]...'
--set service.type=External "enum": ["ClusterIP","NodePort","LoadBalancer"] service.type: value 'External' not in enum
未提供 replicaCount "required": ["replicaCount"] replicaCount: is required

最佳实践:在开发 Chart 时,建议先编写 values.schema.json,再编写模板。这样可以在模板渲染之前就锁定数据结构,避免后期因类型不匹配导致的大规模返工。同时,为每个 properties 添加 description 字段,可以提升 schema 的可读性,也方便后续生成文档。