将JSON补丁应用于Kubernetes自定义资源时出错

时间:2019-08-13 14:45:12

标签: kubernetes kubectl kubernetes-custom-resources

我有一个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

此错误发生的可能原因是什么?我有什么选项可以进一步调试?

1 个答案:

答案 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