Document the provider health checks
Architecture gets a provider-health section, component rows and four decisions; the KVM provider doc gets a health-check section with the reason table and the rotated-Secret gap; the testing guide lists the new suites. CLAUDE.md's Architecture TODO and stale "only go.mod exists" gotcha now point at the real docs, plus the RBAC-marker gotcha found while wiring the monitor. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
+52
-2
@@ -265,12 +265,60 @@ The provider logs through controller-runtime's logger, named `kvm`, with
|
||||
only `length` and `duration`. There is no raw wire tier like the GCP
|
||||
provider's V(5); go-libvirt exposes no hook for it.
|
||||
|
||||
## Health check
|
||||
|
||||
The operator checks every configured host every `--provider-check-interval`
|
||||
(default 1m). It publishes the result in two places: the `ProviderHealth`
|
||||
object named after the provider (`kubectl get ph kvm-home -o yaml`), and the
|
||||
`proxy_operator_provider_target_up{provider,target}` gauge.
|
||||
|
||||
All hosts are checked concurrently, each over the same pooled connection
|
||||
that Create and Get use:
|
||||
|
||||
1. The SSH and libvirt handshakes. These only happen on the first check, or
|
||||
after the link dropped.
|
||||
2. `virConnectGetLibVersion` and `virConnectGetHostname`.
|
||||
3. `virStoragePoolLookupByName` and `virStoragePoolGetInfo` on the host's
|
||||
`pool`.
|
||||
|
||||
A passing target's `details` carry `hostname`, `libvirtVersion`, `pool`,
|
||||
`poolState`, `poolCapacity` and `poolAvailable` (in GiB). The free space is
|
||||
the closest thing this provider has to a capacity signal. Every target also
|
||||
shows its SSH `user`. A failing target says where the check broke:
|
||||
|
||||
| Reason | Meaning | Look at |
|
||||
|---|---|---|
|
||||
| `SSHMaterialUnavailable` | the key or known_hosts file is missing or does not parse | the `kvm-ssh` Secret (see *Cluster-side setup*) |
|
||||
| `Unreachable` | the TCP connect failed, or the link died mid-check | DNS, Tailscale or a firewall between the cluster and `address` |
|
||||
| `SSHHandshakeFailed` | the host key is missing from known_hosts or has changed, or `user` rejected the key | the known_hosts entry; `user`'s `authorized_keys` |
|
||||
| `LibvirtConnectFailed` | SSH worked, the libvirt socket did not | `user` in the `libvirt` group, `libvirtd` running, the `socket` path |
|
||||
| `Timeout` | no answer within `--provider-check-timeout` (default 15s) | a hung `libvirtd` or a saturated link |
|
||||
| `PoolNotFound` | there is no pool named `pool` | `virsh pool-list --all` |
|
||||
| `PoolNotActive` | the pool exists but is not running | `virsh pool-start <pool>` and `virsh pool-autostart <pool>` |
|
||||
| `LibvirtError` | any other libvirt error | the message carries libvirt's own text |
|
||||
|
||||
Sharing the connection has two consequences:
|
||||
|
||||
- The leader now keeps one SSH connection per host open from startup, with a
|
||||
keepalive every 15s. Before, the first connection opened with the first KVM
|
||||
reconcile.
|
||||
- A check that hits its timeout drops the host's connection, just as a
|
||||
cancelled reconcile already does. Calls in flight on a hung link then fail
|
||||
fast, and the next call redials.
|
||||
|
||||
## Known gaps
|
||||
|
||||
- **No quota or capacity detection.** libvirt reports an out-of-space
|
||||
pool or an over-committed host as an ordinary error; the reconciler
|
||||
treats it as transient and retries with backoff rather than the slower
|
||||
quota backoff.
|
||||
quota backoff. The health check does report each pool's free space
|
||||
(`poolAvailable`), so a pool that is filling up shows before Creates
|
||||
start failing.
|
||||
- **A rotated `kvm-ssh` Secret needs a manager restart.** The key and
|
||||
known_hosts files are read on first use and cached for the life of the
|
||||
process. Replacing them in the Secret therefore changes nothing for
|
||||
later connections, health checks included. After a host key change, the
|
||||
check keeps reporting `SSHHandshakeFailed` until the manager restarts.
|
||||
- **Orphan volumes without a domain are invisible to GC.** A crash
|
||||
between creating the volumes and defining the domain leaves an overlay
|
||||
and seed that `ListByTag` cannot see (it lists domains). They are
|
||||
@@ -315,4 +363,6 @@ Unit tests run over an in-memory fake of the libvirt API. The optional
|
||||
integration test against a real host is described in
|
||||
[testing.md](testing.md#the-kvm-integration-test-real-hypervisor); its
|
||||
`-v` output includes the `libvirt call` trace above, at the verbosity
|
||||
`KVM_TEST_LOG_LEVEL` selects (default 1).
|
||||
`KVM_TEST_LOG_LEVEL` selects (default 1). `TestKVMCheck_realHost` runs the
|
||||
health check against the same host and creates nothing:
|
||||
`go test -tags=integration -count=1 -v -run TestKVMCheck ./internal/provider/kvm/`.
|
||||
|
||||
Reference in New Issue
Block a user