--- layout: blog title: 'Using Finalizers to Control Deletion' date: 2021-05-14 slug: using-finalizers-to-control-deletion --- **Authors:** Aaron Alpar (Kasten) Deleting objects in Kubernetes can be challenging. You may think you’ve deleted something, only to find it still persists. While issuing a `kubectl delete` command and hoping for the best might work for day-to-day operations, understanding how Kubernetes `delete` commands operate will help you understand why some objects linger after deletion. In this post, I’ll look at: - What properties of a resource govern deletion - How finalizers and owner references impact object deletion - How the propagation policy can be used to change the order of deletions - How deletion works, with examples For simplicity, all examples will use ConfigMaps and basic shell commands to demonstrate the process. We’ll explore how the commands work and discuss repercussions and results from using them in practice. ## The basic `delete` Kubernetes has several different commands you can use that allow you to create, read, update, and delete objects. For the purpose of this blog post, we’ll focus on four `kubectl` commands: `create`, `get`, `patch`, and `delete`. Here are examples of the basic `kubectl delete` command: ``` kubectl create configmap mymap configmap/mymap created ``` ``` kubectl get configmap/mymap NAME DATA AGE mymap 0 12s ``` ``` kubectl delete configmap/mymap configmap "mymap" deleted ``` ``` kubectl get configmap/mymap Error from server (NotFound): configmaps "mymap" not found ``` Shell commands preceded by `$` are followed by their output. You can see that we begin with a `kubectl create configmap mymap`, which will create the empty configmap `mymap`. Next, we need to `get` the configmap to prove it exists. We can then delete that configmap. Attempting to `get` it again produces an HTTP 404 error, which means the configmap is not found. The state diagram for the basic `delete` command is very simple: {{
}} Although this operation is straightforward, other factors may interfere with the deletion, including finalizers and owner references. ## Understanding Finalizers When it comes to understanding resource deletion in Kubernetes, knowledge of how finalizers work is helpful and can help you understand why some objects don’t get deleted. Finalizers are keys on resources that signal pre-delete operations. They control the garbage collection on resources, and are designed to alert controllers what cleanup operations to perform prior to removing a resource. However, they don’t necessarily name code that should be executed; finalizers on resources are basically just lists of keys much like annotations. Like annotations, they can be manipulated. Some common finalizers you’ve likely encountered are: - `kubernetes.io/pv-protection` - `kubernetes.io/pvc-protection` The finalizers above are used on volumes to prevent accidental deletion. Similarly, some finalizers can be used to prevent deletion of any resource but are not managed by any controller. Below with a custom configmap, which has no properties but contains a finalizer: ``` cat <}} So, if you attempt to delete an object that has a finalizer on it, it will remain in finalization until the controller has removed the finalizer keys or the finalizers are removed using Kubectl. Once that finalizer list is empty, the object can actually be reclaimed by Kubernetes and put into a queue to be deleted from the registry. ## Owner References Owner references describe how groups of objects are related. They are properties on resources that specify the relationship to one another, so entire trees of resources can be deleted. Finalizer rules are processed when there are owner references. An owner reference consists of a name and a UID. Owner references link resources within the same namespace, and it also needs a UID for that reference to work. Pods typically have owner references to the owning replica set. So, when deployments or stateful sets are deleted, then the child replica sets and pods are deleted in the process. Here are some examples of owner references and how they work. In the first example, we create a parent object first, then the child. The result is a very simple configmap that contains an owner reference to its parent: ``` cat <}}