Setting Kubernetes Labels and Annotations

Helm chart is a popular method of packaging applications to be installed on the Kubernetes cluster. As Helm chart developers, we have to decide what configurations need to be made available to the customer and how should they be offered. In this article, we look at configuring labels and annotations. All Kubernetes objects should have a set of labels for external tools to identify and use them in a consistent manner. Specifying labels and annotations involves solving some key challenges.

  1. What are the labels that should be common to all Kubernetes objects?
  2. How to expose labels and annotations configuration parameters in values.yaml?
  3. We cannot say upfront what all the possible labels and annotation parameter names that a customer might want for application Pods.
  4. Allow customers to expose the services externally in the various ways that they might want.

Required Labels

The first challenge is to come up with a list of required labels. The official documentation provides a list of recommended labels. These labels are recommended for every object that we create and have a shared prefix:  app.kubernetes.io . Prefixes ensure that recommended labels do not get mixed up with custom labels defined by the customers. 

YAML
 




xxxxxxxxxx
1


 
1
metadata:
2
 labels:
3
  app.kubernetes.io/name: {{ template "chart.fullname" .}}
4
   helm.sh/chart: {{ template "chart.fullnameandversion" .}}
5
   app.kubernetes.io/instance: {{ .Release.Name }}
6
   app.kubernetes.io/managed-by: {{ .Release.Service }}
7
   app.kubernetes.io/component: my-component
8
   app.kubernetes.io/version: {{ .Chart.AppVersion }}
9
 
          



In addition to these, we need to have an organization-wide consensus on the mandatory set of labels.

Exposing Labels and Annotations Configuration

Next, we need to let customers specify their custom labels and annotations. This can be supported with toYaml:

YAML
 




xxxxxxxxxx
1


 
1
labels:
2
  {{- with .Values.my-service.extraLabels }}
3
  {{ toYaml . | indent 4 }}
4
  {{- end }}



This allows the customer to set additional labels in the custom values file such as:

YAML
 




x


1
my-service:
2
 extraLabels:
3
   name: project-name
4
  env: lab
5
  version: 1.0.0
6
  component: api-gateway
7
  part-of: application
8
  managed-by: orchestrator
9
  location-name: branch



Exposing Services Externally

Customers need to expose some services externally to the cluster via a LoadBalancer. This requires the services to be annotated with annotations specific to that LoadBalancer. For example, a customer may require the following annotations to support the F5 Load Balancer and services that need to be exposed externally to the cluster.

YAML
 




xxxxxxxxxx
1


 
1
annotations:
2
 app: application-name
3
 cis.f5.com/as3-tenant: tenant
4
 cis.f5.com/as-app: ingress
5
 cis.f5.com/as-pool: ingress-pool



This can be supported in a similar way as labels:

YAML
 




xxxxxxxxxx
1


 
1
annotations:
2
  {{- with .Values.my-service.annotations }}
3
  {{ toYaml . | indent 4 }}
4
  {{- end }}



With this background, we can set the labels and annotations for different Kubernetes Objects.

Deployment YAML

Labels will have mandatory labels as decided by the organization and extra labels from the customers and the same for annotations. The deployment file for an application should have labels and annotations as illustrated below.

YAML
 




x


1
labels:
2
   app.kubernetes.io/name: {{ template "chart.fullname" .}}
3
   helm.sh/chart: {{ template "chart.fullnameandversion" .}}
4
   app.kubernetes.io/instance: {{ .Release.Name }}
5
   app.kubernetes.io/managed-by: {{ .Release.Service }}
6
   app.kubernetes.io/component: my-component
7
   app.kubernetes.io/version: {{ .Chart.AppVersion }}
8
  {{- with .Values.extraLabels }}
9
    {{- toYaml . | nindent 4 }}
10
  {{- end }}
11
annotations:
12
 prometheus.io/path: /actuator/prometheus
13
 prometheus.io/port: '9000'
14
 prometheus.io/scrape: 'true'
15
  {{- with .Values.deploymentAnnotations }}
16
    {{- toYaml . | nindent 4 }}
17
  {{- end }}



Service YAML

Service with mandatory labels required of all Kubernetes objects and customer provided annotations.

YAML
 




x


1
labels:
2
   app.kubernetes.io/name: {{ template "chart.fullname" .}}
3
   helm.sh/chart: {{ template "chart.fullnameandversion" .}}
4
   app.kubernetes.io/instance: {{ .Release.Name }}
5
   app.kubernetes.io/managed-by: {{ .Release.Service }}
6
   app.kubernetes.io/component: my-component
7
   app.kubernetes.io/version: {{ .Chart.AppVersion }}
8
    {{- with .Values.extraLabels }}
9
      {{- toYaml . | nindent 4 }}
10
    {{- end }}
11
{{- if .Values.serviceAnnotations }}
12
annotations:
13
  {{ toYaml .Values.serviceAnnotations | indent 4 }}
14
{{- end }}



Other Objects

The other common Kubernetes Objects, e.g., Horizontal Pod Autoscalar, ConfigMap, Secrets should have the mandatory labels common to all objects.

YAML
 




xxxxxxxxxx
1


 
1
labels:
2
   app.kubernetes.io/name: {{ template "chart.fullname" .}}
3
   helm.sh/chart: {{ template "chart.fullnameandversion" .}}
4
   app.kubernetes.io/instance: {{ .Release.Name }}
5
   app.kubernetes.io/managed-by: {{ .Release.Service }}
6
   app.kubernetes.io/component: my-component
7
   app.kubernetes.io/version: {{ .Chart.AppVersion }}



Conclusion

Labels and annotations are one of the main foundations for Kubernetes. They are both ways of adding metadata to Kubernetes objects. Kubernetes labels allow us to identify, select, and operate on Kubernetes objects, whereas annotations are non-identifying metadata.

They are used by external tools to help them to provide extra functionalities. However, there are no standard practices enforced. In this article, we attempted to provide a guideline that will serve as best practices when labeling and annotating Kubernetes objects.

 

 

 

 

Top