Kubernetes labels, selectors & annotations with examples

Kubernetes provides two basic ways to document your infrastructure—labels and annotations. We have used labels in some of the examples in previous articles, but here I will explain the usage of labels and other related terminologies.

 

Labels

  • Labels give us another level of categorization, which becomes very helpful in terms of everyday operations and management.
  • Labels are attached to Kubernetes objects and are simple key: value pairs.
  • You will see them on pods, replication controllers, replica sets, services, and so on.
  • Labels themselves and the keys/values inside of them are based on a constrained set of variables, so that queries against them can be evaluated efficiently using optimized algorithms and data structures.
  • Labels are used for organization and selection of subsets of objects, and can be added to objects at creation time and/or modified at any time during cluster operations.

Let’s use an easy example to demonstrate. Suppose you wanted to identify a pod as being part of the front-end tier of your application. You might create a label named tier and assign it a value of frontend—like so:

Advertisement
“labels”: {
“tier”: “frontend”
}

The text “tier” is the key, and the text “frontend” is the value.

 

Selectors

Labels are queryable — which makes them especially useful in organizing things. The mechanism for this query is a label selector. A label selector is a string that identifies which labels you are trying to match. There are currently two types of selectors: equality-based and set-based selectors.

 

Equality-based selector

An equality-based test is just a “IS/IS NOT” test. For example:

tier = frontend

will return all pods that have a label with the key “tier” and the value “frontend”. On the other hand, if we wanted to get all the pods that were not in the frontend tier, we would say:

tier != frontend

You can also combine requirements with commas like so:

tier != frontend, game = super-shooter-2

This would return all pods that were part of the game named super-shooter-2 but were not in its frontend tier.

Advertisement

 

Set-based selectors

Set-based tests, on the other hand, are of the “IN/NOT IN” variety. For example:

environment in (production, qa)
tier notin (frontend, backend)
partition

The first test returns pods that have the environment label and a value of either production or qa. The next test returns all the pods not in the frontend or backend tiers. Finally, the third test will return all pods that have the partition label—no matter what value it contains.

Like equality-based tests, these can also be combined with commas to perform an AND operation like so:

environment in (production, qa), tier notin (frontend, backend), partition

This test returns all pods that are in either the production or qa environment, also not in either the frontend or backend tiers, and have a partition label of some kind.

 

Annotations

Annotations are bits of useful information you might want to store about a pod (or cluster, node, etc.) that you will not have to query against. They are also key/value pairs and have the same rules as labels.

Examples of things you might put there are the pager contact, the build date, or a pointer to more information someplace else—like a URL.

Labels are used to store identifying information about a thing that you might need to query against. Annotations are used to store other arbitrary information that would be handy to have close but won’t need to be filtered or searched.

 

Assigning a label to a Deployment

Method-1: Assign labels while creating a new object

It is always a good idea to use YAML template from any of the existing resource object. Since we plan to create a deployment, I can use a YAML template from any of the existing template but if you don't have any existing template then you can create one using --dry-run and export the template into another YAML file:

Advertisement
[root@controller ~]# kubectl create deployment label-nginx-example --image=nginx --dry-run=client -o yaml > label-nginx-example.yml

So we now have a template file for a new deployment with following content:

[root@controller ~]# cat label-nginx-example.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: label-nginx-example
  name: label-nginx-example
spec:
  replicas: 1
  selector:
    matchLabels:
      app: label-nginx-example
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: label-nginx-example
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}

We can perform clean up in this file and remove some unwanted content. You can see that by default kubectl has created and assigned a label app: label-nginx-example, I will replace that and assign a new label to our deployment as app: prod.

[root@controller ~]# cat label-nginx-example.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: prod
  name: label-nginx-example
spec:
  replicas: 2
  selector:
    matchLabels:
      app: prod
  template:
    metadata:
      labels:
        app: prod
    spec:
      containers:
      - image: nginx
        name: nginx

Next let us create a new deployment:

