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 会立即终止并输出详细的错误路径和原因,不会继续执行模板渲染。
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 的可读性,也方便后续生成文档。