Status Subresource

By convention, the Kubernetes API makes a distinction between the specificationof the desired state of an object (a nested object field called "spec") and the status of the object at the current time (a nested object field called "status"). The specification is a complete description of the desired state, including configuration settings provided by the user, default values expanded by the system, and properties initialized or otherwise changed after creation by other ecosystem components (e.g., schedulers, auto-scalers), and is persisted in Etcd with the API object. The status summarizes the current state of the object in the system, and is usually persisted with the object by an automated processes but may be generated on the fly. At some cost and perhaps some temporary degradation in behavior, the status could be reconstructed by observation if it were lost.

The PUT and POST verbs on objects MUST ignore the "status" values, to avoid accidentally overwriting the status in read-modify-write scenarios. A /status subresource MUST be provided to enable system components to update statuses of resources they manage.

You can read more about the API convention in Kubernetes API Conventiondoc.

Status subresource support in Kubernetes

Subresource support for CRD is enabled by default in 1.10+ releases, so ensure that you are running kubernetes with the minimum version. You canuse kubectl version command to check the Kubernetes version.

Enabling Status subresource in CRD definition

First step is to enable status subresource in the CRD definition. This can beachieved by adding a comment // +kubebuilder:subresource:status just above theGo type definition as shown in example below.

  1. // MySQL is the Schema for the mysqls API
  2. // +k8s:openapi-gen=true
  3. // +kubebuilder:subresource:status
  4. type MySQL struct {
  5. metav1.TypeMeta `json:",inline"`
  6. metav1.ObjectMeta `json:"metadata,omitempty"`
  7. Spec MySQLSpec `json:"spec,omitempty"`
  8. Status MySQLStatus `json:"status,omitempty"`
  9. }

CRD generation tool will use the +kubebuilder:subresource:status annotation toenable status subresource in the CRD definition. So, if you run, make manifests,it will regenerate the CRD manifests under config/crds/<kind_types.yaml. Hereis an example manifests with status subresource enabled. Note the subresourcessection with an empty status field.

  1. apiVersion: apiextensions.k8s.io/v1beta1
  2. kind: CustomResourceDefinition
  3. metadata:
  4. creationTimestamp: null
  5. labels:
  6. controller-tools.k8s.io: "1.0"
  7. name: mysqls.myapps.examples.org
  8. spec:
  9. group: myapps.examples.org
  10. names:
  11. kind: MySQL
  12. plural: mysqls
  13. scope: Namespaced
  14. subresources:
  15. status: {}
  16. validation:
  17. openAPIV3Schema:
  18. properties:
  19. apiVersion:
  20. type: string
  21. kind:
  22. type: string
  23. metadata:
  24. type: object
  25. spec:
  26. type: object
  27. status:
  28. type: object
  29. version: v1
  30. status:
  31. acceptedNames:
  32. kind: ""
  33. plural: ""
  34. conditions: []
  35. storedVersions: []

Ensure you have updated the CRD definition in your cluster by running kubectlapply -f config/crds

Getting and Updating status in Reconciler code

In order to get the status subresource, you don't have do anything new. TheGet client method returns the entire object which contains the status field.

For updating the status subresource, compute the new status value and update it in the object and then issue client.Status().Update(context.Background(), &obj) to update thestatus.

  1. instance := &myappsv1.MySQL{}
  2. err := r.Get(context.TODO(), request.NamespacedName, instance)
  3. if err != nil {
  4. // handle err
  5. }
  6. // updating the status
  7. instance.Status.SomeField = "new-value"
  8. err = r.Status().Update(context.Background(), instance)
  9. if err != nil {
  10. return reconcile.Result{}, err
  11. }