我正在试图理解Kubernetes在自定义资源及其子资源方面的行为,特别是status
子资源。
具体来说,我想更新status
子资源而不修改父级自定义资源。
据我所知,这应该是可能的。我已经查阅了文档[1],但似乎无法按照预期工作。
我正在使用 Docker Desktop 的Kubernetes 1.19.3
进行测试。
以下是场景...
- 创建此简单的CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: greetings.k8s.test.io
spec:
group: k8s.test.io
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
description: Greeting is the Schema for the Greetings Operator
type: object
properties:
message:
description: A friendly greeting
type: string
default: Hello World!
status:
type: object
properties:
ready:
description: The resource's readiness
type: boolean
additionalPrinterColumns:
- name: ready
type: boolean
description: Readiness of the created resource
jsonPath: .status.ready
subresources:
status: {}
scope: Namespaced
names:
plural: greetings
singular: greeting
kind: Greeting
shortNames:
- grt
- 创建演示资源:
apiVersion: k8s.test.io/v1alpha1
kind: Greeting
metadata:
name: demo
spec:
message: Hi there!
- 启动代理:
kubectl proxy &
- 建立自定义资源的监视器:
curl -L -s -X GET -H "Content-Type: application/json" \
-H "Accept: application/json, */*" \
127.0.0.1:8001/apis//k8s.test.io/v1alpha1/watch/namespaces/default/greetings
此时,您应该看到类似以下的输出:
{"type":"ADDED","object":{"apiVersion":"k8s.test.io/v1alpha1","kind":"Greeting","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"k8s.test.io/v1alpha1\",\"kind\":\"Greeting\",\"metadata\":{\"annotations\":{},\"name\":\"demo\",\"namespace\":\"default\"},\"spec\":{\"message\":\"Hi there!\"}}\n"},"creationTimestamp":"2020-12-10T04:02:55Z","generation":1,"managedFields":[{"apiVersion":"k8s.test.io/v1alpha1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}},"f:spec":{".":{},"f:message":{}}},"manager":"kubectl-client-side-apply","operation":"Update","time":"2020-12-10T04:02:55Z"}],"name":"demo","namespace":"default","resourceVersion":"532930","selfLink":"/apis/k8s.test.io/v1alpha1/namespaces/default/greetings/demo","uid":"40f3a618-74e5-4b14-9bd4-2eb47366d804"},"spec":{"message":"Hi there!"}}}
- 对
/status
子资源执行PATCH
操作
curl -k -s -X PATCH -H "Accept: application/json, */*" \
-H "Content-Type: application/merge-patch+json" \
127.0.0.1:8001/apis/k8s.test.io/v1alpha1/namespaces/default/greetings/demo/status \
--data '{"status":{"ready":true}}'
令人困惑的是,在提交PATCH
之后,我们对父资源的监视产生了...
{"type":"MODIFIED","object":{"apiVersion":"k8s.test.io/v1alpha1","kind":"Greeting","metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"k8s.test.io/v1alpha1\",\"kind\":\"Greeting\",\"metadata\":{\"annotations\":{},\"name\":\"demo\",\"namespace\":\"default\"},\"spec\":{\"message\":\"Hi there!\"}}\n"},"creationTimestamp":"2020-12-10T04:02:55Z","generation":1,"managedFields":[{"apiVersion":"k8s.test.io/v1alpha1","fieldsType":"FieldsV1","fieldsV1":{"f:metadata":{"f:annotations":{".":{},"f:kubectl.kubernetes.io/last-applied-configuration":{}}},"f:spec":{".":{},"f:message":{}}},"manager":"kubectl-client-side-apply","operation":"Update","time":"2020-12-10T04:02:55Z"},{"apiVersion":"k8s.test.io/v1alpha1","fieldsType":"FieldsV1","fieldsV1":{"f:status":{".":{},"f:ready":{}}},"manager":"curl","operation":"Update","time":"2020-12-10T04:05:22Z"}],"name":"demo","namespace":"default","resourceVersion":"533184","selfLink":"/apis/k8s.test.io/v1alpha1/namespaces/default/greetings/demo","uid":"40f3a618-74e5-4b14-9bd4-2eb47366d804"},"spec":{"message":"Hi there!"},"status":{"ready":true}}}
为什么要修改父资源?
如果我们检查资源,可以看到子资源的状态确实被更新了:
$ k get grt demo
NAME READY
demo true
我不知道这种行为是否符合预期,同时我对PATCH
方法论的理解是否有误。
希望有人能帮忙。谢谢。
更新:
除了PATCH
外,我还可以确认PUT
(虽然是一个更复杂的操作)也展现了完全相同的行为。示例:
curl -k -s -X PUT -H "Accept: application/json, */*" \
-H "Content-Type: application/json" \
127.0.0.1:8001/apis/k8s.test.io/v1alpha1/namespaces/default/greetings/demo/status \
--data '{"apiVersion":"k8s.test.io/v1alpha1","kind":"Greeting","metadata":{"name":"demo","resourceVersion":"533184"},"status":{"ready":false}}'
¯\(ツ)/¯
generation
字段,这个字段在对象的spec
子资源被修改时会更新。一个良好构建的操作员不应对与相关对象的generation
字段小于或等于已处理事件的字段(status
子资源中的observedGeneration
可以帮助解决此问题)的任何进一步事件做出反应。 - Adrien Ferrand