Repository navigation
Description
Problem
Every PR E2E run provisions a full Talos cluster of three nested QEMU/KVM VMs inside a privileged Docker container, on the largest VM runner class. This is the heaviest and slowest part of PR CI, and it is paid in full even for a PR that only touches a single app and needs nothing from the storage / networking / virtualization stack that the heavy cluster exists to exercise.
Sibling epic #2847 (Track A) makes the install lighter — a test-minimal bundle + hack/select-install.sh install only the packages a PR's diff needs. This issue tackles the orthogonal axis #2847 explicitly left out of scope: the cluster the install runs on. The two compose: a minimal install on a minimal cluster.
Current heavy approach (evidence)
.github/workflows/pull-requests.yaml— thee2ejob runs on the 24 vCPU / 96 GB VM runner class with a 180-minute timeout.Makefile: prepare-env→packages/core/testingapply+prepare-cluster.packages/core/testing/Makefile: apply—docker run --privilegedlaunches thee2e-sandboxcontainer.hack/e2e-prepare-cluster.bats— inside that container it boots 3 QEMU VMs (-smp 8 -m 24576, i.e. 8 vCPU + 24 GB each), each with a 50 GB system disk cloned from the Talosnocloud-amd64.rawimage plus a 200 GB data disk, wires a bridge + masquerade, generates Talos machine-config, and waits on the Talos API before install.- A dedicated
build-talosjob builds and uploads the nocloud disk (make -C packages/core/talos talos-nocloud) on every PR to feed the above.
Net: full Talos + nested virtualization + a per-PR disk build, for all PRs.
Proposed lighter approach
Add a lightweight cluster provisioner as an alternative to the QEMU-VM path in hack/e2e-prepare-cluster.bats, selected per-PR (e.g. reuse the existing diff/TIA signal from #2559 / #2847 so only diffs that don't touch storage, CNI dataplane, or virtualization opt into it). Two candidate backends:
- kind (Kubernetes-in-Docker) — nodes are containers; no nocloud disk, no nested VMs, runs on a small runner. Closest to the original Add simple test with kind #98 idea but re-scoped to the current Package/bundle install model and to diff-scoped selection rather than a fixed
paas-hostedbundle. - Talos-in-Docker (
talosctl cluster create --provisioner docker) — keeps Talos as the distro (so machine-config, the cozystack API, and the platform bundle behave as in production) while dropping QEMU and the raw-disk build. Higher fidelity than kind; still no kernel-module / KVM surface.
Either way the heavy Talos-on-QEMU path stays as the default and is always used for storage / networking / virtualization diffs and for every release run.
Constraints / non-goals
- A containerized cluster cannot load out-of-tree kernel modules (DRBD / LINSTOR / ZFS), cannot run KubeVirt VMIs, and does not exercise the real CNI dataplane. So the lightweight path is only valid for diff-scoped tests that need none of those; anything touching
system/linstor,system/kubeovn/CNI, orapps/virtual-machineetc. must fall back to full Talos. Release E2E always runs full Talos. - Not replacing the BATS harness or the app-test suite — only the cluster provisioning step.
Open questions
- kind vs Talos-in-Docker: is the extra fidelity of Talos-in-Docker worth it, or is kind enough for the app-only tests that would use this path?
- Selection signal: reuse the
e2e-tia/select-e2e.shdiff classification, or add a distincte2e-light-clusteropt-in label? - Which app E2E tests actually pass on a containerized cluster today? Needs an audit of
hack/e2e-apps/*.batsfor module/VM/dataplane assumptions. - Runner sizing: what runner class can host the light cluster, and what is the measured wall-time / cost delta vs the current 24 vCPU / 96 GB path?
- How does the minimal install (
bundles.testMinimal, [Epic] Diff-driven & scenario-based E2E testing for Cozystack #2847) behave on a containerized cluster — any packages in the minimal baseline that still assume Talos primitives?
Relation to other work
- [Epic] Diff-driven & scenario-based E2E testing for Cozystack #2847 — sibling epic; makes the install minimal and explicitly scopes cluster provisioning out. This issue is the cluster half.
- feat(ci): test-impact analysis E2E (default-on) + release E2E workflow #2559 (merged) — TIA selector this can reuse to decide when the light cluster is safe.
- Add simple test with kind #98 (closed, frozen) — the original "test with kind" idea, retired under the old bundle model; this re-files it against the current Package/bundle + diff-driven model.
- Finish the CI image-build refactor: SBOM emission and pr-* tag retention #2937 — CI image-build refactor (ephemeral runners for builds); orthogonal, but the light-cluster path would also let the E2E leg drop the per-PR
build-talosnocloud-disk dependency.
Activity
myasnikovdaniil commentedon Jul 9, 2026
Survival audit — all 22
hack/e2e-apps/*.batson kind / Talos-in-DockerSURVIVES (15): all set
storageClass: ""(or need no storage) and provision single replicas — no DRBD/replication. kind'slocal-pathor any Talos-in-Docker default SC satisfies them.bucket/harboradditionally need the SeaweedFS+COSI platform stack (a provisioning prerequisite, not a kernel blocker).serviceexposuredeliberately uses theexternalIPsbackend to avoid any MetalLB/Cilium pool or L2 reachability (serviceexposure.bats:5–11).CONDITIONAL (2) — no nested-virt/kernel deps, but require Cilium as CNI (fine on Talos-in-Docker w/ Cilium, fail on vanilla kindnet):
gateway— GatewayClasscilium,cilium-gateway-*LB Service,Programmedneeds Cilium dataplane + LB IPAM.securitygroup— round-trips SecurityGroup ↔cilium.io/v2CiliumNetworkPolicy CRD.NEEDS-REAL-CLUSTER (5) — hard blockers, nested KVM virt and/or DRBD:
vminstance— KubeVirt VM/VMI + CDI DataVolume +storageClass: replicated.kubernetes-latest/-previous— Kamaji CP + CAPK KubeVirt worker VMs + CDI + DRBD-replicated worker disks (run-kubernetes.sh:68,402-438). (latest's second test,verify_storageclass_fallback_default, renders against the mgmt cluster and would survive alone.)kubernetes-oidc-system/-customconfig— tenant k8s withstorageClass: replicated.Recommendation
A lightweight lane (Talos-in-Docker + stock Cilium CNI + a default StorageClass) can run 17 of 22 tests — the 15 SURVIVES plus the 2 CONDITIONAL. Only 5 (
vminstance+ the fourkubernetes-*) truly need a bare-metal-like cluster, each for the same reason: nested KVM for KubeVirt VMs + DRBD storage. Suggested split: run the 17 non-virt tests on the fast containerized lane for PR feedback; keep the 5 virt/DRBD tests on the existing nested-QEMU lane. Reclaims most of the suite's wall-clock with no loss of coverage that actually depends on the heavyweight environment.myasnikovdaniil commentedon Jul 9, 2026
Follow-up: this is an
enabledPackagesprofile + a storage/CNI swap, not a new bundleCorrecting my earlier "someone has to author a bundle" — cozystack already has the granular mechanism. All four bundles (
system/iaas/paas/naas) have per-bundleenabledflags, and on top of thatbundles.enabledPackages/bundles.disabledPackagesgive per-package control — which is exactly whatcozypkg add/deldrives. So the lightweight path is:core-only platform (all bundles
enabled: false) →cozypkg addonly the packages that survive.The catch: core-only has no CNI and no StorageClass
Both normally arrive via the
systembundle:cozystack.networking= kube-ovn + cilium (OVS kernel module)cozystack.linstor= DRBD + ZFSNeither runs in talos-in-docker. So the profile must substitute two things — this is the only part that isn't just
cozypkg add:storageClass: ""= default SC and need some PV).gateway,securitygroup) pass. Note: today's networking package only shipskubeovn-ciliumandkubeovn-cilium-genericvariants — a cilium-only variant is the one genuinely new piece of work here.Result
With storage + CNI substituted, the e2e values just set
bundles.enabledPackagesto the surviving app set:gateway,securitygrouponce cilium-only is in).iaasbundle → KubeVirt/CDI + the CAPK-VM tenant clusters stay off, so the 5 NEEDS-REAL tests (vminstance+ the fourkubernetes-*) drop out for free — no nested KVM, no DRBD.Net: 17/22 tests on a container cluster, driven by an
enabledPackageslist + a local-path default SC + a cilium-only networking variant. No new bundle, no per-component conditional logic.docs(e2e): add lightweight container-cluster e2e lane proposal
feat(system/local-storage): OpenEBS LocalPV hostpath default StorageC…
myasnikovdaniil commentedon Oct 1, 2026
done via #4020
feat(local-storage): add opt-in OpenEBS LocalPV hostpath package (#3266)