BuildKit Kubernetes Driver
BuildKit Kubernetes Driver
Section titled “BuildKit Kubernetes Driver”FractalOps pins moby/buildkit:v0.31.1 by its amd64 child digest and Buildx
v0.35.0 (released 2026-06-17) for the native Kubernetes driver. The direct
child pin matches the hard amd64 node placement and the kubelet-reported image ID.
Investigation date: 2026-07-14.
Supported Path
Section titled “Supported Path”- Assembly GitOps owns the static
fractalops-buildx0Deployment andfractalops-buildx-daemon-configConfigMap infractalops-build. CI consumers use builderfractalops-buildxwithcleanup: false; Buildx v0.35.0 attaches after its bootstrap GET finds that Deployment and does not mutate the live state. - OCI jobs require the
buildplanerunner label. The dedicated repository runner has exactly one replica and usesRollingUpdatewithmaxSurge: 0andmaxUnavailable: 1. The old runner stops before its replacement starts, so at most one runner exists and GitHub queues jobs during the zero-available window. The CLI-only build runner retains scheduler-selected placement and has no control-plane or etcd tolerations. It therefore does not compete with the BuildKit cache for a storage worker’s reserved memory. Its complete label set isself-hosted,build,buildplane; omitting broadlinux,internal, andk8slabels prevents unrelated workflows from matching this restricted service account. The runner carries only the Docker/Buildx CLI: dockerd is disabled, the pod is not privileged, and all image builds execute on the shared Kubernetes BuildKit Deployment. The manifest renderssecurityContext.privileged: falseexplicitly so adoption clears the old live runner’s privileged setting. Its CLI-only container requests100mCPU,512Mimemory, and4Giephemeral storage, with limits of1CPU,2Gimemory, and16Giephemeral storage. - The live Assembly-owned
fractalops-buildx-contractConfigMap is desired-state authority. Its canonical JSON and SHA-256 cover the exact image, driver options, daemon TOML, and Harbor CA source; consumers read it instead of copying values. Setup passes onlyattach-driver-opts(namespace,timeout,loadbalance); mutation options remain audit-only because Assembly already owns the workload. - BuildKit selects the portable
kubernetes.io/os=linuxcapability instead of a hostname. The scheduler may replace it on another Linux worker after node loss. The runner talks to that shared Deployment over the Kubernetes API and needs no node locality. BuildKit tolerates the boundedsandbox=trueworker pool when ordinary workers lack capacity; neither workload tolerates control-plane or etcd taints. - The shared pod requests
8Giand is limited to30Ginode-local ephemeral storage. An explicitbuildkit-rootemptyDir mounts/var/lib/buildkitwith a30Gisize limit. GC reserves6GB, targets at most24GB, and keeps12GBfree. BuildKit requests1CPU and2Gimemory, is limited to2CPU and3Gimemory, and runs daemonmax-parallelism = 1. Scheduler reservation and serialized solves prevent a small worker from entering memory and I/O thrash. This cache survives jobs while the pod survives, but is not recovery data. - Steady state is one BuildKit pod and one build runner. BuildKit uses
RecreatewithrollingUpdate: null; the runner retains the API-compatible RollingUpdate shape but sets surge to zero and unavailable to one. Neither rollout can admit overlapping workers. fractalops-buildx-contractpublishes canonical desired JSON and SHA-256 plus explicit image, resources, node selector, driver options, daemon-config hash, and Harbor CA source. The same canonical hash annotates the Deployment pod template, so an Assembly change performs a GitOps-ownedRecreaterollout.- Stakater Reloader watches
fractalops-buildx-daemon-config,daytona-harbor-ca; daemon-config updates and trust-manager CA rotation therefore restart BuildKit without granting the runner write authority. - Durable layers use a GHCR registry cache with
mode=max. Nexusdocker-groupmirrors only Docker Hub base-image pulls. - trust-manager projects the Harbor CA into ConfigMap
fractalops-build/daytona-harbor-ca. GitOps mounts itsca.crtat/tmp/fractalops-buildkit-daytona-harbor-ca.crt; the daemon config trusts that file only forharbor.daytona.svc.cluster.local. runtime-selfis the sole owner of Namespacefractalops-buildand creates it at wave-20, before trust-manager at wave-10. It preservesargocd.argoproj.io/sync-options: Prune=falsefrom the staged handoff. The child BuildKit chart neither renders the Namespace nor usesCreateNamespace=true, so clean-cluster trust projection has a labeled target without competing owners.
Compatibility and Traps
Section titled “Compatibility and Traps”- Do not set
persistent-volume-claim.requests.storage. The native driver then creates a StatefulSet and one PVC per replica; the namespace quota forbids it. - Keep
docker.ioandghcr.ioorigins on HTTPS.http = trueapplies only to the in-cluster Nexus mirror endpoint. - Fail before use when the projected Harbor CA is missing or the mounted bytes differ from that ConfigMap; never disable Harbor TLS verification or embed the CA bytes in source. CA content is intentionally not pinned, so cert-manager can rotate it and Reloader can restart BuildKit.
- Rootful BuildKit requires the namespace’s explicit privileged Pod Security exception. The exception is isolated to this bounded build plane.
cleanup: true, another builder name, or different driver options can delete or compete with the shared Deployment. Consumer repositories must contract-test their workflow against this pin.- Do not route OCI jobs to general/build labels without
buildplane, increase the dedicated runner replica count, or mutate builder state outside Assembly GitOps. - The dedicated runner service account may only read the named contract and Deployment, list/read BuildKit pods, and exec into the selected pod. It cannot create, patch, or delete Deployments, ConfigMaps, or pods; Argo remains the only runtime-state writer.
- Runtime/canary publication may read only
daytona-workspace-publisherandagentsquad-canary-harbor-robot. The Harbor TLS private-key Secret is never granted to the build runner. - OCI signing uses dedicated roles: read only ClusterSecretStore
fractalops-openbao, and create only a token for ServiceAccountexternal-secrets. The broader general-runner OpenBao bindings remain unchanged and do not include the build service account. - Cache export uses
ignore-error=true: cache failure degrades to a miss, while image publication still fails closed.
Upgrade and Verification
Section titled “Upgrade and Verification”Update the image digest, generated values, contract test, and this page in one commit. Then verify the chart without building an image on the host:
CUE_BIN=.tools/cue/cue platform/k8s/cue-generate.sh lxc-pve-labhelm template fractalops-build platform/k8s/apps/fractalops-build \ -f platform/k8s/environments/lxc-pve-lab/values/fractalops-build.yamlpnpm test:build-planeAuthoritative references: Kubernetes driver, Buildx v0.35.0 release, existing-Deployment bootstrap, generated manifest contract, BuildKit configuration, cache garbage collection, and registry cache.