Kubernetes Operator
The KSail operator brings declarative cluster management into Kubernetes. It reconciles Cluster custom resources (ksail.io/v1alpha1), so you can provision and manage KSail-supported distributions with kubectl apply — or let your GitOps engine do it for you. An optional web UI and OIDC-authenticated REST API are included.
What the Chart Deploys
Section titled “What the Chart Deploys”| Component | Description | Toggle |
|---|---|---|
| Operator | Controller that reconciles Cluster custom resources |
operator.enabled (default true) |
Cluster CRD |
Installed automatically from the chart’s crds/ directory |
— |
| RBAC | ServiceAccount plus the (Cluster)Role and binding the operator needs | serviceAccount.create |
| REST API | Served by the operator, consumed by the UI | api.bindPort (0 disables) |
| Web UI | Dashboard that talks to the REST API | ui.enabled (default false) |
| OIDC auth | App-driven login protecting the REST API and UI | auth.oidc.enabled (default false) |
Getting Started
Section titled “Getting Started”Requires Kubernetes 1.27+ and Helm 3.8+.
-
Install the chart. Each KSail release publishes it as an OCI artifact to GHCR — pin a release version:
Terminal window helm install ksail-operator oci://ghcr.io/devantler-tech/charts/ksail-operator \--version <version> --namespace ksail-system --create-namespace -
Apply a
Clusterresource. The operator picks it up and provisions the cluster:apiVersion: ksail.io/v1alpha1kind: Clustermetadata:name: my-clusternamespace: ksail-systemspec:cluster:distribution: VCluster -
Watch it reconcile:
Terminal window kubectl get clusters -n ksail-system -w
Distributions that run nested inside the host cluster (VCluster, K3s) work out of the box. Docker-based distributions (Vanilla/Kind, K3d) need the host Docker socket mounted via operator.dockerSocket.enabled=true — this is privileged and single-node, so prefer nested distributions in-cluster. See the Kubernetes (Nested) provider for how nested clusters run as pods.
Upgrading
Section titled “Upgrading”Helm installs CRDs from the chart’s crds/ directory only on the first install. helm upgrade never updates them. Before you upgrade an existing installation, apply the Cluster CRD from the chart version you are moving to. If you skip this step, the API server drops status fields that the old CRD does not define, such as status.observedDistribution and status.observedProvider, and their kubectl get clusters -o wide columns stay empty.
helm show crds oci://ghcr.io/devantler-tech/charts/ksail-operator --version <version> \ | kubectl apply --server-side --force-conflicts -f -helm upgrade ksail-operator oci://ghcr.io/devantler-tech/charts/ksail-operator \ --version <version> --namespace ksail-systemThe helm upgrade --install examples below need the same CRD step when the release already exists.
Component Installation
Section titled “Component Installation”The operator reconciles the full Cluster spec, not just the bare cluster. After a cluster is provisioned it installs the components you declared — CNI, CSI, CDI, metrics-server, cert-manager, load-balancer, policy-engine, and the GitOps engine — into the child cluster, in order:
- CNI first, so pods can schedule.
- Infrastructure — CSI, CDI, metrics-server, cert-manager, load-balancer, policy-engine.
- GitOps engine (Flux or ArgoCD) last.
Installation is idempotent and gated, so a steady reconcile does not re-run Helm every tick: the operator records a last-applied-components baseline and re-applies only when the component-relevant spec changes. Progress is reported in a ComponentsReady status condition and a per-component status.components summary the web UI renders. A component that fails to install marks the cluster Degraded with ComponentsReady=False and requeues — it does not fail provisioning, and it retries as the child API becomes reachable. Components you later flip off (to None/Default) are uninstalled from the recorded baseline.
Enabling the Web UI
Section titled “Enabling the Web UI”helm upgrade --install ksail-operator oci://ghcr.io/devantler-tech/charts/ksail-operator \ --version <version> --namespace ksail-system --create-namespace \ --set ui.enabled=trueWithout an Ingress, port-forward to reach it (the Service is named <release-name>-ksail-operator-ui):
kubectl port-forward -n ksail-system svc/ksail-operator-ksail-operator-ui 8080:80Set ui.readOnly=true in GitOps-enforced environments so the Git repository stays the single source of truth — the operator enforces read-only mode server-side, not just in the frontend.
Securing with OIDC
Section titled “Securing with OIDC”OIDC closes the otherwise-unauthenticated REST API. The API owns the login/callback flow as a confidential client, so the client secret stays server-side. The provider must reach the API’s callback at a stable URL — typically through an Ingress:
helm upgrade --install ksail-operator oci://ghcr.io/devantler-tech/charts/ksail-operator \ --version <version> --namespace ksail-system --create-namespace \ --set ui.enabled=true \ --set ui.ingress.enabled=true \ --set ui.ingress.hosts[0].host=ksail.example.com \ --set auth.oidc.enabled=true \ --set auth.oidc.issuerURL=https://dex.example.com \ --set auth.oidc.clientID=ksail \ --set-string auth.oidc.clientSecret=CLIENT_SECRET \ --set auth.oidc.redirectURL=https://ksail.example.com/api/v1/auth/callbackRegister the redirect URL with your provider. To keep secrets out of --set and values files, pre-create a Secret with keys client-secret and session-secret and reference it via auth.oidc.existingSecret.
Uninstalling
Section titled “Uninstalling”helm uninstall ksail-operator --namespace ksail-systemHelm does not remove CRDs installed from crds/. Delete the Cluster CRD manually if you no longer need it — this also deletes all Cluster resources:
kubectl delete crd clusters.ksail.ioConfiguration Reference
Section titled “Configuration Reference”The full values reference — images, replicas, leader election, resources, Ingress, and OIDC — lives in the chart README.
Related
Section titled “Related”- Web UI & Desktop App — the same UI, running locally instead of in-cluster
- Kubernetes (Nested) provider — how nested clusters run as pods inside a host cluster
- GitOps Workflows — drive
Clusterresources from Git with Flux or ArgoCD