Free — no signup required

Status Updates: Communicating with Users

2 min read

Spec vs. Status: A Strict Division of Responsibility

Every Kubernetes resource has two distinct sections that serve opposite purposes:

Spec is the user's declaration of desired state. The user writes it. Your controller reads from it. Think of it as the order placed at a restaurant.

Status is the system's report of actual state. Your controller writes it. Users and other tools read from it. Think of it as the kitchen's status board showing which orders are being prepared.

This division is not just a convention — it is enforced by the Kubernetes API through subresources. When you enable the status subresource on your CRD (which Kubebuilder does by default), kubectl apply cannot modify the Status field, and r.Status().Update() cannot modify the Spec field. They are separate API endpoints.

Why this matters — the infinite loop trap:

If your controller updates the Spec, it generates a new watch event, which triggers a new reconcile, which might update the Spec again. This is an infinite loop. The Spec/Status separation prevents this: your controller only writes to Status, which does not trigger a reconcile (unless you explicitly watch Status changes, which you should not do for your own resources).

Updating Status correctly:

// After completing your reconcile actions:
myResource.Status.ReadyReplicas = currentReadyCount
myResource.Status.Phase = "Running"
myResource.Status.Conditions = []metav1.Condition{
    {
        Type:               "Available",
        Status:             metav1.ConditionTrue,
        Reason:             "DeploymentReady",
        Message:            "All replicas are ready",
        LastTransitionTime: metav1.Now(),
    },
}

if err := r.Status().Update(ctx, &myResource); err != nil {
    return ctrl.Result{}, err
}

Conditions are the standard way to communicate multi-dimensional status. Rather than a single phase: Running string, conditions let you express multiple independent aspects of health simultaneously: Available: True, Progressing: False, Degraded: False. This is the same pattern used by Deployments, Nodes, and every other core Kubernetes resource.

This is one of 18 chapters

Every chapter is free — Kubernetes, Terraform, SRE, distributed systems, and more — with fast daily review built in.

Sign up free