What happened
On bare-metal (Cluster API Provider Metal3 / Ironic), Machine.status.addresses includes the node's kernel-assigned IPv6 link-local address with a zone identifier, e.g. fe80::5054:ff:fe07:37d1%enp1s0, alongside the usable IPv4 (192.168.122.29). CACPPT builds a Talos client endpoint from all of those addresses and fails:
failed to create client connection: parse "dns:///talosroundrobin:///192.168.122.29:50000,[fe80::5054:ff:fe07:37d1%enp1s0]:50000": invalid URL escape "%en"
The zone-scoped address (%enp1s0) is not a valid URL component, so the parse fails and CACPPT can never reach the control plane — it loops on bootstrap failed/failed to get kubeconfig even though the cluster itself is healthy (etcd up, apiserver serving).
Where
controllers/configs.go (talosconfigForMachines) appends every MachineInternalIP/MachineExternalIP to addrList and passes them to talosclient.WithEndpoints(addrList...), which wraps each in a dns:///…:50000 gRPC target. The same unfiltered pattern appears in taloscontrolplane_controller.go and etcd.go. There is no link-local / zone handling.
Expected
CACPPT should skip IPv6 link-local addresses (net.IP.IsLinkLocalUnicast()), or at least strip the %zone identifier, before building the endpoint list — so a Machine that happens to carry a fe80::…%zone address (the kernel default on any NIC) doesn't break control-plane management.
Environment / repro
- CAPI v1.13.2, CAPM3/Ironic v1.13.0 (Metal3, bare-metal), CACPPT v0.5.13 / CABPT v0.6.12, Talos v1.13.3.
- Provision a Talos control-plane node on a NIC with a kernel-default IPv6 link-local. CAPM3 copies the BMH's inspected NIC addresses (incl.
fe80::…%enp1s0) into Machine.status.addresses; CACPPT then fails as above.
Suggested fix
Filter net.IP.IsLinkLocalUnicast() (and strip the %zone suffix) before talosclient.WithEndpoints(...) in controllers/configs.go (and the analogous spots in taloscontrolplane_controller.go / etcd.go). Happy to open a PR if this direction looks right.
What happened
On bare-metal (Cluster API Provider Metal3 / Ironic),
Machine.status.addressesincludes the node's kernel-assigned IPv6 link-local address with a zone identifier, e.g.fe80::5054:ff:fe07:37d1%enp1s0, alongside the usable IPv4 (192.168.122.29). CACPPT builds a Talos client endpoint from all of those addresses and fails:The zone-scoped address (
%enp1s0) is not a valid URL component, so the parse fails and CACPPT can never reach the control plane — it loops onbootstrap failed/failed to get kubeconfigeven though the cluster itself is healthy (etcd up, apiserver serving).Where
controllers/configs.go(talosconfigForMachines) appends everyMachineInternalIP/MachineExternalIPtoaddrListand passes them totalosclient.WithEndpoints(addrList...), which wraps each in adns:///…:50000gRPC target. The same unfiltered pattern appears intaloscontrolplane_controller.goandetcd.go. There is no link-local / zone handling.Expected
CACPPT should skip IPv6 link-local addresses (
net.IP.IsLinkLocalUnicast()), or at least strip the%zoneidentifier, before building the endpoint list — so a Machine that happens to carry afe80::…%zoneaddress (the kernel default on any NIC) doesn't break control-plane management.Environment / repro
fe80::…%enp1s0) intoMachine.status.addresses; CACPPT then fails as above.Suggested fix
Filter
net.IP.IsLinkLocalUnicast()(and strip the%zonesuffix) beforetalosclient.WithEndpoints(...)incontrollers/configs.go(and the analogous spots intaloscontrolplane_controller.go/etcd.go). Happy to open a PR if this direction looks right.