Skip to content

Instantly share code, notes, and snippets.

@erdii
Last active September 20, 2023 08:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erdii/04d967f98f5892182e988a38f0ee8182 to your computer and use it in GitHub Desktop.
Save erdii/04d967f98f5892182e988a38f0ee8182 to your computer and use it in GitHub Desktop.
Control Flows in Kubernetes: Orphaning deletion of an object with a finalizer.

TL;DR the orphan finalizer only ensures that children become orphans. Depending on the orphan finalizer being present during deletion/teardown is racy when there are other finalizers on the same object.

Orphaning deletion adds the orphan finalizer during deletion to ensure that all ownerReferences pointing to this object will be removed BEFORE the object gets deleted.
After all children had their ownerReferences removed, the orphan finalizer gets removed to unblock deletion of the parent object. This means that if the parent has another finalizer and someone watches the parent they:

  • Will probably see the orphan finalizer being added on deletion and then removed again afterwards.
  • Are not guaranteed to see the orphan finalizer on the deleted object at all.

An illustrated example:

  1. create parent configmap: kubectl apply -f parent.yaml
  2. get parent uid: kubectl get configmap parent -o jsonpath='{.metadata.uid}'
  3. paste parent uid into child manifest at .metadata.ownerReferences[0].uid
  4. create child configmap: kubectl apply -f child.yaml
  5. get and watch all configmaps: kubectl get -w -o yaml
  6. you should see both configmap object manifests and the child should have an owner reference to the parent.
    parent: image child: image
  7. keep the watch from Step 5 open and delete the parent with cascade=orphan: kubectl delete configmap parent --cascade=orphan
  8. now the watch will show us what happens over time:
  9. the deletion sets the deletionTimestamp and adds the orphan finalizer to the parent: image
  10. next, kubernetes removes the ownerReference from the child object: image
  11. And finally, now that all children have been orphaned and will not be garbage-collected when the parent actually gets deleted, it will remove the orphan finalizer from the parent to unblock its deletion. image

Links:

apiVersion: v1
kind: ConfigMap
metadata:
name: child
ownerReferences:
- apiVersion: v1
blockOwnerDeletion: true
controller: true
kind: ConfigMap
name: parent
uid: TODO - replace with parent UID
data: {}
apiVersion: v1
kind: ConfigMap
metadata:
name: parent
# Let's add a finalizer
# so that the parent does not get fully deleted after the orphaning has happened.
finalizers:
- k8s.erdii.net/a-blocking-finalizer
data: {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment