Phase 5: KubeVirt + CDI IaaS proof (R-PLAT-03/04, R-STATE-01, R-NET-01)

- platform/kubevirt: pinned KubeVirt v1.9.0 + CDI v1.66.0 operators (remote bases);
  KubeVirt/CDI CRs tuned for Longhorn; useEmulation=true (prefer real KVM, emulate fallback).
- Controllers/configs split (F-MON1): CRs + ServiceMonitors + alerts via platform-config.
- Observability: ServiceMonitors, KubeVirt platform-health alerts (R-OBS-04), VM dashboard.
- catalog/vm-demo.yaml (kind: vm) + rendered VirtualMachine/DataVolume fixture.
- Conformance: vm-lifecycle (R-PLAT-03/04), vm-data-survival (R-STATE-01, L3),
  vm-default-deny (R-NET-01) — self-skipping until KubeVirt+longhorn exist.
- ci/SPEC_PIN: adopt accepted spec b633b7f (ADR-0015 egress work already merged).
- conformance/run.sh: document R-ENV-02/R-GITOPS-01 coverage gaps (WS-GITOPS/INFRA-owned).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
jakman85andClaude Opus 4.8 committed 2026-08-24 19:51:30 -05:00
1 parent 254d50a20c
commit dbffb8fab8
16 files changed
+905 -61

No files matched your search

@@ -0,0 +1,94 @@
# Rendered from catalog/vm-demo.yaml (kind: vm) — the Phase-5 IaaS proof workload (ADR-0005, docs/06).
# A small headless Fedora Cloud VM whose root disk is CDI-imported onto a Longhorn PVC. Applied by the
# vm-lifecycle (R-PLAT-03) test and by the deploy runbook. Namespace-agnostic: chainsaw injects its
# ephemeral namespace; the runbook applies it into a `vm-demo` namespace (see platform/kubevirt/README).
#
# DURABILITY (R-STATE-01): the DataVolume is STANDALONE (not a `dataVolumeTemplates` entry), so it is
# NOT owner-referenced by the VirtualMachine and OUTLIVES a `kubectl delete vm`. Destroy the VM, keep
# this DataVolume/PVC, re-apply the VM — it re-binds the same Longhorn disk. (dataVolumeTemplates would
# be garbage-collected with the VM and would FAIL rebuild-survival.)
---
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: vm-demo-rootdisk
spec:
source:
registry:
# CDI imports this containerdisk (Fedora Cloud) into the Longhorn PVC below. Pinned tag; Renovate
# can maintain. Import needs egress to quay.io — in an app namespace under default-deny the runbook
# adds a CiliumNetworkPolicy allowing the CDI importer pod egress (see README); the ephemeral test
# namespace has no default-deny baseline, so the import egresses freely there.
url: "docker://quay.io/containerdisks/fedora:41"
storage:
accessModes:
- ReadWriteOnce
storageClassName: longhorn # replicated tier (ADR-0003) — VM disk gets the same durability
resources:
requests:
storage: 6Gi
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-demo
labels:
app.kubernetes.io/name: vm-demo
spec:
# Lifecycle is driven through the K8s API: `running: false` here means "defined but stopped"; the
# test/operator sets it true/false to start/stop, and `kubectl delete vm` destroys it (R-PLAT-03/04).
running: false
template:
metadata:
labels:
kubevirt.io/vm: vm-demo
# Propagated to the virt-launcher pod so Cilium egress steering + the Kyverno egress-class
# policy see the class (ADR-0015). internet = default WAN path (this proof is not VPN-class).
homelab.keithjackson.dev/egress-class: internet
spec:
domain:
cpu:
cores: 1
memory:
guest: 1536Mi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
- name: cloudinit
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
resources:
requests:
memory: 1536Mi
networks:
- name: default
pod: {}
volumes:
- name: rootdisk
dataVolume:
name: vm-demo-rootdisk
- name: cloudinit
cloudInitNoCloud:
# Guest auto-updates with NO human step (docs/11 §3, R-UPD-01): enable dnf-automatic so the
# guest applies stable package updates on its own timer. This is the VM analogue of a
# container image-policy bump — the update policy is declared once, automation applies it.
userData: |-
#cloud-config
package_update: true
packages:
- dnf-automatic
write_files:
- path: /etc/dnf/automatic.conf
content: |
[commands]
upgrade_type = default
random_sleep = 0
download_updates = yes
apply_updates = yes
runcmd:
- [ systemctl, enable, --now, dnf-automatic.timer ]