10.2 Organizing pods with labels

In this book, you will build and deploy the full Kiada application suite, which is composed of several services. So far, you’ve implemented the Kiada, the Quote service, and the Quiz service. These services run in three different pods. Accompanying the pods are other types of objects, like config maps, secrets, persistent volumes, and claims.

As you can imagine, the number of these objects will increase as the book progresses. Before things get out of hand, you need to start organizing these objects so that you and all the other users in your cluster can easily figure out which objects belong to which service.

In other systems that use a microservices architecture, the number of services can exceed 100 or more. Some of these services are replicated, which means that multiple copies of the same pod are deployed. Also, at certain points in time, multiple versions of a service are running simultaneously. This results in hundreds or even thousands of pods in the system.

Imagine you, too, start replicating and running multiple releases of the pods in your Kiada suite. For example, suppose you are running both the stable and canary release of the Kiada service.

DEFINITION  A canary release is a deployment pattern where you deploy a new version of an application alongside the stable version, and direct only a small portion of requests to the new version to see how it behaves before rolling it out to all users. This prevents a bad release from being made available to too many users.

You run three replicas of the stable Kiada version, and one canary instance. Similarly, you run three instances of the stable release of the Quote service, along with a canary release of the Quote service. You run a single, stable release of the Quiz service. All these pods are shown in the following figure.

Even with only nine pods in the system, the system diagram is challenging to understand. And it doesn’t even show any of the other API objects required by the pods. It’s obvious that you need to organize them into smaller groups. You could split these three services into three namespaces, but that’s not the real purpose of namespaces. A more appropriate mechanism for this case is object labels.

10.2.1 Introducing labels

Labels are an incredibly powerful yet simple feature for organizing Kubernetes API objects. A label is a key-value pair you attach to an object that allows any user of the cluster to identify the object’s role in the system. Both the key and the value are simple strings that you can specify as you wish. An object can have more than one label, but the label keys must be unique within that object. You normally add labels to objects when you create them, but you can also change an object’s labels later.

Using labels to provide additional information about an object

To illustrate the benefits of adding labels to objects, let’s take the pods shown in figure 10.4. These pods run three different services - the Kiada service, the Quote, and the Quiz service. The Kiada and Quote services are each divided into stable and canary releases. While it is true that you can tell which service and release type each pod belongs to by its name, that’s only because I made sure to name the pods that way. However, it’s not always practical to include all this information in the name of the object.

Instead, we can store this information in pod labels. Kubernetes does not care what labels you add to your objects. You can choose the keys and values however you want. In the case at hand, the following two labels make sense:

  • The “app” label indicates to which application the pod belongs.
  • The “rel” label indicates whether the pod is running the stable or canary release of the application.

As you can see in the following figure, the value of the “app” label is set to “kiada” in all three kiada-stable-xxx and the kiada-canary pod, since all these pods are running the Kiada application. The “rel” label differs between the pods running the stable release and the pod running the canary release.

The illustration shows only the kiada pods, but imagine adding the same two labels to the other pods as well. With these labels, users that come across these pods can easily tell what application and what kind of release is running in the pod.

Understanding how labels keep objects organized

The illustration shows only the kiada pods, but imagine adding the same two labels to the other pods as well. With these labels, users that come across these pods can easily tell what application and what kind of release is running in the pod.

This may seem abstract until you see how these labels make it easier to manage these pods with kubectl, so let’s get practical.

10.2.2 Attaching labels to pods

The book’s code archive contains an object manifest file with all the pods from the previous example. All the stable pods are already labelled, but the canary pods aren’t. You’ll label them manually.

Setting up the exercise

To get started, create a new namespace called kiada, switch to that namespace, and deploy the objects as follows. To create the namespace, run:

$ kubectl create namespace kiada
namespace/kiada created

To switch to the namespace, run:

$ kubectl config set-context --current --namespace kiada
Context "kind-kind" modified.

To deploy the pods and related objects, run:

1 $ kubectl apply -f many-pods.yaml
2 pod/kiada-stable-001 created
3 pod/kiada-stable-002 created
4 pod/kiada-stable-003 created
5 pod/kiada-canary created
6 configmap/kiada-envoy-config created
7 secret/kiada-tls created
8 pod/quote-stable-001 created
9 pod/quote-stable-002 created
10 pod/quote-stable-003 created
11 pod/quote-canary created
12 pod/quiz-stable created
13 persistentvolumeclaim/quiz-data created

As you can see, the manifest contains several objects of different kinds. Their labels will be crucial if you want to make sense of them.

Defining labels in object manifests

Examine the manifest file. At the top, you’ll see a pod named kiada-stable-001. In the metadata section, you’ll find the labels field with the labels app and rel, as shown in the following listing.

apiVersion: v1
kind: Pod
metadata:
  name: kiada-stable-001
  labels:
    app: kiada
    rel: stable
spec:
  ...

The listing shows how to add labels to an object definition. Labels are supported by all object kinds. Regardless of the kind, you add labels to the object in this way.

Displaying object labels

