Kubernetes Controller
The Kubernetes controller manages Kubernetes deployments, handling the complete lifecycle of Helm charts in customer environments. It installs and upgrades charts, monitors Kubernetes resource health, supports customer-specific value overrides, and provides rollback capabilities for failed deployments.
Installation and Environment
Section titled “Installation and Environment”The controller is installed by applying manifests fetched directly from Distr:
kubectl apply -n <namespace> -f "https://<distr-host>/api/v1/connect?targetId=<targetId>&targetSecret=<targetSecret>"The namespace must already exist. The targetId and targetSecret ensure the controller can only fetch deployments for one specific deployment target. The secret is shown once and never stored by Distr. It can only be verified.
The fetched manifests contain the distr-controller Deployment:
---apiVersion: apps/v1kind: Deploymentmetadata: name: distr-controllerspec: selector: matchLabels: app: distr-controller replicas: 1 strategy: type: Recreate template: metadata: labels: app: distr-controller spec: serviceAccountName: distr-controller securityContext: runAsNonRoot: true containers: - name: distr-controller image: 'ghcr.io/distr-sh/distr/kubernetes-controller' imagePullPolicy: IfNotPresent env: - name: DOCKER_CONFIG value: /opt/config/.docker/ - name: DISTR_CONTROLLER_CONFIG_DIRS value: | /opt/config/.controller/env /opt/config/.controller/auth envFrom: - secretRef: name: distr-controller-auth - configMapRef: name: distr-controller-env volumeMounts: - name: dockerconfig mountPath: /opt/config/.docker/ - name: env mountPath: /opt/config/.controller/env - name: auth mountPath: /opt/config/.controller/auth - name: cache mountPath: /.cache/ volumes: - name: env configMap: name: distr-controller-env - name: auth secret: secretName: distr-controller-auth - name: cache emptyDir: {}The controller can be cluster-scoped or namespace-scoped. This cannot be changed after creation. Cluster-scoped controllers get a ClusterRoleBinding to the built-in cluster-admin role. Namespace-scoped controllers get a RoleBinding to a namespace-admin role limited to that namespace.
The distr-controller-env ConfigMap contains all controller environment variables (same as the Docker controller). The distr-controller-auth Secret contains targetId and targetSecret.
Core Logic
Section titled “Core Logic”The controller runs the following loop at the interval defined by DISTR_CONTROLLER_INTERVAL (default 5 seconds):
- Fetch the deployments from
DISTR_RESOURCE_ENDPOINT - Uninstall Helm releases that are no longer in the list (undeployed)
- Install or upgrade Helm releases that are in the list. If images need pulling, the controller reports status
PROGRESSING. - Send the Helm output to
DISTR_STATUS_ENDPOINT, reporting the deployment’s status.
An install or upgrade that has not finished after 10 minutes is reported as an error rather than left in PROGRESSING. The deployment’s Helm options set that timeout per deployment.
All requests are authenticated with a JWT token obtained from DISTR_LOGIN_ENDPOINT.
Altering the Helm Release
Section titled “Altering the Helm Release”The Kubernetes controller uses the Helm API to manage releases, similar to how the Flux Helm Controller works. You can inspect releases with helm ls -a -n <namespace>.
Authentication with OCI Registries
Section titled “Authentication with OCI Registries”If a deployment uses images from the Distr registry, the controller authenticates automatically, so the customer needs no extra steps.
To reference Distr registry images in your Helm chart, see Configuring Helm Charts for Distr Artifacts.
You can also provide credentials via an application entitlement (Pro feature). When a deployment is created with that entitlement, the controller logs in to the specified registry using the provided credentials.
Controller Self Updates
Section titled “Controller Self Updates”When the controller version for a deployment target is updated in Distr, the controller updates itself on the next cycle. It fetches the new manifest from DISTR_MANIFEST_ENDPOINT and restarts.
Migrating an Existing Helm Release
Section titled “Migrating an Existing Helm Release”The Kubernetes controller only manages releases it knows about. If you already have a Helm release running and want Distr to take it over, you need to create a tracking secret that tells the controller the release exists and which revision it is on.
Step 1: Get the Current Revision Number
Section titled “Step 1: Get the Current Revision Number”helm history <release-name> -n <namespace> --max 1Note the REVISION number from the output.
Step 2: Create the Tracking Secret
Section titled “Step 2: Create the Tracking Secret”kubectl create secret generic "sh.distr.agent.v1.<release-name>" \ --namespace=<namespace> \ --from-literal=release='{"id":"00000000-0000-0000-0000-000000000000","revisionId":"00000000-0000-0000-0000-000000000000","releaseName":"<release-name>","helmRevision":<REVISION>,"deploymentLogsEnabled":false,"phase":"ready"}'Then label it so the controller can discover it:
kubectl label secret "sh.distr.agent.v1.<release-name>" \ --namespace=<namespace> \ "agent.distr.sh/deployment=<release-name>"Step 3: Install the Controller
Section titled “Step 3: Install the Controller”kubectl apply -n <namespace> -f "<distr-connect-url>"The controller discovers the tracking secret, adopts the release, and performs an upgrade on the next reconciliation cycle.
Fixing Revision Skew
Section titled “Fixing Revision Skew”If the controller reports actual helm revision is different from latest deployed by controller, the revision number in the tracking secret does not match the actual Helm release revision.
Option A: From the Distr UI
Open the deployment in the vendor portal, click Update, and use the reset button to sync the controller’s Helm revision to the current release revision.
Option B: Patch the Secret
kubectl patch secret "sh.distr.agent.v1.<release-name>" \ --namespace=<namespace> --type='strategic' \ -p '{"stringData":{"release":"{\"id\":\"00000000-0000-0000-0000-000000000000\",\"revisionId\":\"00000000-0000-0000-0000-000000000000\",\"releaseName\":\"<release-name>\",\"helmRevision\":<CURRENT_REVISION>,\"logsEnabled\":false,\"phase\":\"ready\"}"}}'Uninstalling
Section titled “Uninstalling”Before removing the controller, undeploy all managed deployments via the UI or API.
Set your context to the controller’s namespace:
kubectl config set-context --current --namespace={{deployment-namespace}}Then remove the controller and its associated resources:
kubectl delete deployment/distr-controller secrets/distr-controller-auth configmaps/distr-controller-env serviceaccounts/distr-controller clusterrolebindings/distr-controller-{{deployment-namespace}}Deployment targets connected with Distr 4.2 or earlier use the former distr-agent names for these resources.