Concepts
The object model
Section titled “The object model”Project ──▶ Environment ──▶ App ──▶ Release shop staging api #42 production worker db (template)| Object | What it is | On the cluster |
|---|---|---|
| Project | A group of related apps: a product, a customer, a team. Roles are given per organisation, and can be raised for one project or one environment. | A cluster-scoped Project resource |
| Environment | Where apps run. staging and production are the common pair, but any number is fine. A production environment starts out needing one approval per deployment. |
An Environment resource and a namespace kb-<project>-<environment> with a ResourceQuota, a LimitRange, a NetworkPolicy and Pod Security labels |
| App | One deployable unit: an image, its processes, environment variables, domains, volumes. | An ApplicationRuntime for the cluster agent (or, without an agent, an App resource) in the environment namespace, carried out as a Deployment (or CronJob), a Service, an HPA and an HTTPRoute |
| Release | An immutable snapshot of an app’s spec, numbered per app. Deploys, configuration changes, rollbacks, promotions and template deploys all create one, and each goes out as a deployment that moves through phases such as Awaiting approval, Applying and Succeeded. | Kept in PostgreSQL; the cluster sees only the result |
| Secret | Named values written through the API and never read back. Apps reference them by name. | Sealed with Kuben’s keyring in PostgreSQL, one revision per change; each revision an app uses is written as an immutable Kubernetes Secret in the environment namespace |
Apps carry a Ready condition and, when they serve HTTP, Exposed; environments carry Ready. Each has a reason and a message, visible in the console and with kubectl.
PostgreSQL holds the desired state
Section titled “PostgreSQL holds the desired state”Kuben keeps what should exist in PostgreSQL: projects, environments, apps, their configuration and release history, sealed secrets, policies, users, tokens and the audit log. The materializer writes it to the cluster as kuben.dev resources, or hands it to the cluster agent, and the controllers make the cluster match.
Two consequences follow:
- Kuben owns what it writes. A change made by hand to an object Kuben manages is recorded as drift and written back. To hand an app to Argo CD or Flux, export it (plain manifests, no secret values) and detach it: Kuben lets go and leaves it running.
- Backups are the database.
kuben backupwrites apg_dumparchive, and the Helm chart runs it every night; the cluster objects are rebuilt from it. Secret values in it stay sealed, so keep a copy of the keyring apart from it. See Backup and restore.
Networking
Section titled “Networking”For every app with an HTTP port, the controller creates an HTTPRoute whose hostnames are the app’s custom domains plus <app>-<project>-<environment>.<baseDomain>. Processes with protocol: tcp (databases from templates) get a cluster-internal Service only and are never reachable from the internet.
Kuben writes the listeners of its own Gateway only: one it creates from gatewayClassName, or one you label kuben.dev/gateway-owner=kuben. It never touches any other Gateway. With a cert-manager ClusterIssuer configured, that means one HTTPS listener per hostname with its own certificate, a plain-HTTP listener that only redirects, and optionally a wildcard listener for generated hostnames. Details and limits are in Exposing apps and HTTPS.
Inside the binaries
Section titled “Inside the binaries”Kuben has two binaries. kuben, the hub, is the server and the command line. kuben-agent, the cluster agent, is a small, unprivileged process in the cluster: it dials the hub over a mutually authenticated TLS link, receives what each app should be, and applies it with server-side apply. Nothing else. The Helm chart and kuben setup run one by default, and it enrolls on its own; without an agent, the hub’s App controller delivers apps itself.
kuben serve runs several roles in one process:
| Role | Responsibility |
|---|---|
api |
The REST API (/api/v1), the embedded web console, server-sent events for logs and status |
controller |
The materializer, and the reconcilers for projects, environments, apps and the Gateway |
activator |
Reserved for scale-to-zero; it does nothing yet, and Kuben logs a warning when you select it |
By default a process runs all of them (--roles=all). In the Helm chart you can run several replicas: every replica serves the API from its own projections, small in-memory read models fed by Kubernetes watches, while only the replica holding the kuben-controller Lease runs the controllers. A crashed leader is replaced within about fifteen seconds, a gracefully stopped one within a few. Several replicas need an external PostgreSQL. See High availability.
Identity and access
Section titled “Identity and access”- Sessions are opaque ids in an
HttpOnly,Secure,__Host-cookie. There is no JWT in the browser; a revoked session stops working within seconds on every replica. - API tokens (
kbn_pat_…) are opaque too. Only their SHA-256 hash is stored and compared in constant time. A token is capped at a role and optionally scoped to one project or environment. - Roles form a strict ladder:
viewer<developer<admin<owner. See Teams and roles. - Single sign-on through OpenID Connect maps your identity provider’s groups to roles, and GitHub Actions can exchange its OIDC token for a short-lived Kuben token, so CI needs no stored secret. See Sign-in and Deploy from CI.
- Audit. Every create, update, delete, restart, rollback, promotion, invitation and token change is recorded, as is every refused change and every login. Request bodies, and therefore secret values, never are. See The audit log.
Generated contracts
Section titled “Generated contracts”The OpenAPI document and the CRD manifests in the Helm chart are the contracts Kuben keeps: the server’s routes and the TypeScript client used by the console are generated from the OpenAPI document, and the binary embeds the CRD manifests. CI fails on any difference, so what this site’s REST API reference shows is what the binary serves.