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:
“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.
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:
[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:
[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.


