TL;DR
HCCM derives the IPv6 ExternalIP of a Robot node as <server_ipv6_net> + "1". This assumes both that Robot knows the server's IPv6 subnet, and that the host uses ::1 within it. Neither holds in general, and there is currently no way to tell HCCM which address the node actually uses.
Expected behavior
A Robot node should be able to end up with its real IPv6 address in .status.addresses.
There are two situations where the derived address is wrong today:
1. server_ipv6_net is empty.
Robot models IPv6 as one /64 per server. In setups where IPv6 is not managed per server — for example when a single /64 is configured on upstream network equipment and individual hosts take addresses out of it — Robot has nothing to report, and the field is null for every affected server (which the Go client decodes to the empty string):
Today HCCM appends "1" to that empty string and writes the literal address "1" to the Node. #1337 fixes the invalid value, but the result is then simply that the node has no IPv6 ExternalIP at all, with no way to supply the correct one.
2. The host does not use ::1.
A Robot server is assigned a /64 and the operator may configure any address out of it. HCCM hardcodes the ::1 host address, so a server configured with, say, ::2 is given an ExternalIP it does not answer on. The Robot API does not expose which address is actually configured on the server.
The Cloud code path does not have this problem, because the Cloud API reports the server's address rather than a subnet from which the address has to be guessed.
Possible solutions
a) Preserve an existing IPv6 ExternalIP from the Node object when server_ipv6_net is empty.
robotNodeAddresses already forwards InternalIPs from the Node object (ROBOT_FORWARD_INTERNAL_IPS, #865). Applying the same idea to the IPv6 ExternalIP, but only for the case where HCCM cannot derive one itself, would stay unambiguous: HCCM keeps precedence whenever Robot has data, and falls back to what is already on the Node only when it has none.
This needs no new configuration surface, covers situation 1, and composes with #1337, which makes HCCM emit nothing in exactly that case.
b) A Node annotation that overrides the derived address, e.g. instance.hetzner.cloud/robot-external-ipv6.
This additionally covers situation 2 and makes the intent explicit rather than inferred, at the cost of new API surface — HCCM currently reads annotations on Services only, never on Nodes.
c) --node-ip was considered and does not solve it: the kubelet accepts at most one address per family, and in dual-stack clusters that slot is typically already taken by the node's InternalIP. It also expresses an InternalIP rather than an ExternalIP. An address that HCCM does not also report causes node initialization to fail outright (failed to get node address from cloud provider that matches ip, see #647).
Additional information
TL;DR
HCCM derives the IPv6
ExternalIPof a Robot node as<server_ipv6_net>+"1". This assumes both that Robot knows the server's IPv6 subnet, and that the host uses::1within it. Neither holds in general, and there is currently no way to tell HCCM which address the node actually uses.Expected behavior
A Robot node should be able to end up with its real IPv6 address in
.status.addresses.There are two situations where the derived address is wrong today:
1.
server_ipv6_netis empty.Robot models IPv6 as one /64 per server. In setups where IPv6 is not managed per server — for example when a single /64 is configured on upstream network equipment and individual hosts take addresses out of it — Robot has nothing to report, and the field is
nullfor every affected server (which the Go client decodes to the empty string):Today HCCM appends
"1"to that empty string and writes the literal address"1"to the Node. #1337 fixes the invalid value, but the result is then simply that the node has no IPv6ExternalIPat all, with no way to supply the correct one.2. The host does not use
::1.A Robot server is assigned a /64 and the operator may configure any address out of it. HCCM hardcodes the
::1host address, so a server configured with, say,::2is given anExternalIPit does not answer on. The Robot API does not expose which address is actually configured on the server.The Cloud code path does not have this problem, because the Cloud API reports the server's address rather than a subnet from which the address has to be guessed.
Possible solutions
a) Preserve an existing IPv6
ExternalIPfrom the Node object whenserver_ipv6_netis empty.robotNodeAddressesalready forwardsInternalIPs from the Node object (ROBOT_FORWARD_INTERNAL_IPS, #865). Applying the same idea to the IPv6ExternalIP, but only for the case where HCCM cannot derive one itself, would stay unambiguous: HCCM keeps precedence whenever Robot has data, and falls back to what is already on the Node only when it has none.This needs no new configuration surface, covers situation 1, and composes with #1337, which makes HCCM emit nothing in exactly that case.
b) A Node annotation that overrides the derived address, e.g.
instance.hetzner.cloud/robot-external-ipv6.This additionally covers situation 2 and makes the intent explicit rather than inferred, at the cost of new API surface — HCCM currently reads annotations on Services only, never on Nodes.
c)
--node-ipwas considered and does not solve it: the kubelet accepts at most one address per family, and in dual-stack clusters that slot is typically already taken by the node'sInternalIP. It also expresses anInternalIPrather than anExternalIP. An address that HCCM does not also report causes node initialization to fail outright (failed to get node address from cloud provider that matches ip, see #647).Additional information
HCLOUD_INSTANCES_ADDRESS_FAMILY=ipv6ordualstack; the defaultipv4never enters this code path."1"address whenserver_ipv6_netis empty), Robot Servers InternalIP is not set in node manifest #760 / feat(robot): forward InternalIPs by default on Robot nodes #865 (InternalIPforwarding for Robot nodes), CCM failed to get node address from cloud provider that matches IPv6 #647 (node-ip matching failure).subnet[]array alongsideserver_ipv6_net, which HCCM does not currently read. It isnullon the servers affected here, so it is not a usable fallback — there is no other field in the API response that HCCM could derive the address from.