Skip to content

Preserve Helm-compatible labels

This content is for the v0.1 version. Switch to the latest version for up-to-date documentation.

Use Helm-style labels when an existing workload selects Pods with the app and release keys. Keeping those selectors avoids an immutable-field change when Kix takes ownership.

Read the current workload selector and Pod template labels:

❱ kubectl get deployment helm-web -n apps -o jsonpath='{.spec.selector.matchLabels}{"\n"}{.spec.template.metadata.labels}{"\n"}'

Continue if the selector follows the common Helm shape, with both app and release set to the release name. For a different selector, use selectorLabels to copy it exactly.

Set labelStyle on the instance:

how-to/adoption/cluster.nix (L83–L90)
apps.helm-web = {
package = webPackage;
labelStyle = "helm";
config = {
message = "Kix manages a Helm-labelled workload";
environment = "production";
};
};

View source on GitHub ↗

For this instance, Kix generates app = "helm-web" and release = "helm-web" as scope.selectorLabels. Packages built with Kix’s workload and Service helpers use the same pair consistently.

Evaluate the cluster:

Run in kix-examples/
❱ kix check how-to-adoption
 TOOL         RESULT  DETAILS                                                       
 eval         pass    20 manifests evaluated                                        
 kubeconform  pass    skipped (this validation tool is not yet integrated with Kix) 
 pluto        pass    skipped (this validation tool is not yet integrated with Kix) 
 kyverno      pass    skipped (this validation tool is not yet integrated with Kix) 
 scorecard    pass    0 errors, 14 warnings, 4 info

Render the Deployment and Service to verify their labels and selectors:

Run in kix-examples/ Output excerpt
❱ kix build how-to-adoption --output json
[
  {
    "apiVersion": "apps/v1",
    "kind": "Deployment",
    "metadata": {
      "name": "helm-web",
      "namespace": "apps",
      "labels": {
        "app": "helm-web",
        "app.kubernetes.io/managed-by": "kix",
        "release": "helm-web"
      }
    },
    "spec": {
      "selector": {
        "matchLabels": {
          "app": "helm-web",
          "release": "helm-web"
        }
      },
      "template": {
        "metadata": {
          "labels": {
            "app": "helm-web",
            "release": "helm-web"
          }
        }
      }
    }
  },
  {
    "apiVersion": "v1",
    "kind": "Service",
    "metadata": {
      "name": "helm-web",
      "namespace": "apps",
      "labels": {
        "app.kubernetes.io/managed-by": "kix",
        "release": "helm-web"
      }
    },
    "spec": {
      "selector": {
        "app": "helm-web",
        "release": "helm-web"
      }
    }
  }
]

Compare the rendered Deployment selector with the live selector from the first step. kix diff cannot make this comparison because it finds live resources through Kix’s management labels. A Helm-owned workload does not have those labels, so the diff shows it as a new resource.

Ask the API server to review the complete ownership change instead:

Run in kix-examples/
❱ kix deploy how-to-adoption --dry-run

A selector mismatch fails there rather than reaching the cluster, because the field is immutable.