Skip to content

fix(net): health-check unmanaged-Site gateways through the tunnel - #990

Open
Semen Kolesnikov (Lotarcc) wants to merge 1 commit into
Azure:mainfrom
Lotarcc:fix/net-unmanaged-gateway-healthcheck-v2
Open

Semen Kolesnikov (Lotarcc) wants to merge 1 commit into
Azure:mainfrom
Lotarcc:fix/net-unmanaged-gateway-healthcheck-v2

Conversation

@Lotarcc

@Lotarcc Semen Kolesnikov (Lotarcc) commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Follow-up to #926, for the health-check note in its review. Since #926, remote nodes program
gateways in a Site with manageCniPlugin: false even without a pod CIDR, but
registerPeersWithHealthCheck still skips them because they have no overlay address. They are never
health-checked or failed over. This replaces #931, rebased on main after #943.

Probing the gateway's internal IP over the underlay is not an option: firewalls between Sites
typically allow only the encapsulation (GENEVE), not the health-check port, so the gateway would be
marked down.

These gateways are now probed at their internal IPv4 address out of unbounded0:

  • healthcheck.Manager.AddPeerVia sets the outgoing interface per packet (IP_PKTINFO), so the
    probe leaves through unbounded0 without a kernel route and replies still reach the shared
    socket. The interface index is cached and refreshed after a failed send.
  • The remote node pins the gateway's IP in the BPF map (no route) when localCidrs keep it out, as
    a single nexthop, so probes keep flowing while the gateway is down and it can recover.
  • Only when this node has an IPv4 overlay address to probe from; IPv6 has no on-link fallback
    without a route, so IPv6-only gateways are still not probed.

It also corrects the #926 comments that said such a gateway never gets a podCIDR: an explicit
assignmentEnabled: true can still assign one, and the gateway is then probed at its overlay
address as before.

Lab (kind, unmanaged Calico Site with an Internal gateway pool, remote managed Site over GENEVE, main
at ae6dfab, UDP 9997 dropped on every node's underlay):

Step Gateway health on remote, main with this PR
baseline not checked Up
GENEVE from the remote dropped at the gateway not checked Down after ~40s, BPF entries unhealthy
GENEVE restored not checked Up after ~75s, BPF entries healthy

Remote <-> gateway and remote -> member pod traffic is unchanged. Lab runs disable the #964
neighbor tuner, which kind's network namespace does not support.

Not changed: nodes inside the unmanaged Site have no overlay address either, so they still do not
health-check their own gateways.

Part of #921.

Testing: TestManagerProbesViaInterface, TestSessionWriteViaUnknownInterface,
TestAddPeerViaKeepsSessionWhenUnchanged, TestAddPeerViaReplacesSessionWhenInterfaceChanges,
TestGatewayHealthTarget, TestGatewayProbePins, TestRegisterUnmanagedGatewayHealthCheck;
go test ./cmd/unbounded-net-node/ ./internal/net/healthcheck/ ./internal/net/netlink/ on Linux;
golangci-lint on the changed packages; lab scenario above.

@Lotarcc
Semen Kolesnikov (Lotarcc) requested a review from a team October 23, 2026 08:14
@Lotarcc

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service terminate

@Lotarcc

Copy link
Copy Markdown
Contributor Author

@microsoft-github-policy-service agree

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant