我有一个 Kubernetes 实例 Custom Resource我想使用 JSON 补丁通过 Kubernetes API 进行补丁。
这是我的 PATCH 请求:
PATCH /apis/example.com/v1alpha1/namespaces/default/mycrd/test HTTP/1.1
Accept: application/json
Content-Type: application/json-patch+json
[other headers omitted for brevity...]
[
{"op": "replace", "path": "/status/foo", value: "bar"}
]
我相当确定我的请求正文是有效的 JSON patch ,而且我之前已经使用类似的 API 调用成功更新了核心(非 CRD)API 资源。 CRD 有一个
openAPIV3Schema
定义明确允许 .status.foo
存在且属于 string
类型.上述请求被 Kubernetes API 服务器拒绝,响应如下:
HTTP/1.1 422 Unprocessable Entity
Conent-Type: application/json
[other headers omitted for brevity...]
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "the server rejected our request due to an error in our request",
"reason": "Invalid",
"details": {},
"code": 422
}
根据CRD documentation , CRD 应该支持
PATCH
与 application/json-patch+json
的请求内容类型。但出于某种原因,如果 Kubernetes 没有告诉我原因,请求似乎是无效的。 API 服务器 pod 的日志流中也没有任何相关消息。使用
kubectl patch
时也会出现同样的错误在命令行上:$ kubectl patch mycrd.example.com test --type=json -p '[{"op": "replace", "path": "/status/foo", "value": "bar"}]'
The "" is invalid
发生此错误的可能原因是什么?我有哪些选项可以进一步调试?
最佳答案
在仍然输入问题的同时找到了(或至少是部分)答案......
Kubernetes API 服务器不会为 JSON 补丁输入递归创建嵌套对象。 此行为与 JSON Patch specification in RFC 6902, section A.12 一致:
A.12. Adding to a Nonexistent Target
An example target JSON document:
{ "foo": "bar" }
A JSON Patch document:
[ { "op": "add", "path": "/baz/bat", "value": "qux" } ]
This JSON Patch document, applied to the target JSON document above, would result in an error (therefore, it would not be applied), because the "add" operation's target location that references neither the root of the document, nor a member of an existing object, nor a member of an existing array.
这就是当自定义资源没有
.status
时原始请求失败的原因。属性(property)开始。以下两个后续调用(第二个是原始调用)将成功完成:$ kubectl patch mycrd.example.com test --type=json \
-p '[{"op": "replace", "path": "/status", "value": {}}]'
mycrd.example.com/test patched
$ kubectl patch mycrd.example.com test --type=json \
-p '[{"op": "replace", "path": "/status/foo", "value": "bar"}]'
mycrd.example.com/test patched
显然,replace
整个.status
与 {}
的属性(property)如果该属性已包含您要保留的数据,则不是一个好主意。在这种情况下,JSON 补丁的合适替代方案是 JSON Merge Patch :
PATCH /apis/example.com/v1alpha1/namespaces/default/mycrd/test HTTP/1.1
Accept: application/json
Content-Type: application/merge-patch+json
[other headers omitted for brevity...]
{
"status": {
"foo": "bar"
}
}
或者,或者,使用 kubectl
:$ kubectl patch mycrd.example.com test --type=merge \
-p '{"status": {"foo": "bar"}}'
mycrd.example.com/test patched
关于kubernetes - 将 JSON 补丁应用于 Kubernetes 自定义资源时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57480205/