hel*_*ert 3 kubernetes kubectl kubernetes-custom-resources
我有一个 Kubernetes自定义资源的实例,我想使用 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"}
]
Run Code Online (Sandbox Code Playgroud)
我相当确定我的请求正文是一个有效的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
}
Run Code Online (Sandbox Code Playgroud)
根据CRD 文档,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
Run Code Online (Sandbox Code Playgroud)
发生此错误的可能原因是什么?我有哪些选项可以进一步调试?
hel*_*ert 11
在仍然输入问题的同时找到了(或至少是部分)答案......
Kubernetes API 服务器不会为 JSON 补丁输入递归创建嵌套对象。此行为与RFC 6902 第 A.12 节中的JSON 补丁规范一致:
A.12. 添加到不存在的目标
示例目标 JSON 文档:
Run Code Online (Sandbox Code Playgroud){ "foo": "bar" }一个 JSON 补丁文档:
Run Code Online (Sandbox Code Playgroud)[ { "op": "add", "path": "/baz/bat", "value": "qux" } ]这个 JSON Patch 文档,应用于上面的目标 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
Run Code Online (Sandbox Code Playgroud)
显然,如果该属性已经包含您想要保留的数据,replace则将整个.status属性使用ing{}并不是一个好主意。
在这种情况下,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"
}
}
Run Code Online (Sandbox Code Playgroud)
或者,或者,使用kubectl:
$ kubectl patch mycrd.example.com test --type=merge \
-p '{"status": {"foo": "bar"}}'
mycrd.example.com/test patched
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5255 次 |
| 最近记录: |