[root@controller ~]# kubectl create -f label-nginx-example.yml
deployment.apps/label-nginx-example created

List the available deployments with their labels:

[root@controller ~]# kubectl get deployments --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE     LABELS
label-nginx-example   2/2     2            2           3m12s   app=prod
nginx-deploy          2/2     2            2           22h     type=dev

List the available pods with their labels:

[root@controller ~]# kubectl get pods --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE     LABELS
label-nginx-example-5c57d87787-qjmhw   1/1     Running   0          4m36s   app=prod,pod-template-hash=5c57d87787
label-nginx-example-5c57d87787-vsjv5   1/1     Running   0          4m36s   app=prod,pod-template-hash=5c57d87787
nginx-deploy-d98cc8bdb-48ppw           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev
nginx-deploy-d98cc8bdb-nvcb5           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev

 

Method-2: Assign a new label to existing pod runtime as a patch

In this example we will assign new label "tier: frontend" to our existing Pods from the deployment label-nginx-example which we created in the previous example. To achieve this we need to create a spec file with the required properties:

[root@controller ~]# cat update-label.yml
spec:
  template:
    metadata:
      labels:
        tier: frontend

Next patch the deployment with this YAML file:

[root@controller ~]# kubectl patch deployment label-nginx-example --patch "$(cat update-label.yml)"
deployment.apps/label-nginx-example patched

Now you can use kubectl describe to check if our label was applied to the deployment:

Advertisement
[root@controller ~]# kubectl describe deployment label-nginx-example
Name:                   label-nginx-example
Namespace:              default
CreationTimestamp:      Thu, 03 Dec 2020 11:35:15 +0530
Labels:                 app=prod
Annotations:            deployment.kubernetes.io/revision: 2
Selector:               app=prod
Replicas:               2 desired | 2 updated | 2 total | 2 available | 0 unavailable
StrategyType:           RollingUpdate
MinReadySeconds:        0
RollingUpdateStrategy:  25% max unavailable, 25% max surge
Pod Template:
  Labels:  app=prod
           tier=frontend
...

This would apply the label to the Pod:

[root@controller ~]# kubectl get pods --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE     LABELS
label-nginx-example-79fdbb7d49-sd82d   1/1     Running   0          8m26s   app=prod,pod-template-hash=79fdbb7d49,tier=frontend
label-nginx-example-79fdbb7d49-wf2c4   1/1     Running   0          8m18s   app=prod,pod-template-hash=79fdbb7d49,tier=frontend
nginx-deploy-d98cc8bdb-48ppw           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev
nginx-deploy-d98cc8bdb-nvcb5           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev

 

Method-3: Assign a new label to existing deployments runtime using kubectl

In this example we can assign a new label runtime using kubectl command to our deployment. I have another deployment nginx-deploy on my cluster, so I will assign label tier: backend to this deployment:

[root@controller ~]# kubectl label deployment nginx-deploy tier=backend
deployment.apps/nginx-deploy labeled

Verify if the label was applied successfully:

[root@controller ~]# kubectl get deployments --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
label-nginx-example   2/2     2            2           14m   app=prod
nginx-deploy          2/2     2            2           22h   tier=backend,type=dev

 

Using labels to list resource objects

Now I have already used some of these commands in previous example but let me summarise all here again for your reference.

To list all the pods with their label details:

[root@controller ~]# kubectl get pods --show-labels
NAME                                   READY   STATUS    RESTARTS   AGE     LABELS
label-nginx-example-79fdbb7d49-sd82d   1/1     Running   0          8m26s   app=prod,pod-template-hash=79fdbb7d49,tier=frontend
label-nginx-example-79fdbb7d49-wf2c4   1/1     Running   0          8m18s   app=prod,pod-template-hash=79fdbb7d49,tier=frontend
nginx-deploy-d98cc8bdb-48ppw           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev
nginx-deploy-d98cc8bdb-nvcb5           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev

