Go-language parity operator for the Lux platform. Sibling to
hanzoai/operator (Rust, canonical for
all universes); same CRDs, same reconcile behavior, different language.
Used by:
- lux.cloud production (single Go-binary stack for the Lux universe).
- The lux community where the Go ergonomics fit existing services.
The canonical Rust operator (hanzoai/operator v0.2.3+) continues to run in
production for all four universes (hanzo, lux, zoo, osage); this Go port
exists so the Lux community can extend the operator in Go natively without
the Rust toolchain in their critical path.
| Property | Value |
|---|---|
| Language | Go 1.26 |
| Framework | sigs.k8s.io/controller-runtime 0.23 |
| Image | ghcr.io/luxfi/operator:vX.Y.Z (semver only, never :latest) |
| API group | Configurable at install via --api-group / OPERATOR_API_GROUP (default lux.cloud) |
| Default namespace | hanzo-operator-system |
| Kind | Short | Materializes |
|---|---|---|
| Service | hsvc | Deployment + Service + Ingress + HPA + PDB + NetworkPolicy + KMSSecret |
| Datastore | hds | StatefulSet + ClusterIP Service + headless Service + PVC + aliases |
| Gateway | hgw | Deployment + Service + ConfigMap (krakend.json) + Ingress |
| MPC | hmpc | StatefulSet + headless + ClusterIP Service |
| Network | hnet | StatefulSet (validators) + Services + PVC |
| Ingress | hing | Multiple Ingress resources with cert-manager TLS |
| DNS | hdns | Deployment + Service (CoreDNS) |
| BaseApp | bapp | StatefulSet + headless + ClusterIP Service (Quasar writer election) |
| Kind | Short | Inner |
|---|---|---|
| SQL | sql | Datastore (type=postgresql) |
| KV | kv | Datastore (type=valkey) |
| DocDB | docdb | Datastore (type=docdb) |
| S3 | s3 | Datastore (type=minio) |
| IAM | iam | Service |
| KMS | kms | Service |
| LLM | llm | Service |
| Indexer | idx | Service |
| Explorer | exp | Service |
| Kind | Short |
|---|---|
| Chain | chain |
| Subnet | subnet |
| Validator | val |
| Kind | Inner |
|---|---|
| HanzoService | Service |
| HanzoDatastore | Datastore |
| HanzoDNS | DNS |
CRs authored before the canonical v1 split (HanzoService, HanzoDatastore, HanzoDNS) keep working unchanged — they're aliases that delegate to the new reconcilers.
api/
v1/ # Canonical types (20 Kinds).
v1alpha1/ # Legacy compat types (3 Kinds).
cmd/
operator/main.go # Manager entrypoint.
generate-crd-yaml/ # Per-universe CRD bundle generator.
internal/
apply/ # Server-side apply helper.
controller/ # One reconciler per Kind + ReconcileServiceSpec /
# ReconcileDatastoreSpec shared paths.
manifests/ # Pure K8s object builders (no I/O).
config/
crd/bases/<group>/ # Pre-rendered CRD YAML per universe.
default/ # RBAC + ServiceAccount + Deployment + Namespace.
Dockerfile # Multi-stage build → distroless static.
go build ./... # build
go vet ./... # vet
go test -race ./... # unit tests
go run ./cmd/operator --api-group lux.cloud # local run against current
# kubeconfigThe same operator binary serves every universe; bake the API group into the CRD bundle at install time:
go run ./cmd/generate-crd-yaml --api-group lux.cloud --out config/crd/bases/lux.cloud
go run ./cmd/generate-crd-yaml --api-group hanzo.ai --out config/crd/bases/hanzo.ai
go run ./cmd/generate-crd-yaml --api-group zoo.cloud --out config/crd/bases/zoo.cloud
go run ./cmd/generate-crd-yaml --api-group osage.cloud --out config/crd/bases/osage.cloud23 CRDs per universe (20 canonical + 3 legacy).
# 1. Install CRDs.
kubectl apply -f config/crd/bases/lux.cloud/
# 2. Install operator (namespace + ServiceAccount + ClusterRole +
# ClusterRoleBinding + Deployment).
kubectl apply -k config/default/To run in a different universe, edit config/default/rbac.yaml to swap
apiGroups: [lux.cloud] → [hanzo.ai] (etc.), edit
config/default/deployment.yaml OPERATOR_API_GROUP env, and apply the
matching CRD bundle.
spec.env / spec.envFrom / spec.volumes / spec.volumeMounts MUST be
honored on every generated Deployment. The gateway 503 root cause (May 2026
on the legacy Go operator) was these silently being dropped. Tests assert
the round-trip:
go test ./internal/controller -run TestReconcileServiceSpec_GatewayEnvVolumesHonoredBoth this Go operator and the canonical Rust operator at
hanzoai/operator must pass the
operator-e2e
parity suite (31 cases, 11 full-quality byte-asserted). Each
cases/<id>/input.yaml + expected/*.yaml pair specifies "given this CR,
the operator MUST produce these K8s objects."
# From hanzoai/universe checkout:
cd test/operator-e2e
./runners/run.sh --operator=go # this Go operator
./runners/run.sh --operator=rust # canonical Rust operator at hanzoai/operatorDrift between the two is a bug to fix on whichever side strayed.
The Rust v0.3.x implementation of this repo (pre-2026-05-18) is preserved on
the legacy/rust-impl-before-go-rewrite branch. The canonical Rust operator
at hanzoai/operator absorbed that codebase's CRDs (Network, Chain,
Validator, Subnet, MPC, Gateway, Indexer, Explorer) when this Go port took
over the main branch.
- Go 1.26. Update via
go.modonly, never viareplacedirectives. - Never
:latest,:main,:dev. PinvX.Y.Zper semver-only policy. - Field-for-field wire compatibility with the Rust operator — CRs in the cluster MUST NOT need editing when you switch the operator binary.
- Honor
spec.env/volumes/volumeMounts— the load-bearing assertion. - amd64 only (arm64 paused per global LLM.md 2026-04-27 — DOKS has no arm64).