Photo of the Kubernetes logo showing on a smartphone
Piotr Swat/

Annotations, labels, and selectors are used to manage metadata attached to your Kubernetes objects. Annotations and labels define the data while selectors provide a way to query it.

Here are the differences between the three concepts, what they’re designed for, and how you can use them to manage your resources.


The Kubernetes documentation defines annotations as “arbitrary non-identifying metadata” which you add to your objects. Their status as “non-identifying” means they aren’t used internally by Kubernetes as part of its object selection system.

This means annotations are best used for data that’s independent of the object and its role in your cluster. You could use them to add information about the tool that created an object, define who’s responsible for its management, or add tags to be picked up by external tools.

There’s no restrictions on what you use annotations for. As long as your data can be expressed as a key-value pair, you can create an annotation that encapsulates it. The model lets you store useful data directly alongside your objects, instead of having to refer to external documentation or databases.

Setting Annotations

Annotations are defined as part of a resource’s metadata field. They’re simple key-value pairs. The key needs to be 63 characters or less and can include alphanumeric characters, dashes, underscores, and dots. It must start and end with an alphanumeric character.

Keys also support an optional prefix which must be a valid DNS subdomain. Prefixes are used to namespace your annotation keys, avoiding collisions between common annotations like name and version. When a prefix is used, a slash character separates it from the key.

apiVersion: v1
kind: Pod
  name: pod-with-annotations
    unprefixed-annotation: "value" "another value"
  # <omitted>

This example demonstrates both prefixed and unprefixed annotations.

You can retrieve the annotations that have been set on an object using Kubectl. There’s no built-in command so you need to get the JSON or YAML definition of the object, then extract the value of the annotations field. Here’s an example that displays the annotations associated with the Pod shown above:

kubectl get pod pod-with-annotations -o jsonpath='{.metadata.annotations}'

image of getting annotations with Kubectl


Labels are another form of metadata which you can attach to your resources. The documentation describes the role of labels as “identifying attributes of objects that are meaningful and relevant to users” but independent of the properties of the core system.

Whereas annotations are intentionally purposeless, capable of representing any arbitrary data, labels are meant for more formal situations. They’re commonly used to represent processes and organizational structures. You might use labels to denote a resource’s release status (such as beta or stable) or the development stage it maps to (build or qa).

Labels can be used as selectors when referencing objects. This is a key difference compared to annotations which aren’t supported as selectors. Here’s a Pod which selects Nodes that have the node-environment: production label:

apiVersion: v1
kind: Pod
  name: pod-with-node-selector
    # <omitted>
    node-environment: production

Setting Labels

Labels are attached to objects in the same way as annotations. Add a labels field to the object’s metadata, then populate it with key-value pairs. Labels possess the same constraints around key names and prefixes.

apiVersion: v1
kind: Pod
  name: pod-with-labels
  labels: stable
  # <omitted>

You can retrieve an object’s labels using Kubectl with the same technique as shown earlier. Get the object’s JSON representation, then extract the labels field:

kubectl get pod pod-with-labels -o jsonpath='{.metadata.labels}'

Kubectl also supports a --show-labels flag to include labels in human-readable output tables:

kubectl get pods --show-labels

image of getting labels with Kubectl


Selectors are used within Kubernetes object definitions to reference other objects. Different types of selectors are available to pull in objects that possess certain characteristics.

In the example above, we used a selector to identify Nodes with a particular label. Here’s a Deployment object that uses an explicit label selector to identify the Pods it should manage:

apiVersion: apps/v1
kind: Deployment
  name: deployment
    matchLabels: selectors-demo
  replicas: 3
      labels: selectors-demo
      # <omitted>

The Deployment’s template will create Pods that have the label set. These will be matched by the selector so they become part of the Deployment.

Selectors in Kubectl

You can use a form of selector to filter the objects that are returned by Kubectl:

kubectl get pods -l

Label-based queries support several kinds of comparison operator. These include equality-based and set-based comparisons:

  • = – The label value is equal to a given value.
  • == – The label value is strictly equal to a given value.
  • != – The label value is not equal to a given value.
  • in – The label value is one of a set of given values.
  • notin – The label value is not in a set of given values.
  • exists – The label exists on the object.

Here’s an example of using the in operator to query objects that are in the staging or production environments:

kubectl get pods -l "environment in (dev, production)"


Annotations and Labels are two ways to add metadata to your Kubernetes objects. Annotations are for non-identifying data that won’t be referenced by Kubernetes. Labels are used to identify objects so that they can be selected by other Kubernetes resources.

It’s best to use an annotation if you won’t be querying for objects with the key-value pair. Use a label if you’ll be referencing it within another resource or using it to filter Kubectl output in your terminal.

When working with labels, several forms of selector are available to help you access the data you need. Annotations are a little trickier to access as they’re not meant to be queried but you can still list them by viewing the JSON representation of a Kubernetes object.

Profile Photo for James Walker James Walker
James Walker is a contributor to How-To Geek DevOps. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes.
Read Full Bio »