如何在Kubernetes CRD Schema中禁止额外属性并触发校验错误?
问题背景
现有如下CRD定义:
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: examples.tomasaschan.com spec: group: tomasaschan.com names: kind: Example listKind: Examples plural: examples singular: example scope: Namespaced versions: - name: v1 served: true storage: true schema: openAPIV3Schema: properties: spec: properties: foo: type: string type: object type: object
合法的Example资源示例:
apiVersion: tomasaschan.com/v1 kind: Example metadata: name: example1 spec: foo: bar
由于foo不是必填项,当拼写错误(如写成boo)时,API服务器仍会接受该资源:
apiVersion: tomasaschan.com/v1 kind: Example metadata: name: example1 spec: boo: far
需求:让此类包含未知字段的请求触发Schema校验错误,返回400响应并提示未知属性。
此前尝试的问题:
- 在JSON Schema中使用
additionalProperties: false会触发API服务器报错:Forbidden: additionalProperties and properties are mutual exclusive - 设置
spec.preserveUnknownFields: false或x-kubernetes-preserve-unknown-fields: false仅会丢弃未知字段,不会拒绝请求。
解决方案
方案1:使用x-kubernetes-validations(Kubernetes 1.25+)
从Kubernetes 1.25开始,CRD支持通过x-kubernetes-validations扩展添加自定义校验规则,直接在schema中实现未知字段的拦截。修改后的CRD如下:
apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: examples.tomasaschan.com spec: group: tomasaschan.com names: kind: Example listKind: Examples plural: examples singular: example scope: Namespaced preserveUnknownFields: false # 必须关闭未知字段保留,确保校验生效 versions: - name: v1 served: true storage: true schema: openAPIV3Schema: properties: spec: type: object properties: foo: type: string # 添加自定义校验规则,限制spec仅允许foo属性 x-kubernetes-validations: - rule: "self.keys().all(key, key in ['foo'])" message: "spec仅允许包含'foo'属性,未知属性: {{key}}" type: object
当提交包含boo的Example资源时,API服务器会返回400错误,示例响应如下:
Error from server: error when creating "example.yaml": admission webhook "validation.examples.tomasaschan.com" denied the request: spec仅允许包含'foo'属性,未知属性: boo
方案2:使用Validating Admission Webhook(全版本兼容)
如果你的Kubernetes版本低于1.25,或需要更复杂的校验逻辑,可通过Validating Admission Webhook实现:
- 开发一个Webhook服务,接收Kubernetes的AdmissionReview请求,解析请求中的Example资源spec字段。
- 对比spec的属性列表与CRD定义的允许字段,若存在未知字段,返回
allowed: false的AdmissionResponse,并携带错误信息。 - 将Webhook注册到Kubernetes集群,配置为针对
examples.tomasaschan.com资源的CREATE、UPDATE操作触发校验。
这种方式完全自定义校验逻辑,可灵活控制错误提示和校验范围。
内容的提问来源于stack exchange,提问作者Tomas Aschan
相关产品推荐
相关产品推荐

