Skip to content
Distr
Book DemoStart free trialLogin

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.

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/v1
kind: Deployment
metadata:
name: distr-controller
spec:
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.

The controller runs the following loop at the interval defined by DISTR_CONTROLLER_INTERVAL (default 5 seconds):

  1. Fetch the deployments from DISTR_RESOURCE_ENDPOINT
  2. Uninstall Helm releases that are no longer in the list (undeployed)
  3. Install or upgrade Helm releases that are in the list. If images need pulling, the controller reports status PROGRESSING.
  4. 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.

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>.

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.

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.

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.

Terminal window
helm history <release-name> -n <namespace> --max 1

Note the REVISION number from the output.

Terminal window
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:

Terminal window
kubectl label secret "sh.distr.agent.v1.<release-name>" \
--namespace=<namespace> \
"agent.distr.sh/deployment=<release-name>"
Terminal window
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.

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

Terminal window
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\"}"}}'

Before removing the controller, undeploy all managed deployments via the UI or API.

Set your context to the controller’s namespace:

Terminal window
kubectl config set-context --current --namespace={{deployment-namespace}}

Then remove the controller and its associated resources:

Terminal window
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.