3

我试图了解 Kubernetes 的行为,因为它与自定义资源及其子资源有关——特别是status子资源。

具体来说,我想在status不修改父自定义资源的情况下更新子资源。

据我所知,这应该是可能的。我已经查看了文档 [此处][1],但我似乎无法让它按预期工作。

我正在使用 Docker Desktop 的Kubernetes1.19.3进行测试。

这是场景...

  1. 创建这个简单的 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
  1. 创建演示资源:
apiVersion: k8s.test.io/v1alpha1
kind: Greeting
metadata:
  name: demo
spec:
  message: Hi there!
  1. 启动代理:
kubectl proxy &
  1. 建立对自定义资源的监视:
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!"}}}
  1. PATCH/status资源
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}}}

为什么要修改父资源?

如果我们检查资源,我们可以看到子资源status的资源肯定已更新:

$ 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}}'

¯\ (ツ)

4

1 回答 1

4

status子资源实际上并不是一个不同的对象。它只是一个单独的 API 路径,只能修改对象中的顶级status:块。这很有用,因为您可以为控制器设置 RBAC 策略以允许对整个对象进行读取访问,但只允许写入对象的状态。

特别是,您在最后一个命令中看到了这一点。如果你kubectl get grt demo -o yaml,扩展的 YAML 语法将包括status:子块。更新状态的控制器将导致status:.

于 2020-12-10T12:11:03.460 回答