Wire the KVM provider: main.go, kvm-ssh Secret mount, samples, docs, CHANGELOG

Registers "kvm" in the provider builtins, mounts an optional kvm-ssh
Secret at /etc/proxy-operator/kvm, adds a kvm-home providers-config
sample and a proxy_kvm.yaml Proxy sample, documents the provider in
docs/kvm-provider.md (prerequisites, config reference, image cache and
its do-not-replace-in-use rule, known gaps), and updates the README
and architecture provider sections and decision log.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 19:13:51 +00:00
co-authored by Claude Fable 5.1
parent b3984ca69d
commit 791988b5a0
11 changed files with 448 additions and 6 deletions
+27 -3
View File
@@ -15,9 +15,10 @@ itself**, and hands out to crawler clients via an HTTP list/lease API.
cattle**: any meaningful spec change (placement, cloud-init, port)
deletes and recreates the VM — never in-place mutation.
- **Providers** behind one minimal interface: `kubernetes` (a real Squid
pod in this cluster — local dev/CI) and `gcp` (Compute Engine VMs with
ephemeral external IPs — the real egress fleet). Config is a YAML file
(`--providers-config`) with named instances (`gcp-eu`, `gcp-us`, ...).
pod in this cluster — local dev/CI), `gcp` (Compute Engine VMs with
ephemeral external IPs — the real egress fleet) and `kvm` (VMs on your
own libvirt hypervisors, reached over SSH). Config is a YAML file
(`--providers-config`) with named instances (`gcp-eu`, `kvm-home`, ...).
- **Health engine** probes every proxy by fetching a URL *through* it (a
real CONNECT tunnel — a proxy that accepts TCP but can't egress goes
Unhealthy), with threshold logic and transition-only status writes.
@@ -131,6 +132,29 @@ make deploy IMG=<registry>/egress-proxies-operator:dev
which also installs Squid via cloud-init). A missing field fails the
Proxy with a message naming it.
## KVM setup
Managed proxies as VMs on libvirt/KVM hosts you own. Full guide:
[docs/kvm-provider.md](docs/kvm-provider.md).
1. Each host needs `libvirtd`, an SSH user in the `libvirt` group, a
bridge to a network with DHCP, and a storage pool.
2. Create the `kvm-ssh` Secret (private key + `known_hosts`); the manager
mounts it at `/etc/proxy-operator/kvm`:
```sh
kubectl -n egress-proxies-operator-system create secret generic kvm-ssh \
--from-file=id_ed25519=<key> --from-file=known_hosts=<known_hosts>
```
3. Add a `kvm` entry to the providers config with `images`,
`machineTypes` and `hosts` (see
[config/samples/providers-config.yaml](config/samples/providers-config.yaml)).
Base images are downloaded into each host's pool on first use.
4. A Proxy names a host (`placement.zone`, optional with one host), a
size (`placement.machineType`) and an image (`placement.image`) — see
[config/samples/proxy_kvm.yaml](config/samples/proxy_kvm.yaml).
Cloud-init from a Secret: the Secret **must** carry the label
`crawl.example.com/cloud-init: "true"` — the operator's cache only holds
labelled Secrets, so an unlabelled one is invisible (the Proxy reports