Skip to content

feat(robot): allow providing the actual IPv6 address of a Robot node #1338

Description

@Jakob3xD

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):

// GET /server/<number>
{
  "server": {
    "server_ip": "203.0.113.7",
    "server_ipv6_net": null,   // <--
    "product": "AX102",
    "dc": "HEL1-DC12",
    "ip": ["203.0.113.7"],
    "subnet": null,            // <-- no alternative source either
    "...": "..."
  }
}

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions