Does helm or K8S override spec.template.metadata.labels with spec.selector.matchLabels?

Viewed 623

I have a chart I am applying with helm v3 and when I render it locally it looks like this;

apiVersion: apps/v1
kind: Deployment
metadata:
  name: RELEASE-NAME-generic
  labels:
    app: generic
    chart: generic-1.1.2
    release: RELEASE-NAME
    heritage: Helm
    app.kubernetes.io/name: generic
    app.kubernetes.io/instance: RELEASE-NAME
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/version:
spec:
  replicas: 1
  selector:
    matchLabels:
      app: generic
      release: RELEASE-NAME
  template:
    metadata:
      labels:
        app.kubernetes.io/name: generic
        app.kubernetes.io/instance: RELEASE-NAME
    spec:
      imagePullSecrets:
      - name: ""
      containers:
        - name: generic
          image: ":"
          imagePullPolicy: IfNotPresent
          ports:
          resources:
            {}

Note that the spec.selector.matchLabels and spec.template.metadata.labels do not match here. This is potentially a problem, but this was just for a test.

When I apply it to the cluster (GKE, latest version) and inspect the yaml there, it looks like this (roughly);

apiVersion: apps/v1
kind: Deployment
metadata:
  name: RELEASE-NAME-generic
  labels:
    app: generic
    chart: generic-1.1.2
    release: RELEASE-NAME
    heritage: Helm
    app.kubernetes.io/name: generic
    app.kubernetes.io/instance: RELEASE-NAME
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/version:
spec:
  replicas: 1
  selector:
    matchLabels:
      app: generic
      release: RELEASE-NAME
  template:
    metadata:
      labels:
        app: generic
        release: RELEASE-NAME
    spec:
      imagePullSecrets:
      - name: ""
      containers:
        - name: generic
          image: ":"
          imagePullPolicy: IfNotPresent
          ports:
          resources:
            {}

The spec.template.metadata.labels has been overwritten with the labels in spec.selector.matchLabels.

Now, this makes sense from the perspective of having a working deployment, but I cannot find this behaviour documented anywhere, in either K8S or Helm, and I'm wondering if this is actually supposed to happen, or if I'm going nuts here...

1 Answers

Those labels are added for finding resources managed by Helm. Below you can find some information from documentation:

Helm's github site might be helpful in understanding how labels and selectors work:

spec.selector.matchLabels defined in Deployments/StatefulSets/DaemonSets >=v1/beta2 must not contain helm.sh/chart label or any label containing a version of the chart, because the selector is immutable. The chart label string contains the version, so if it is specified, whenever the Chart.yaml version changes, Helm's attempt to change this immutable field would cause the upgrade to fail.

Additional information found on helm's site:

An item of metadata should be a label under the following conditions:

It is used by Kubernetes to identify this resource It is useful to expose to operators for the purpose of querying the system. For example, we suggest using helm.sh/chart: NAME-VERSION as a label so that operators can conveniently find all of the instances of a particular chart to use.

If an item of metadata is not used for querying, it should be set as an annotation instead.

Related