To list all the deployments with their label details:

[root@controller ~]# kubectl get deployments --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
label-nginx-example   2/2     2            2           19m   app=prod
nginx-deploy          2/2     2            2           22h   tier=backend,type=dev

To list all resources with assigned labels:

[root@controller ~]# kubectl get all --show-labels
NAME                                       READY   STATUS    RESTARTS   AGE     LABELS
pod/label-nginx-example-79fdbb7d49-sd82d   1/1     Running   0          9m8s    app=prod,pod-template-hash=79fdbb7d49,tier=frontend
pod/label-nginx-example-79fdbb7d49-wf2c4   1/1     Running   0          9m      app=prod,pod-template-hash=79fdbb7d49,tier=frontend
pod/nginx-deploy-d98cc8bdb-48ppw           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev
pod/nginx-deploy-d98cc8bdb-nvcb5           1/1     Running   1          22h     pod-template-hash=d98cc8bdb,type=dev

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE     LABELS
service/kubernetes   ClusterIP   10.96.0.1            443/TCP   5d12h   component=apiserver,provider=kubernetes

NAME                                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
deployment.apps/label-nginx-example   2/2     2            2           19m   app=prod
deployment.apps/nginx-deploy          2/2     2            2           22h   tier=backend,type=dev

NAME                                             DESIRED   CURRENT   READY   AGE    LABELS
replicaset.apps/label-nginx-example-5c57d87787   0         0         0       19m    app=prod,pod-template-hash=5c57d87787
replicaset.apps/label-nginx-example-79fdbb7d49   2         2         2       9m8s   app=prod,pod-template-hash=79fdbb7d49,tier=frontend
replicaset.apps/nginx-deploy-d98cc8bdb           2         2         2       22h    pod-template-hash=d98cc8bdb,type=dev

To list all the deployments using type: dev label:

[root@controller ~]# kubectl get deployments -l type=dev
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   2/2     2            2           22h

To list all the pods using app: prod label:

[root@controller ~]# kubectl get pods -l app=prod
NAME                                   READY   STATUS    RESTARTS   AGE
label-nginx-example-79fdbb7d49-sd82d   1/1     Running   0          12m
label-nginx-example-79fdbb7d49-wf2c4   1/1     Running   0          12m

 

Using selector to list resource objects

In this section we will use selectors to list the deployments and pods. The pod's selector determines where the ReplicaSet is running, so in our examples we have defined selector when creating a deployment.

But to demonstrate, I will create another deployment here with two labels and use one of the label as selector:

[root@controller ~]# cat lab-nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: dev
    tier: backend
  name: lab-nginx
spec:
  replicas: 2
  selector:
    matchLabels:
      app: dev
  template:
    metadata:
      labels:
        app: dev
    spec:
      containers:
      - image: nginx
        name: nginx

Now we will create this deployment:

[root@controller ~]# kubectl create -f lab-nginx.yml
deployment.apps/lab-nginx created

List the applied labels to the newly created pods and deployment:

[root@controller ~]# kubectl get pods --show-labels
NAME                                   READY   STATUS              RESTARTS   AGE     LABELS
lab-nginx-58f9bf94f7-df24l             0/1     ContainerCreating   0          34s     app=dev,pod-template-hash=58f9bf94f7
lab-nginx-58f9bf94f7-pc8zf             1/1     Running             0          34s     app=dev,pod-template-hash=58f9bf94f7
label-nginx-example-79fdbb7d49-sd82d   1/1     Running             0          52m     app=prod,pod-template-hash=79fdbb7d49,tier=frontend
label-nginx-example-79fdbb7d49-wf2c4   1/1     Running             0          52m     app=prod,pod-template-hash=79fdbb7d49,tier=frontend
nginx-deploy-d98cc8bdb-48ppw           1/1     Running             1          23h     pod-template-hash=d98cc8bdb,type=dev
nginx-deploy-d98cc8bdb-nvcb5           1/1     Running             1          23h     pod-template-hash=d98cc8bdb,type=dev

