我有一个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服务器容器的日志流中也没有任何相关消息。
在命令行上使用kubectl patch
时,也会发生相同的错误:
$ kubectl patch mycrd.example.com test --type=json -p '[{"op": "replace", "path": "/status/foo", "value": "bar"}]'
The "" is invalid
此错误发生的可能原因是什么?我有什么选项可以进一步调试?
答案 0 :(得分:3)
在仍然输入问题的同时找到了(或至少是部分)答案...
Kubernetes API服务器不会为JSON补丁输入递归创建嵌套对象。此行为与JSON Patch specification in RFC 6902, section A.12一致:
A.12。添加到不存在的目标
目标JSON文档示例:
{ "foo": "bar" }
JSON补丁文件:
[ { "op": "add", "path": "/baz/bat", "value": "qux" } ]
此JSON补丁文件已应用于上述目标JSON文档, 会导致错误(因此将不会应用), 因为“添加”操作的目标位置没有引用 文档的根目录,既不是现有对象的成员,也不是 现有数组的成员。
这就是为什么自定义资源没有.status
属性开始时原始请求失败的原因。以下两个后续调用(第二个为原始调用)将成功完成:
$ 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
属性已经包含要保留的数据,则不是一个好主意。
在这种情况下,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