@@ -1124,28 +1124,145 @@ And create it:
11241124kubectl apply -f my-crontab.yaml
11251125crontab "my-new-cron-object" created
11261126` ` `
1127+
11271128<!--
1128- # ## Validation rules
1129+ # ## Validation ratcheting
1130+ -->
1131+ # ## 验证逐步升级 {#validation-ratcheting}
1132+
1133+ {{< feature-state state="alpha" for_k8s_version="v1.28" >}}
1134+
1135+ <!--
1136+ You need to enable the `CRDValidationRatcheting`
1137+ [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) to
1138+ use this behavior, which then applies to all CustomResourceDefinitions in your
1139+ cluster.
1140+ -->
1141+ 你需要启用 `CRDValidationRatcheting`
1142+ [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/),
1143+ 才能使用这种行为,并将其应用到集群中的所有 CustomResourceDefinition。
1144+
1145+ <!--
1146+ Provided you enabled the feature gate, Kubernetes implements _validation racheting_
1147+ for CustomResourceDefinitions. The API server is willing to accept updates to resources that
1148+ are not valid after the update, provided that each part of the resource that failed to validate
1149+ was not changed by the update operation. In other words, any invalid part of the resource
1150+ that remains invalid must have already been wrong.
1151+ You cannot use this mechanism to update a valid resource so that it becomes invalid.
1152+ -->
1153+ 只要你启用了此特性门控,Kubernetes 就会对 CustomResourceDefinition 实施**验证逐步升级**。
1154+ 即使更新后的资源无效,API 服务器也愿意接受对资源的更新,
1155+ 只要资源中未通过验证的每个部分都没有被更新操作改变。
1156+ 换句话说,资源中任何无效的部分如果仍然无效,那它必须之前就是错误的。
1157+ 你不能使用此机制来更新一个有效资源,使其变为无效。
1158+
1159+ <!--
1160+ This feature allows authors of CRDs to confidently add new validations to the
1161+ OpenAPIV3 schema under certain conditions. Users can update to the new schema
1162+ safely without bumping the version of the object or breaking workflows.
1163+ -->
1164+ 此特性使得 CRD 的作者能够在某些条件下有信心地向 OpenAPIV3 模式定义中添加新的验证。
1165+ 用户可以安全地更新到新的模式定义,而不必提升对象的版本或破坏工作流。
1166+
1167+ <!--
1168+ While most validations placed in the OpenAPIV3 schema of a CRD support
1169+ ratcheting, there are a few exceptions. The following OpenAPIV3 schema
1170+ validations are not supported by ratcheting under the implementation in Kubernetes
1171+ {{< skew currentVersion >}} and if violated will continue to throw an error as normally:
1172+ -->
1173+ 尽管大多数放在 CRD 的 OpenAPIV3 模式定义中的验证都支持逐步升级,仍存在一些例外。
1174+ Kubernetes {{< skew currentVersion >}} 下实现的验证逐步升级不支持下面所列举的 OpenAPIV3 模式检查,
1175+ 如果检查时发现违例,会和以往一样抛出错误:
1176+
1177+ <!--
1178+ - Quantors
1179+ - ` allOf`
1180+ - ` oneOf`
1181+ - ` anyOf`
1182+ - ` not`
1183+ - any validations in a descendent of one of these fields
1184+ -->
1185+ - 量词
1186+ - ` allOf`
1187+ - ` oneOf`
1188+ - ` anyOf`
1189+ - ` not`
1190+ - 以及这些字段的下级字段中的所有合法性检查
1191+
1192+ <!--
1193+ - ` x-kubernetes-validations`
1194+ For Kubernetes 1.28, CRD validation rules](#validation-rules) are ignored by
1195+ ratcheting. Starting with Alpha 2 in Kubernetes 1.29, `x-kubernetes-validations`
1196+ are ratcheted.
1197+
1198+ Transition Rules are never ratcheted : only errors raised by rules that do not
1199+ use `oldSelf` will be automatically ratcheted if their values are unchanged.
1200+ -->
1201+ - ` x-kubernetes-validations`
1202+
1203+ 在 Kubernetes 1.28 中,CRD [验证规则](#validation-rules)被逐步升级所忽略。
1204+ 从 Kubernetes 1.29 的 Alpha 2 开始,`x-kubernetes-validations` 的检查也用逐步升级机制处理。
1205+
1206+ 转换规则(Transition Rules)永远不会被逐步升级机制处理:只有那些不使用
1207+ ` oldSelf` 的规则引发的错误会在其值未更改时自动按逐步升级机制处理。
1208+
1209+ <!--
1210+ - ` x-kubernetes-list-type`
1211+ Errors arising from changing the list type of a subschema will not be
1212+ ratcheted. For example adding `set` onto a list with duplicates will always
1213+ result in an error.
1214+ - ` x-kubernetes-map-keys`
1215+ Errors arising from changing the map keys of a list schema will not be
1216+ ratcheted.
1217+ -->
1218+ - ` x-kubernetes-list-type`
1219+
1220+ 更改子模式的列表类型引发的错误不会被逐步升级机制处理。
1221+ 例如,在具有重复项的列表上添加 `set` 一定会出错。
1222+
1223+ - ` x-kubernetes-map-keys`
1224+
1225+ 由于更改列表模式定义的映射键而引起的错误将不会被逐步升级机制处理。
1226+
1227+ <!--
1228+ - ` required`
1229+ Errors arising from changing the list of required fields will not be ratcheted.
1230+ - ` properties`
1231+ Adding/removing/modifying the names of properties is not ratcheted, but
1232+ changes to validations in each properties' schemas and subschemas may be ratcheted
1233+ if the name of the property stays the same.
1234+ -->
1235+ - ` required`
1236+
1237+ 由于更改必需字段列表而引起的错误将不会被逐步升级处理。
1238+
1239+ - ` properties`
1240+
1241+ 添加、移除、修改属性的名称不会被逐步升级处理,但如果属性名称保持不变,
1242+ 如果更改各属性的模式定义和子模式定义中的合法性检查规则,可能会被逐步升级机制处理。
1243+
1244+ <!--
1245+ - ` additionalProperties`
1246+ To remove a previously specified `additionalProperties` validation will not be
1247+ ratcheted.
1248+ - ` metadata`
1249+ Errors arising from changes to fields within an object's `metadata` are not
1250+ ratcheted.
11291251-->
1130- # ## 验证规则
1252+ - ` additionalProperties `
11311253
1132- {{< feature-state state="beta" for_k8s_version="v1.25" >}}
1254+ 移除先前指定的 `additionalProperties` 合法性检查时,不会被逐步升级机制处理。
1255+
1256+ - ` metadata`
1257+
1258+ 因更改对象的 `metadata` 中的字段而引起的错误不会被逐步升级机制处理。
11331259
11341260<!--
1135- Validation rules are in beta since 1.25 and the `CustomResourceValidationExpressions`
1136- [feature gate](/docs/reference/command-line-tools-reference/feature-gates/) is enabled by default to
1137- validate custom resource based on _validation rules_. You can disable this feature by explicitly
1138- setting the `CustomResourceValidationExpressions` feature gate to `false`, for the
1139- [kube-apiserver](/docs/reference/command-line-tools-reference/kube-apiserver/) component. This
1140- feature is only available if the schema is a [structural schema](#specifying-a-structural-schema).
1261+ # ## Validation rules
11411262-->
1142- 验证规则从 1.25 开始处于 Beta 状态,
1143- 默认情况下,`CustomResourceValidationExpressions` [特性门控](/zh-cn/docs/reference/command-line-tools-reference/feature-gates/)
1144- 是被启用的,以便根据**验证规则**来验证定制资源。
1145- 对于 [`kube-apiserver`](/zh-cn/docs/reference/command-line-tools-reference/kube-apiserver/) 组件,
1146- 特性门控显式设置为 false 来禁用此特性。
1263+ # ## 合法性检查规则 {#validation-rules}
11471264
1148- 这个特性只有在模式是[结构化的模式](#specifying-a-structural-schema)时才可用。
1265+ {{< feature-state state="stable" for_k8s_version="v1.29" >}}
11491266
11501267<!--
11511268Validation rules use the [Common Expression Language (CEL)](https://github.com/google/cel-spec)
@@ -1686,11 +1803,169 @@ message will be used instead.
16861803如果满足上述条件之一且未设置 `message` 字段,则将使用默认的检查失败消息。
16871804
16881805<!--
1689- ` messageExpression` is a CEL expression, so the restrictions listed in [Resource use by validation functions](#resource-use-by-validation-functions) apply. If evaluation halts due to resource constraints
1806+ ` messageExpression` is a CEL expression, so the restrictions listed in [Resource use by validation functions](#resource-use-by-validation-functions) apply. If evaluation halts due to resource constraints
16901807during `messageExpression` execution, then no further validation rules will be executed.
1808+
1809+ Setting `messageExpression` is optional.
1810+ -->
1811+ ` messageExpression` 是一个 CEL 表达式,
1812+ 因此[验证函数的资源使用](#resource-use-by-validation-functions)中所列出的限制也适用于它。
1813+ 如果在 `messageExpression` 执行期间由于资源限制而导致计算停止,则不会继续处理其他合法性检查规则。
1814+
1815+ ` messageExpression` 设置是可选的。
1816+
1817+ <!--
1818+ # ### The `message` field {#field-message}
1819+
1820+ If you want to set a static message, you can supply `message` rather than `messageExpression`.
1821+ The value of `message` is used as an opaque error string if validation fails.
1822+
1823+ Setting `message` is optional.
1824+ -->
1825+ # ### `message` 字段 {#field-message}
1826+
1827+ 如果你要设置一个静态消息,可以提供 `message` 而不是 `messageExpression`。
1828+ 如果合法性检查失败,则 `message` 的值将被用作不透明的错误字符串。
1829+
1830+ ` message` 设置是可选的。
1831+
1832+ <!--
1833+ # ### The `reason` field {#field-reason}
1834+
1835+ You can add a machine-readable validation failure reason within a `validation`, to be returned
1836+ whenever a request fails this validation rule.
1837+
1838+ For example :
1839+ -->
1840+ # ### `reason` 字段 {#field-reason}
1841+
1842+ 你可以在 `validation` 中添加一个机器可读的验证失败原因,以便在请求未通过此验证规则时返回。
1843+
1844+ 例如:
1845+
1846+ ` ` ` yaml
1847+ x-kubernetes-validations:
1848+ - rule: "self.x <= self.maxLimit"
1849+ reason: "FieldValueInvalid"
1850+ ` ` `
1851+
1852+ <!--
1853+ The HTTP status code returned to the caller will match the reason of the first failed validation rule.
1854+ The currently supported reasons are : " FieldValueInvalid" , "FieldValueForbidden", "FieldValueRequired", "FieldValueDuplicate".
1855+ If not set or unknown reasons, default to use "FieldValueInvalid".
1856+
1857+ Setting `reason` is optional.
1858+ -->
1859+ 返回给调用者的 HTTP 状态码将与第一个失败的验证规则的原因匹配。
1860+ 目前支持的原因有:"FieldValueInvalid"、"FieldValueForbidden"、"FieldValueRequired"、"FieldValueDuplicate"。
1861+ 如果未设置或原因未知,默认使用 "FieldValueInvalid"。
1862+
1863+ ` reason` 设置是可选的。
1864+
1865+ <!--
1866+ # ### The `fieldPath` field {#field-field-path}
1867+
1868+ You can specify the field path returned when the validation fails.
1869+
1870+ For example :
1871+ -->
1872+ # ### `fieldPath` 字段 {#field-field-path}
1873+
1874+ 你可以指定在验证失败时返回的字段路径。
1875+
1876+ 例如:
1877+
1878+ ` ` ` yaml
1879+ x-kubernetes-validations:
1880+ - rule: "self.foo.test.x <= self.maxLimit"
1881+ fieldPath: ".foo.test.x"
1882+ ` ` `
1883+
1884+ <!--
1885+ In the example above, the validation checks the value of field `x` should be less than the value of `maxLimit`.
1886+ If no `fieldPath` specified, when validation fails, the fieldPath would be default to wherever `self` scoped.
1887+ With `fieldPath` specified, the returned error will have `fieldPath` properly refer to the location of field `x`.
1888+ -->
1889+ 在上面的示例中,验证检查字段 `x` 的值应小于 `maxLimit` 的值。
1890+ 如果未指定 `fieldPath`,当验证失败时,`fieldPath` 将默认为 `self` 的作用范围。
1891+ 如果指定了 `fieldPath`,返回的错误将正确地将 `fieldPath` 指向字段 `x` 的位置。
1892+
1893+ <!--
1894+ The `fieldPath` value must be a relative JSON path that is scoped to the location of this x-kubernetes-validations extension in the schema.
1895+ Additionally, it should refer to an existing field within the schema.
1896+ For example when validation checks if a specific attribute `foo` under a map `testMap`, you could set
1897+ ` fieldPath` to `".testMap.foo"` or `.testMap['foo']'`.
1898+ If the validation requires checking for unique attributes in two lists, the fieldPath can be set to either of the lists.
1899+ For example, it can be set to `.testList1` or `.testList2`.
1900+ It supports child operation to refer to an existing field currently.
1901+ Refer to [JSONPath support in Kubernetes](/docs/reference/kubectl/jsonpath/) for more info.
1902+ The `fieldPath` field does not support indexing arrays numerically.
1903+ -->
1904+ ` fieldPath` 值必须是相对 JSON 路径,且限定为此 `x-kubernetes-validations` 扩展在模式定义中的位置。
1905+ 此外,它应该指向模式定义中的一个现有字段。例如,当验证检查 `testMap` 映射下的特定属性 `foo` 时,
1906+ 你可以将 `fieldPath` 设置为 `".testMap.foo"` 或 `.testMap['foo']'`。
1907+ 如果验证要求检查两个列表中的唯一属性,`fieldPath` 可以设置为其中一个列表。
1908+ 例如,它可以设置为 `.testList1` 或 `.testList2`。它目前支持引用现有字段的取子操作。
1909+ 更多信息请参阅 [Kubernetes 中的 JSONPath 支持](/zh-cn/docs/reference/kubectl/jsonpath/)。
1910+ ` fieldPath` 字段不支持按数字下表索引数组。
1911+
1912+ <!--
1913+ Setting `fieldPath` is optional.
1914+
1915+ # ### The `optionalOldSelf` field {#field-optional-oldself}
1916+ -->
1917+ ` fieldPath` 设置是可选的。
1918+
1919+ # ### `optionalOldSelf` 字段 {#field-optional-oldself}
1920+
1921+ {{< feature-state state="alpha" for_k8s_version="v1.29" >}}
1922+
1923+ <!--
1924+ The feature [CRDValidationRatcheting](#validation-ratcheting) must be enabled in order to
1925+ make use of this field.
1926+
1927+ The `optionalOldSelf` field is a boolean field that alters the behavior of [Transition Rules](#transition-rules) described
1928+ below. Normally, a transition rule will not evaluate if `oldSelf` cannot be determined :
1929+ during object creation or when a new value is introduced in an update.
1930+ -->
1931+ 要使用此字段,必须启用特性 [CRDValidationRatcheting](#validation-ratcheting)。
1932+
1933+ ` optionalOldSelf` 字段是一个布尔字段,它会改变下文所述的[转换规则](#transition-rules)的行为。
1934+ 通常,在对象创建期间或在更新中引入新值时,如果无法确定 `oldSelf`,则不会处理转换规则。
1935+
1936+ <!--
1937+ If `optionalOldSelf` is set to true, then transition rules will always be
1938+ evaluated and the type of `oldSelf` be changed to a CEL [`Optional`](https://pkg.go.dev/github.com/google/cel-go/cel#OptionalTypes) type.
1939+ -->
1940+ 如果 `optionalOldSelf` 设置为 true,则一定会处理转换规则,并且 `oldSelf` 的类型会被更改为
1941+ CEL [`Optional`](https://pkg.go.dev/github.com/google/cel-go/cel#OptionalTypes) 类型。
1942+
1943+ <!--
1944+ ` optionalOldSelf` is useful in cases where schema authors would like a more
1945+ control tool [than provided by the default equality based behavior of ][#validation-ratcheting]
1946+ to introduce newer, usually stricter constraints on new values, while still
1947+ allowing old values to be "grandfathered" or ratcheted using the older validation.
1948+
1949+ Example Usage :
1950+ -->
1951+ ` optionalOldSelf` 在以下情况下很有用,
1952+ 模式的作者希望拥有[比默认的基于相等性的行为](#validation-ratcheting)的控制力更强的工具,
1953+ 以便对新值引入更严格的约束,同时仍允许旧值通过旧的验证进行 "grandfathered"(溯源)或作逐步升级处理。
1954+
1955+ 示例用法:
1956+
1957+ <!--
1958+ | CEL | Description |
1959+ |-----------------------------------------|-------------|
1960+ | `self.foo == "foo" || (oldSelf.hasValue() && oldSelf.value().foo != "foo")` | Ratcheted rule. Once a value is set to "foo", it must stay foo. But if it existed before the "foo" constraint was introduced, it may use any value |
1961+ | [oldSelf.orValue(""), self].all(x, ["OldCase1", "OldCase2"].exists(case, x == case)) || ["NewCase1", "NewCase2"].exists(case, self == case) || ["NewCase"].has(self)` | "Ratcheted validation for removed enum cases if oldSelf used them" |
1962+ | oldSelf.optMap(o, o.size()).orValue(0) < 4 || self.size() >= 4 | Ratcheted validation of newly increased minimum map or list size |
16911963-->
1692- ` messageExpression` 是一个 CEL 表达式,因此[验证函数的资源使用](#resource-use-by-validation-functions)中列出的限制也适用于它。
1693- 如果在 `messageExpression` 执行期间由于资源限制而导致计算停止,则不会执行进一步的检查规则。
1964+ | CEL | 描述 |
1965+ |-----------------------------------------|------|
1966+ | `self.foo == "foo" || (oldSelf.hasValue() && oldSelf.value().foo != "foo")` | 逐步升级规则。一旦将值设置为 "foo",它必须保持为 foo。但如果在引入 "foo" 约束之前它已存在,则可以使用所有值 |
1967+ | [oldSelf.orValue(""), self].all(x, ["OldCase1", "OldCase2"].exists(case, x == case)) || ["NewCase1", "NewCase2"].exists(case, self == case) || ["NewCase"].has(self)` | "如果 oldSelf 使用了已移除的枚举值,则逐步升级验证" |
1968+ | oldSelf.optMap(o, o.size()).orValue(0) < 4 || self.size() >= 4 | 对新增的最小映射或列表大小进行逐步升级验证 |
16941969
16951970<!--
16961971# ### Validation functions {#available-validation-functions}
0 commit comments