Plan: lab1 workers on pv1-2 via per-node template copy
Session note on CAPMOX v0.9.1 against the 2-node PVE cluster, the plan and its execution log. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
# Session: CAPMOX against a two-node PVE cluster
|
||||
|
||||
**Date:** 2026-09-29 23:11 CEST
|
||||
|
||||
## Question
|
||||
|
||||
`pv1-1` became the PVE cluster `homelab`, and a second node `pv1-2` joined it. Does the CAPI/CAPMOX
|
||||
configuration need changes to work against the cluster?
|
||||
|
||||
## What was checked
|
||||
|
||||
- PVE API (read-only GETs with the `capmox@pve!capi` token, 2026-09-29): `/cluster/status`,
|
||||
`/nodes`, `/storage`, `/nodes/<n>/network`, `/nodes/<n>/storage`, `/cluster/resources`,
|
||||
`/access/acl`.
|
||||
- CAPMOX v0.9.1 source (Go proxy zip): scheduler, clone path, template lookup,
|
||||
`templates/cluster-template.yaml`.
|
||||
- PVE `qemu-server` `PVE/API2/Qemu.pm` (HEAD, not pinned to a PVE release): the clone target check.
|
||||
|
||||
## Findings
|
||||
|
||||
PVE state:
|
||||
|
||||
| Item | pv1-1 | pv1-2 |
|
||||
| --- | --- | --- |
|
||||
| IP | 192.168.0.8 | 192.168.0.10 |
|
||||
| CPU / RAM | 16 / 29.2 GiB | 12 / 40.9 GiB |
|
||||
| `vmbr0` VLAN-aware | yes | **no** |
|
||||
| `local-lvm` | local LVM-thin | local LVM-thin (not shared) |
|
||||
| Templates | 101 `ubuntu-2404-kube-v1.35.9`, 9000, 9001 | none |
|
||||
|
||||
- Storage definitions (`local`, `local-lvm`, `proxy-seeds`) are cluster-wide without a `nodes`
|
||||
restriction, but none of them is shared.
|
||||
- The `capmox@pve` ACLs (`/`, `/storage`, `/sdn/zones/localnetwork`) are cluster-wide, so they
|
||||
cover `pv1-2` as well. There are no SDN zones.
|
||||
|
||||
CAPMOX v0.9.1:
|
||||
|
||||
- **Node choice.** If the ProxmoxMachine has its own `allowedNodes`, that list replaces the
|
||||
ProxmoxCluster's (`internal/service/scheduler/vmscheduler.go:52-62`).
|
||||
- The scheduler balances by how many machines of this cluster are already on each node
|
||||
(`status.nodeLocations`), and only picks a node where the requested memory fits
|
||||
(`vmscheduler.go:75-119`).
|
||||
- `memoryAdjustment` is applied per node, against that node's own total memory.
|
||||
- With empty `allowedNodes` the scheduler isn't called and the VM clones on the source node
|
||||
(`internal/service/vmservice/vm.go:477`).
|
||||
- **Clone.** `target` goes to the PVE clone call as-is (`pkg/proxmox/goproxmox/api_client.go:84-95`).
|
||||
- PVE refuses a cross-node clone when any source disk is on non-shared storage:
|
||||
`can't clone VM to node '<target>' (VM uses local storage)`.
|
||||
- Setting `full: true` or `storage` does not change that.
|
||||
- v0.9.1 has no `localStorage` option.
|
||||
- **`templateSelector`** searches the whole PVE cluster and needs exactly one match
|
||||
(`api_client.go:149-212`). "One template per node with the same tags" fails with
|
||||
`found 2 VM templates`.
|
||||
- **API URL and credentials.** Everything goes through one API URL; nothing in the credentials
|
||||
names a node.
|
||||
- Cross-node requests should be forwarded by PVE (standard PVE behaviour, not checked in code).
|
||||
- `192.168.0.8` is `pv1-1`, so a down `pv1-1` also means no API for CAPMOX.
|
||||
- **Bridge.** `bridge`/`vlan` are written into `netX` without any check (`vm.go:338`).
|
||||
|
||||
Conclusion:
|
||||
|
||||
- Nothing has to change for the current setup to keep working. `lab1` pins `allowedNodes: [pv1-1]`
|
||||
and `sourceNode: pv1-1`, which is decision #7.
|
||||
- Using `pv1-2` requires two things:
|
||||
1. Make `vmbr0` on `pv1-2` VLAN-aware and trunk VLAN 4 on its switch port.
|
||||
2. Either put a template copy on `pv1-2`, or add shared storage.
|
||||
- With a template copy per node:
|
||||
- Workers get one ProxmoxMachineTemplate and one MachineDeployment per PVE node, each with
|
||||
`sourceNode`, `templateID` (the node's own VMID) and `allowedNodes: [<node>]`. For
|
||||
cluster-autoscaler that is one node group per PVE node.
|
||||
- KubeadmControlPlane takes a single infrastructureRef, so the control plane stays on one node.
|
||||
|
||||
## Open questions
|
||||
|
||||
- How to get the template onto `pv1-2`: a second image-builder run (`PROXMOX_NODE=pv1-2`), or
|
||||
`qm clone` + `qm migrate` / vzdump-restore? The image-builder run is reproducible; the copy is
|
||||
faster.
|
||||
- Is shared storage (NFS) worth adding instead? It gives one MachineDeployment spread over both
|
||||
nodes, and the control plane can use both nodes too.
|
||||
- Behaviour when a cross-node clone fails: the scheduler may keep picking the same node. This is
|
||||
inferred from the code, not tested.
|
||||
|
||||
## Follow-ups
|
||||
|
||||
- The owner chose: no shared storage for now; copy template 101 to `pv1-2` as 9101; keep
|
||||
`lab1-workers` and add `lab1-workers-pv1-2`. Plan:
|
||||
[2026-09-29-2315-pv1-2-workers](../plans/2026-09-29-2315-pv1-2-workers.md). It covers the bridge
|
||||
fix, the template copy, the second MD, the CA limits and a decision row superseding #7.
|
||||
- Update the "Lab facts" in CLAUDE.md/AGENTS.md: PVE cluster `homelab`, `pv1-2` at 192.168.0.10.
|
||||
Reference in New Issue
Block a user