You can see the labels of a particular object by running the kubectl describe command. View the labels of the pod kiada-stable-001 as follows:

$ kubectl describe po kiada-stable-001
Name:         kiada-stable-001
Namespace:    kiada
Priority:     0
Node:         kind-worker2/172.18.0.2
Start Time:   Sun, 10 Oct 2021 21:58:25 +0200
Labels:       app=kiada
              rel=stable
Annotations:  <none>
...

The kubectl get pods command doesn’t display labels by default, but you can display them with the --show-labels option. Check the labels of all pods in the namespace as follows:

$ kubectl get po --show-labels
NAME               READY   STATUS    RESTARTS   AGE   LABELS
kiada-canary       2/2     Running   0          12m   <none>
kiada-stable-001   2/2     Running   0          12m   app=kiada,rel=stable
kiada-stable-002   2/2     Running   0          12m   app=kiada,rel=stable
kiada-stable-003   2/2     Running   0          12m   app=kiada,rel=stable
quiz-stable        2/2     Running   0          12m   app=quiz,rel=stable
quote-canary       2/2     Running   0          12m   <none>
quote-stable-001   2/2     Running   0          12m   app=quote,rel=stable
quote-stable-002   2/2     Running   0          12m   app=quote,rel=stable
quote-stable-003   2/2     Running   0          12m   app=quote,rel=stable

Instead of showing all labels with --show-labels, you can also show specific labels with the --label-columns option (or the shorter variant -L). Each label is displayed in its own column. List all pods along with their app and rel labels as follows:

$ kubectl get po -L app,rel
NAME               READY   STATUS    RESTARTS   AGE   APP     REL
kiada-canary       2/2     Running   0          14m
kiada-stable-001   2/2     Running   0          14m   kiada   stable
kiada-stable-002   2/2     Running   0          14m   kiada   stable
kiada-stable-003   2/2     Running   0          14m   kiada   stable
quiz-stable        2/2     Running   0          14m   quiz    stable
quote-canary       2/2     Running   0          14m
quote-stable-001   2/2     Running   0          14m   quote   stable
quote-stable-002   2/2     Running   0          14m   quote   stable
quote-stable-003   2/2     Running   0          14m   quote   stable

You can see that the two canary pods have no labels. Let’s add them.

Adding labels to an existing object

To add labels to an existing object, you can edit the object’s manifest file, add labels to the metadata section, and reapply the manifest using kubectl apply. You can also edit the object definition directly in the API using kubectl edit. However, the simplest method is to use the kubectl set label command.

Add the labels app and rel to the kiada-canary pod using the following command:

$ kubectl label pod kiada-canary app=kiada rel=canary
pod/kiada-canary labeled

Now do the same for the pod quote-canary:

$ kubectl label pod quote-canary app=kiada rel=canary
pod/quote-canary labeled

List the pods and display their labels to confirm that all pods are now labelled. If you didn’t notice the error when you entered the previous command, you probably caught it when you listed the pods. The app label of the pod quote-canary is set to the wrong value (kiada instead of quote). Let’s fix this.

Changing labels of an existing object

You can use the same command to update object labels. To change the label you set incorrectly, run the following command:

$ kubectl label pod quote-canary app=quote
error: 'app' already has a value (kiada), and --overwrite is false

To prevent accidentally changing the value of an existing label, you must explicitly tell kubectl to overwrite the label with --overwrite. Here’s the correct command:

$ kubectl label pod quote-canary app=quote --overwrite
pod/quote-canary labeled

List the pods again to check that all the labels are now correct.

Labelling all objects of a kind

Now imagine that you want to deploy another application suite in the same namespace. Before doing this, it is useful to add the suite label to all existing pods so that you can distinguish which pods belong to one suite and which belong to the other. Run the following command to add the label to all pods in the namespace:

$ kubectl label po --all suite=kiada-suite
pod/kiada-canary labeled
pod/kiada-stable-001 labeled
...
pod/quote-stable-003 labeled

List the pods again with the --show-labels or the -L suite option to confirm that all pods now contain this new label.

Removing a label from an object

Okay, I lied. You will not be setting up another application suite. Therefore, the suite label is redundant. To remove the label from an object, run the kubectl label command with a minus sign after the label key as follows:

$ kubectl label pod kiada-canary suite-
pod/kiada-canary labeled

To remove the label from all other pods, specify --all instead of the pod name:

$ kubectl label pod --all suite-
label "suite" not found.
pod/kiada-canary not labeled
pod/kiada-stable-001 labeled
...
pod/quote-stable-003 labeled

NOTE

If you set the label value to an empty string, the label key is not removed. To remove it, you must use the minus sign after the label key.

10.2.3 Label syntax rules

While you can label your objects however you like, there are some restrictions on both the label keys and the values.

Valid label keys

In the examples, you used the label keys app, rel, and suite. These keys have no prefix and are considered private to the user. Common label keys that Kubernetes itself applies or reads always start with a prefix. This also applies to labels used by Kubernetes components outside of the core, as well as other commonly accepted label keys.

