Start your free 14-day ContainIQ trial

Using Kubectl Patch | Tutorial and Best Practices

June 24, 2022

With Kubernetes, sometimes you need to change the config of a running resource. kubectl patch can help you out, and this guide will teach you everything you need to know about it.

Cameron Pavey
Full Stack Developer

The kubectl command line utility offers a lot of functionality to users to help them manage their Kubernetes resources. One such command exposed by this utility is the <terminal inline>kubectl patch<terminal inline> command, which allows you to change running configurations immediately.

In this guide, you will see how you can use the <terminal inline>kubectl patch<terminal inline> command to manipulate your Kubernetes resources, and you’ll learn the different options presented to you by this command. You will then learn some best practices that you can follow to ensure that your usage of this command is as sustainable as possible.

Why Do You Need kubectl patch?

kubectl gives you several different ways to update running configurations. The main ways are the <terminal inline>apply<terminal inline>, <terminal inline>edit<terminal inline>, and <terminal inline>patch<terminal inline> commands. There are some nuances between each of these commands that will be touched on later, but the focus of this guide is on the <terminal inline>patch<terminal inline> command. If you need to update API objects in place, <terminal inline>kubectl patch<terminal inline> is one of the commands available to you that you will likely want to consider using.

The <terminal inline>patch<terminal inline> command lets you apply a change to your running configuration by specifying only the bit that you wish to change and then using one of three different patch types to apply this change. The three patch types each vary slightly in how they apply the change, and as such, each is suitable for different use cases. Applying small changes like this can be useful if you want to test configuration changes or perform some small experiments, but don’t want to update the whole configuration file. However, if you decide to keep the changes, it’s generally a good idea to codify these changes into your base configuration, as patches can become burdensome to maintain in the long run.

Introducing kubectl patch

The best way to learn how to use the <terminal inline>patch<terminal inline> command is by using it. If you want to follow along with the examples in this article, you will need a Kubernetes cluster to experiment with. You can either create one with a cloud provider such as GKE, or set up a local cluster using one of the various tools available to do so.

If you are using Mac or Windows, you can get a simple single-node cluster via Docker Desktop. If you are running a Linux-based OS, there are several options available to you, such as minikube and MicroK8s.

For the purposes of following along with this article, any type of Kubernetes cluster should be sufficient.

Using kubectl patch

To experiment with the <terminal inline>patch<terminal inline> command, you first need some resources to work with. The following configuration file will create a simple deployment with a single replica, which has a single pod:


# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: patch-demo
spec:
  replicas: 1
  selector:
    matchLabels:
    app: nginx
  template:
    metadata:
    labels:
        app: nginx
    spec:
    containers:
    - name: nginx-container
        image: nginx

To run this configuration from your terminal, execute the following command:


kubectl apply -f ./deployment.yaml

This will create your resources—the deployment and the pod—which you can verify by running <terminal inline>kubectl get pods<terminal inline>. That will give you the following response:

NAME READY STATUS RESTARTS AGE
patch-demo-d47fd7f66-84dc6 1/1 Running 0 4m27s

The first way to use <terminal inline>patch<terminal inline> is by running the command with your patch object inline. In this case, if you wanted to patch the deployment to have two replicas, it would look something like this:


kubectl patch deployment patch-demo -p '{"spec": {"replicas": 2}}'

If you run <terminal inline>kubectl get pods<terminal inline> again, you will see two replicas, where previously there was only one. This approach can be useful for small changes or cases where repeatability isn’t a key consideration. One very real use case for doing your patches inline is that sometimes when trying to delete a PersistentVolume, it will seemingly hang indefinitely. You can easily resolve this issue by running inline patches as follows:


kubectl patch pvc pvc_name -p '{"metadata":{"finalizers":null}}'
kubectl patch pv pv_name -p '{"metadata":{"finalizers":null}}'
kubectl patch pod pod_name -p '{"metadata":{"finalizers":null}}'

In many instances, however, it is a good idea to apply your patches from a patch file, which is a partial YAML file saved to your disk. If you were to do this with the above example of increasing the replicas in your deployment to two, you would first need to create a new file called something like <terminal inline>patch-file.yaml<terminal inline>, which would contain your patch object:


spec:
  replicas: 2

From the terminal, you can now patch your deployment by providing the file, instead of the object itself:


kubectl patch deployment patch-demo --patch-file patch-file.yaml

This ultimately has the same effect, but is more convenient than doing it all inline, especially for larger patch objects and things that you might want to iterate on.

K8s Metrics, Logging, and Tracing
Monitor the health of your cluster and troubleshoot issues faster with pre-built dashboards that just work.
Start Free Trial Book a Demo

Different Patch Types

