Kubernetes operator
The OrbitalReg Kubernetes operator manages the entire governance surface from CRDs in your GitOps repo. Projects, repositories, service accounts and tokens, retention policies, security blocks, and webhook subscriptions — all seven resources are reconciled against the OrbitalReg REST API by an in-cluster controller.
The operator's source repo is tools/k8s-operator/. The Helm chart lives at tools/k8s-operator/charts/orbitalreg-operator.
This section is the externally-rendered companion to docs/operator/ in the repo. The in-repo tree remains the canonical engineering source.
When to use it
- You have more than a handful of projects and clicking through the admin UI no longer scales.
- You manage your platform via GitOps (ArgoCD, Flux) and want the same flow for OrbitalReg state.
- You need per-namespace credential provisioning — the operator materialises service-account tokens into Kubernetes Secrets in the consuming namespace, no human-readable token ever touches a CI variable.
When NOT to use it
- You already use the Terraform provider for the same resources. Pick one or the other for any given resource — overlapping management causes write-write loops.
- You only have one or two projects and your team is fluent with the admin UI. The operator's value scales with inventory.
CRDs
| CRD | Scope | Purpose |
|---|---|---|
OrbitalRegProject | Cluster-scoped | Top-level governance boundary |
OrbitalRegRepository | Cluster-scoped | Typed package store |
OrbitalRegServiceAccount | Cluster-scoped | Non-human principal |
OrbitalRegServiceAccountToken | Namespace | Bearer-token credential, materialised into Secret |
OrbitalRegRetentionPolicy | Cluster-scoped | Per-repo prune rules |
OrbitalRegSecurityBlock | Cluster-scoped | Pattern-match block rules |
OrbitalRegWebhookSubscription | Cluster-scoped | Outbound HMAC-signed event delivery |
Full schemas and field-by-field descriptions: CRD reference.
Reconciliation model
Each controller follows the same loop:
- Resolve refs —
spec.projectRef,spec.repositoryRef, etc. to the parent CR'sstatus.<id>. - Adopt or create — first reconcile pass either takes ownership of an existing upstream row (matched by deterministic key) or POSTs a new one.
- PATCH on drift — subsequent passes compute a state→plan diff and PATCH only fields that actually changed. UI edits made in between passes are reverted.
- Finalizer-guarded delete — deleting the CR triggers a foreground-cascade DELETE on the upstream row, then removes the finalizer.
The reconcile interval defaults to 5 minutes; tune via the manager's --reconcile-period flag.
Status conditions
Every CR carries two conditions:
Synced— the controller's view;Trueonce the upstream row matches the CR's spec,Falsewith a reason ofCreateFailed,UpdateFailed, orRefUnresolved.Ready— the canonical Kubernetes name; mirrorsSynced's value but in the shape thatkubectl wait --for=condition=Ready, ArgoCD, Lens, and k9s expect.
status.observedGeneration advances even on no-op merges so kubectl wait honours observedGeneration semantics.
Where to next
- Architecture — controller layout, reconcile loop, finalizers
- Installation — Helm chart, manual install, air-gapped
- CRD reference — every field, every default
- Examples — three reference scenarios
- Troubleshooting — keyed off
Syncedreason codes