Skip to content
kix /docs
Install the CLI

How-to guide Adopt existing resources

Preserve existing selectors

Keep an existing workload's immutable selector when moving it under Kix management.

Kubernetes does not allow a Deployment or StatefulSet selector to change in place. Before Kix takes ownership of an existing workload, configure its instance to retain that selector.

Get the selector from the live workload:

❱ kubectl get deployment legacy-web -n apps -o jsonpath='{.spec.selector.matchLabels}'

Use the labels from spec.selector.matchLabels, not every label on the workload. Confirm that the Pod template has the same labels before continuing.

Copy those labels into selectorLabels:

how-to/adoption/cluster.nix
apps.legacy-web = {
package = webPackage;
selectorLabels = {
app = "legacy-web";
tier = "frontend";
};
config = {
message = "Kix now manages this workload";
environment = "production";
};
};

View source on GitHub ↗

Kix passes this value to package builders as scope.selectorLabels. Workload helpers use it for both spec.selector.matchLabels and the Pod template labels, and Service helpers use it when selecting the workload.

The package must build its selectors from scope.selectorLabels for this instance option to take effect.

Evaluate the cluster:

kix-examples/
❱ kix check how-to-adoption
 TOOL       RESULT  DETAILS                       
 eval       pass    21 manifests evaluated        
 scorecard  pass    0 errors, 14 warnings, 2 info

Render the workload and compare both label sets with the live Deployment:

kix-examples/ output excerpt
❱ kix build how-to-adoption --output json
{
  "apiVersion": "apps/v1",
  "kind": "Deployment",
  "metadata": {
    "name": "legacy-web",
    "namespace": "apps"
  },
  "spec": {
    "selector": {
      "matchLabels": {
        "app": "legacy-web",
        "tier": "frontend"
      }
    },
    "template": {
      "metadata": {
        "labels": {
          "app": "legacy-web",
          "app.kubernetes.io/name": "legacy-web",
          "tier": "frontend"
        }
      }
    }
  }
}

The rendered selector and Pod labels contain the existing app and tier values. Compare them against the kubectl get output from the first step.

kix diff cannot make this comparison. It finds live resources through Kix’s management labels, which the existing workload does not yet have. The diff therefore shows the workload as a new resource and never compares the selectors.

Ask the API server instead:

kix-examples/
❱ kix plan how-to-adoption

Deployment and StatefulSet selectors are immutable. A mismatch therefore appears among the writes the deploy would stop on, either as an immutable-field refusal or as a field ownership conflict when another manager owns the selector.