A few different types of patch can be performed when applying configs with the <terminal inline>patch<terminal inline> command. In the above examples, kubectl uses the strategic merge type by default. The available types are:

  • <terminal inline bold>json<terminal inline bold>: A JSON patch allows you to provide an operation or operations to carry out on the object.
  • <terminal inline bold>json merge<terminal inline bold>: A JSON merge patch allows you to naively override keys in an object.
  • <terminal inline bold>strategic<terminal inline bold>: A strategic merge patch will either replace or merge values based on the object’s <terminal inline>patchStrategy<terminal inline> as defined in the Kubernetes source code. This is the default patch type.

You can change which type is used by specifying the <terminal inline>type<terminal inline> parameter when you call the <terminal inline>patch<terminal inline> command:


kubectl patch deployment patch-demo --type merge --patch-file patch-file.yaml

There are some important differences between each of the types. Notably, a JSON patch uses a slightly more complicated syntax, whereby you specify a sequence of atomic operations that are executed one after another. For the above example of setting the number of replicas, it might look something like this:


- op: replace
  path: "/spec/replicas"
  value: 2

The key difference with JSON patches is that instead of specifying a partial fragment of the config that you wish to combine with the existing config, you simply specify instructions to carry out. This type of patch is good for more granular operations, as you can specify each atomic change individually. You can also perform multiple operations together. If you wanted to add a Redis container to your pod, and a new corresponding label, you could perform a JSON patch with the following:


- op: add
  path: "/spec/template/spec/containers/1"
  value:
    name: redis-container
    image: redis
- op: add
  path: "/spec/template/metadata/labels/cache"
  value: redis

The conceptually simpler JSON merge patch is good for small replacement operations, but has some limitations. If you want to update a list, you need to specify the entire new list, not just new items. Additionally, you can delete a key by setting its value to null, but as a result, it is not possible to update a value to have a <terminal inline>null<terminal inline> literal value. Similar to the above example, if you wanted to add a Redis container and label using this patch strategy, it would look something like this:

Best Practices

When using the <terminal inline>patch<terminal inline> command, it’s easy to get carried away and potentially create a bit of a mess, where your running configs don’t match what you have on disk, and you aren’t sure what has changed. To avoid this kind of scenario, there are some best practices that you can follow to keep things nice and tidy.

Prefer Patch Files

Inline patching can be useful if you’re just trying something out, or if you are making a throwaway change that you don’t care about. When working with resources that you care about, though, it’s often wise to use patch files for a few reasons:

  • Keeping patch files can give you an idea of the changes that your resources have gone through without requiring you to inspect the running configuration.
  • There’s a chance that your patch might not be exactly right and could require some tweaks. In this case, updating and reapplying the patch file is more convenient than doing multiple inline patches.

Know When to Use kubectl patch

There are multiple different ways that you can update configurations in Kubernetes. In addition to <terminal inline>patch<terminal inline>, there is also <terminal inline>kubectl apply<terminal inline> and kubectl edit. Suppose you create and manage your resources using <terminal inline>apply<terminal inline>. In that case, it is generally a good idea to use this when updating your configurations, as <terminal inline>apply<terminal inline> keeps track of the previously applied configuration via annotation. This annotation is not updated by <terminal inline>patch<terminal inline>, so you miss some functionality there.

Use kubectl patch Sparingly

The <terminal inline>patch<terminal inline> command can be very useful for testing and experimentation. Still, even with patch files, it is generally a good idea to encode changes you’ll be keeping into your base config files. This is because when you recreate your resources by applying your config, your patches will not be automatically reapplied. This can be inconvenient, especially if you have multiple patches you need to apply. Reflecting changes you wish to keep in your base configs makes future maintainability much easier.

Final Thoughts

In this guide, you learned about the <terminal inline>kubectl patch<terminal inline> command: what it is, how to use it, and its different modes of operation.

The <terminal inline>patch<terminal inline> command is a useful tool to be familiar with, and can ease the debugging and experimentation process significantly. However, it’s important to know when to use it and whether there’s a better alternative available. kubectl gives you several options for updating configurations. They each have use cases where they’re most suitable, so while it’s important to be familiar with the <terminal inline>patch<terminal inline> command to use it effectively, it’s just as important to know when it is time to reach for a different tool.

Start your free 14-day ContainIQ trial
Start Free TrialBook a Demo
No card required
Cameron Pavey
Full Stack Developer

Cameron is a Full Stack Developer at Rexlabs, and before that was a Software Engineer at Catapult. He specializes in Laravel, React, and is also knowledgeable in DevOps. Cameron received a Bachelor of Information Technology from Queensland University of Technology. He is currently living and working in Melbourne, Australia.

READ MORE