[root@controller ~]# kubectl get deployments --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE   LABELS
lab-nginx             0/2     2            0           15s   app=dev,tier=backend
label-nginx-example   2/2     2            2           62m   app=prod
nginx-deploy          2/2     2            2           23h   tier=backend,type=dev

So, all the pods from our lab-nginx deployment has two labels but is using app=dev as the selector so we can use this to filter the list of pods:

[root@controller ~]# kubectl get pods --selector "app=dev"
NAME                         READY   STATUS    RESTARTS   AGE
lab-nginx-58f9bf94f7-df24l   1/1     Running   0          18m
lab-nginx-58f9bf94f7-pc8zf   1/1     Running   0          18m

But will we get any output if we use tier: backend as the selector:

[root@controller ~]# kubectl get pods --selector "tier=backend"
No resources found in default namespace.

No resources found as we are using app=dev as our selector for the pods part of lab-nginx deployment.

To list all the deployments with selector app: prod

[root@controller ~]# kubectl get deployments --selector "app=prod"
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
label-nginx-example   2/2     2            2           32m

In the last example we used equality-based selector to filter the available deployments, now we will use set-based selector:

[root@controller ~]# kubectl get deployments --selector "app in (prod, dev)"
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE
lab-nginx             2/2     2            2           21m
label-nginx-example   2/2     2            2           83m

 

Removing labels

We can also remove a label from a resource object using following syntax:

]# kubectl label <resource-type> <resource> <label-key>-

For example to remove label app: dev from pods created by lab-nginx deployment:

[root@controller ~]# kubectl label pod lab-nginx-58f9bf94f7-pc8zf app-
pod/lab-nginx-58f9bf94f7-pc8zf labeled

As soon as we remove the selector label from the Pod, replicaset will create another Pod to fulfil the replica requirement of the deployment. Since lab-nginx expects two replica pods with label app=dev, another one will be created as soon as we remove label from existing Pod:

[root@controller ~]# kubectl get pods --show-labels
NAME                                   READY   STATUS              RESTARTS   AGE    LABELS
lab-nginx-58f9bf94f7-df24l             1/1     Running             0          106m   app=dev,pod-template-hash=58f9bf94f7
lab-nginx-58f9bf94f7-fbkc2             0/1     ContainerCreating   0          3s     app=dev,pod-template-hash=58f9bf94f7
lab-nginx-58f9bf94f7-pc8zf             1/1     Running             0          106m   pod-template-hash=58f9bf94f7
...

So as expected, you can see that as soon as I removed the app label from exiting lab-nginx Pod, a new one is getting created.

Similarly, we can also remove label from a deployment:

[root@controller ~]# kubectl get deployments --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE    LABELS
lab-nginx             2/2     2            2           107m   app=dev,tier=backend
label-nginx-example   2/2     2            2           169m   app=prod
nginx-deploy          2/2     2            2           25h    tier=backend,type=dev

Now we remove app label from this deployment:

[root@controller ~]# kubectl label deployment lab-nginx app-
deployment.apps/lab-nginx labeled

Verify the available set of label of your deployment:

[root@controller ~]# kubectl get deployments --show-labels
NAME                  READY   UP-TO-DATE   AVAILABLE   AGE    LABELS
lab-nginx             2/2     2            2           107m   tier=backend
label-nginx-example   2/2     2            2           170m   app=prod
nginx-deploy          2/2     2            2           25h    tier=backend,type=dev

 

Conclusion

In this Kubernetes Tutorial we learned about the usage of labels, selector and annotation using different examples. To summarise, labels and annotation help you organize the Pods once your cluster size grows in size and scope. These are mostly used with replication controllers and replica sets in a deployment. You also learned that we can assign/modify/remove labels from different Kubernetes resource runtime.

Didn't find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

Buy GoLinuxCloud a Coffee

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Leave a Comment