Skip to main content
Version: 2.0

GitOps Scaffolder

Service: gitops-scaffolder · Namespace: kubeopera-core · Jobs run in: kubeopera-provisioning

gitops-scaffolder writes the GitOps environment for a new cluster. Given a cluster's name, domain and region, it generates a complete Flux tree — ingress, certificates, storage, database, monitoring, security and every KubeOpera service, all configured for that cluster's domain, with freshly generated and sealed credentials — and pushes it to Git. host-cluster-controller calls it during the GeneratingGitOpsTree phase.

How a run works​

Each run is a Kubernetes Job running scaffold-runner (packaged with the generate-gitops-env tool):

POST /api/v1/scaffolds
▼
Job "scaffold-<id>" in kubeopera-provisioning:
1. clone the target Git repository
2. generate the infrastructure layer only (nothing sealed yet)
3. commit and push
4. wait for the new cluster's Sealed Secrets controller to be Available
5. fetch its public certificate (through the Kubernetes API — no port-forward)
6. generate everything else, sealing fresh credentials with that certificate
7. commit and push
▲
│ polled by host-cluster-controller

Why two passes?​

Credentials must be sealed with the new cluster's own Sealed Secrets key — but the Sealed Secrets controller is itself part of the infrastructure layer being generated. So the scaffolder pushes the infrastructure first, waits for Flux to bring Sealed Secrets up on the cluster, and only then seals and pushes the rest.

The generated tree encodes the same order for Flux: the infrastructure Kustomization has no dependencies, and apps, database and cert-manager-config each depend on infrastructure.

What gets generated​

Using the reference environment as a template:

  • the infrastructure layer — cert-manager, ingress-nginx, storage classes, monitoring, Kyverno, Falco and Sealed Secrets — with external-dns pointed at the new cluster's domain and region;
  • a hostname for every service under the cluster's domain, as overlay patches (the shared base/ manifests are never edited);
  • fresh credentials — PostgreSQL, RabbitMQ and a registry pull secret (or your own, if you supplied one) — sealed before they're committed.

See Setup: creating more environments.

The target can be the platform's shared GitOps repository or your own repository, with credentials supplied when the cluster is created.

API​

Only KubeOpera's own services call this API, using their service identities.

MethodPathDescription
POST/api/v1/scaffoldsStart a run. Returns 202 immediately with the job.
GET/api/v1/scaffolds/{id}Status, message and the generated gitops_path.
GET/api/v1/scaffolds/{id}/logsJob logs.
GET/healthzHealth check.

Operating it​

kubectl logs -n kubeopera-core deploy/gitops-scaffolder -f
kubectl get jobs -n kubeopera-provisioning
kubectl logs -n kubeopera-provisioning job/scaffold-<id> -f

Configuration​

VariableDefaultDescription
DATABASE_URL—PostgreSQL connection.
JOB_NAMESPACEkubeopera-provisioningWhere scaffolding Jobs run.
SCAFFOLD_RUNNER_IMAGEpinned releaseThe scaffold-runner image.
DEFAULT_GITOPS_REPO_URL—The platform's shared GitOps repository.
REFERENCE_ENVIRONMENTdevelopmentThe environment used as the template.