CertGrid CertGrid
Concepts·Kubernetes and Cloud Native Associate

Owner References and the Controller Chain

Two numbers tell you whether a controller has caught up with your change, and one field explains why deleting a Pod does not help. The chain runs Deployment to ReplicaSet to Pod, and it is visible in the object itself.

Kubernetes Fundamentals Guide 4 of 46 Beginner

Written against the versions above. The API model here has been stable since 1.0. Verbosity flag output format changes between kubectl releases.

Any cluster works for this. Nothing here changes state except one annotation.
Server NameIP AddressOSRolesCPURAMHDD
CKA1001192.168.0.175Ubuntu 26.04 LTSControl Plane Node2 Core4 GB50 GB
CKA1001-NODE01192.168.0.176Ubuntu 26.04 LTSWorker Node2 Core4 GB50 GB

Before you start

  1. The two numbers that mean "caught up"

    generation        1
    observedGeneration 1

    metadata.generation increments each time the *spec* changes. status.observedGeneration is the generation the controller has finished acting on. Equal means the controller has seen your latest change.

    When they differ, the controller is behind - either mid-work or stuck. That is a far better signal than staring at Pod counts, because it distinguishes "still working" from "finished, and this is the result".

    Note that only spec changes bump generation. Annotating metadata, as the previous guide did, changes resourceVersion but not generation - because it asked the controller for nothing new.

    bash Example session
    kubectl --context cka1001 -n hpa-demo get deploy cpu-demo -o jsonpath='{.metadata.generation} {.status.observedGeneration}{"\n"}'1 1

    Expected resultTwo equal numbers.

    Success conditionYou can tell whether a controller has caught up with the spec.

  2. The chain, from the Pod upwards

    A Pod's ownerReferences names what created it:

    ReplicaSet/cpu-demo-7dd7d449d6

    Not the Deployment. The chain is Deployment -> ReplicaSet -> Pod, each link a separate controller doing one job: the Deployment controller manages ReplicaSets, the ReplicaSet controller manages Pods.

    That indirection is what makes rollouts work at all. A new revision is a *new ReplicaSet*, scaled up while the old one scales down - which is why rollback is fast and why the hash in the name matters.

    Two practical consequences. Deleting a Pod achieves nothing - the ReplicaSet recreates it, because its job is to maintain a count. And garbage collection follows these references: delete the Deployment and the ReplicaSet becomes an orphan whose owner is gone, so it is collected, and its Pods with it.

    bash Example session
    kubectl --context cka1001 -n hpa-demo get rs -l app=cpu-demo --no-headers | wc -l1kubectl --context cka1001 -n hpa-demo get pod -l app=cpu-demo -o jsonpath='{.items[0].metadata.ownerReferences[0].kind}/{.items[0].metadata.ownerReferences[0].name}{"\n"}'ReplicaSet/cpu-demo-7dd7d449d6

    Expected resultOne ReplicaSet, and a Pod owned by it rather than by the Deployment.

    Success conditionYou can name the object that owns a given Pod.

Troubleshooting

Official sources