An example of a prefixed label key used by Kubernetes is kubernetes.io/arch. You can find it on Node objects to identify the architecture type used by the node.

$ kubectl get node -L kubernetes.io/arch
NAME                 STATUS   ROLES                  AGE   VERSION   ARCH
kind-control-plane   Ready    control-plane,master   31d   v1.21.1   amd64
kind-worker          Ready    <none>                 31d   v1.21.1   amd64
kind-worker2         Ready    <none>                 31d   v1.21.1   amd64

The label prefixes kubernetes.io/ and k8s.io/ are reserved for Kubernetes components. If you want to use a prefix for your labels, use your organization’s domain name to avoid conflicts.

When choosing a key for your labels, some syntax restrictions apply to both the prefix and the name part. The following table provides examples of valid and invalid label keys.

Table 10.1 Examples of valid and invalid label keys

Valid label keys Invalid label keys
foo _foo
foo-bar_baz foo%bar*baz
example/foo /foo
example/FOO EXAMPLE/foo
example.com/foo example..com/foo
my_example.com/foo my@example.com/foo
example.com/foo-bar example.com/-foo-bar
my.example.com/foo a.very.long.prefix.over.253.characters/foo

The following syntax rules apply to the prefix:

  • Must be a DNS subdomain (must contain only lowercase alphanumeric characters, hyphens, underscores, and dots).
  • Must be no more than 253 characters long (not including the slash character).
  • Must end with a forward slash.

The prefix must be followed by the label name, which:

  • Must begin and end with an alphanumeric character.
  • May contain hyphens, underscores, and dots.
  • May contain uppercase letters.
  • May not be longer than 63 characters.

Valid label values

Remember that labels are used to add identifying information to your objects. As with label keys, there are certain rules you must follow for label values. For example, label values can’t contain spaces or special characters. The following table provides examples of valid and invalid label values.

Table 10.2 Examples of valid and invalid label values

Valid label values Invalid label values
foo _foo
foo-bar_baz foo%bar*baz
FOO value.longer.than.63.characters
(empty) value with spaces

A label value:

  • Must begin with an alphanumeric character if not empty.
  • May contain only alphanumeric characters, hyphens, underscores, and dots.
  • Must not contain spaces or other whitespace.
  • Must be no more than 63 characters long.
  • If you need to add values that don’t follow these rules, you can add them as annotations instead of labels. You’ll learn more about annotations later in this chapter.

10.2.4 Using standard label keys

While you can always choose your own label keys, there are some standard keys you should know. Some of these are used by Kubernetes itself to label system objects, while others have become common for use in user-created objects.

Well-known labels used by Kubernetes

Kubernetes doesn’t usually add labels to the objects you create. However, it does use various labels for system objects such as Nodes and PersistentVolumes, especially if the cluster is running in a cloud environment. The following table lists some well-known labels you might find on these objects.

Table 10.3 Well-known labels on Nodes and PersistentVolumes

Label key Example value Applied to Description
kubernetes.io/arch amd64 Node The architecture of the node.
kubernetes.io/os linux Node The operating system running on the node.
kubernetes.io/hostname worker-node2 Node The node’s hostname.
topology.kubernetes.io/ region eu-west3 Node PersistentVolume The region in which the node or persistent volume is located.
topology.kubernetes.io/ zone eu-west3-c Node PersistentVolume The zone in which the node or persistent volume is located.
node.kubernetes.io/ instance-type micro-1 Node The node instance type. Set when using cloud-provided infrastructure.

NOTE

You can also find some of these labels under the older prefix beta.kubernetes.io, in addition to kubernetes.io.

Cloud providers can provide additional labels for nodes and other objects. For example, Google Kubernetes Engine adds the labels cloud.google.com/gke-nodepool and cloud.google.com/gke-os-distribution to provide further information about each node. You can also find more standard labels on other objects.

The Kubernetes community has agreed on a set of standard labels that you can add to your objects so that other users and tools can understand them. The following table lists these standard labels.

Table 10.4 Recommended labels used in the Kubernetes community

Label Example Description
app.kubernetes.io/name quotes The name of the application. If the application consists of multiple components, this is the name of the entire application, not the individual components.
app.kubernetes.io/instance quotes-foo The name of this application instance. If you create multiple instances of the same application for different purposes, this label helps you distinguish between them.
app.kubernetes.io/component database The role that this component plays in the application architecture.
app.kubernetes.io/part-of kubia-demo The name of the application suite to which this application belongs.
app.kubernetes.io/version 1.0.0 The version of the application.
app.kubernetes.io/managed-by quotes-operator The tool that manages the deployment and update of this application.

All objects belonging to the same application instance should have the same set of labels. For example, the pod and the persistent volume claim used by that pod should have the same values for the labels listed in the previous table. This way, anyone using the Kubernetes cluster can see which components belong together and which do not. Also, you can manage these components using bulk operations by using label selectors, which are explained in the next section.

Copyrights © Wang Wei all right reserved

results matching ""

    No results matching ""