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

标签 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 应该支持 PATCHapplication/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/

相关文章:

kubernetes - 如何检查字段是否在自定义资源中显式设置

Kubernetes:了解资源请求/限制和调度

kubernetes - 我可以在Kubernetes服务中使用多个名称吗?

kubernetes - 无法创建 pod 沙箱 : rpc error: code = Unknown desc = failed to set up sandbox container

kubernetes - 运行kubeadm重置后的问题

java - 使用 Kubernetes 的 java-client 创建 CRD

docker - 如何使用 docker(不是 vagrant 或 virtualbox)在 mac os High Sierra 上运行 kubernetes?

mysql - 从nodejs GKE pod连接到外部mysql数据库

kubernetes - 有人可以解释不同的Kubernetes Yaml文件和类型吗?

Kubernetes:自定义资源的 RBAC 授权失败