Skip to content

feat(build): support the Kairos Hadron (musl) base via static runtime#20

Merged
wrkode merged 1 commit into
mainfrom
feat/hadron-base-support
Jun 20, 2026
Merged

feat(build): support the Kairos Hadron (musl) base via static runtime#20
wrkode merged 1 commit into
mainfrom
feat/hadron-base-support

Conversation

@wrkode

@wrkode wrkode commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

What

Add support for building a provider-kubernetes image on the Kairos Hadron minimal/musl immutable OS, alongside the default Ubuntu base. Build capability + docs only (no prebuilt Hadron images in the release pipeline; not in CI yet -- both deliberate).

Two build flags cover the differences (Hadron is used unmodified -- no upstream patches to Hadron, kubelet, or containerd):

  1. KAIROS_INIT_FINALIZE=false -- skip kairos-init. Hadron is already a Kairos OS; re-running kairos-init regenerates the kernel/initrd and fails. The needed services (containerd, kubelet) are enabled directly.
  2. STATIC_RUNTIME=true -- build containerd (make STATIC=1) and kubelet (CGO_ENABLED=0) from source as static binaries. The official glibc-linked containerd/kubelet cannot exec on musl; kubeadm/kubectl/crictl/runc are already static. A static binary also runs on glibc, so the default Ubuntu build is byte-identical -- buildkit only runs the from-source stages when STATIC_RUNTIME=true.

Supply chain

The from-source clones are pinned to commit SHAs (KUBERNETES_COMMIT / CONTAINERD_COMMIT, fail-loud on mismatch) so source integrity matches the checksum discipline of the binary-download path (a git tag is mutable; a commit is content-addressed). Build toolchain patch-pinned (golang:1.26.4).

Docs

New docs/hadron.md operator guide: the two flags, build command, :<ver>-hadron tag convention, per-minor commit pinning, verification, and static-binary capability caveats (no dlopen -> no PKCS#11/HSM or .so plugins; glibc NSS bypassed; seccomp/AppArmor/cgroups/runc unaffected). Linked from the docs index and root README.

Validation

  • libvirt smoke: a single control plane converges end to end on Hadron 4.1.2 -- node v1.34.0, OS Hadron Linux, kernel 7.1.0-hadron, containerd://2.1.4, both static binaries active, all control-plane pods Running, status + annotations correct.
  • Ubuntu default: confirmed unchanged (official glibc kubelet, from-source stages skipped).
  • Pinned build: commit-asserts pass and the image builds.
  • security-architect review: PASS-WITH-NITS, no blockers (pins verified, default path unchanged, no credential/trust/privilege surface touched).
  • Go gates green; no Go/runtime code changed (build-tooling + docs only).

Not in scope (recorded)

Prebuilt Hadron images in the release pipeline; a Hadron CI e2e; digest-pinning the remaining base images (tracked backlog). If Hadron images ever enter the release pipeline they must be brought under the ADR-15 attestation.

🤖 Generated with Claude Code

Comment thread Makefile Outdated
@wrkode
wrkode marked this pull request as draft June 19, 2026 14:16
@wrkode
wrkode requested a review from Itxaka June 19, 2026 18:12
provider-kubernetes images are now built on the Kairos Hadron minimal/musl
immutable OS, via the canonical Kairos build flow (per Itxaka review feedback:
the previous approach re-ran a stale kairos-init on an already-Kairos base).

- Base: pure upstream ghcr.io/kairos-io/hadron:v0.4.0; kairos-init v0.14.6 runs
  the canonical two-phase (install, then init) transform as the final step.
- Hadron is musl, so the official glibc containerd + kubelet cannot exec: both
  are built fully static from source (containerd make STATIC=1, kubelet
  CGO_ENABLED=0). kubeadm/kubectl/crictl/runc are already static and stay the
  checksum-verified downloads. From-source clones are pinned to commit SHAs
  (KUBERNETES_COMMIT/CONTAINERD_COMMIT, fail-loud) for download-path integrity
  parity; static build toolchain patch-pinned (golang:1.26.4).
- Single build path: removed the KAIROS_INIT_FINALIZE / STATIC_RUNTIME flags and
  the dual-base selector stages.
- CI + release resolve the per-minor Kubernetes commit SHA (peeled tag) so the
  from-source build passes across the 1.34/1.35/1.36 matrix; timeouts raised for
  the from-source compile.
- main.go: handle the init.provider.info event kairos-init probes during build
  (was returning empty JSON -> "unexpected end of JSON input").
- docs/hadron.md + README updated for Hadron-as-base.

Validated on libvirt: a control plane converges on Hadron (static binaries
active, phase=Converged). The full e2e suite passes on the Hadron node
container (no harness change needed). Go gates + actionlint green.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: William Rizzo <william.rizzo@gmail.com>
@wrkode
wrkode force-pushed the feat/hadron-base-support branch from 6b8ecce to 411b0cc Compare June 19, 2026 18:12
@wrkode
wrkode marked this pull request as ready for review June 19, 2026 18:36
Comment thread docs/hadron.md

@Itxaka Itxaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

One thing I would change is to try to cache things on order to speed up builds. If nothing changes in the docker file then the cache hits and we don't rebuild. Otherwise, looks good. We may need a workaround for that pkcs11 issue on static builds? Either we build against musl for hadron and other musl systems or we bundle the libs statically as well?

Anyway, for the future.

@wrkode

wrkode commented Jun 20, 2026

Copy link
Copy Markdown
Collaborator Author

LGTM

One thing I would change is to try to cache things on order to speed up builds. If nothing changes in the docker file then the cache hits and we don't rebuild. Otherwise, looks good. We may need a workaround for that pkcs11 issue on static builds? Either we build against musl for hadron and other musl systems or we bundle the libs statically as well?

Anyway, for the future.

dito on the cache.
in my opinion we should build the libs statically. The socially good thing to do is to build for other systems too, but we can take that path in the future, if needed. now?

@wrkode wrkode closed this Jun 20, 2026
@wrkode wrkode reopened this Jun 20, 2026
@wrkode
wrkode merged commit 0860329 into main Jun 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants