Skip to content

Drill the failover gap of one pool address in front of two replicas #372

Closed

Description

@ExtraToast

What to do

Measure how long DNS goes unanswered when the node that announces a pool address fails, with two replicas behind that one address. Decide which conditions on the settled decisions change the model accepts that a Process spread across nodes behind a pool address is failover and not load sharing, on the condition that the gap is measured before the utility Project hands over.

In layer 2 mode all traffic for an address goes to one node, and under the Local traffic policy a replica on another node receives none. MetalLB documents failover after a node failure as "within a few seconds", and a client that caches the old hardware address waits longer (docs/research/unsupported-claims.md, claim C18). adguard-ha answers the same failure in the client today, with two addresses in the router. One address replaces that, so the whole LAN's DNS depends on this gap.

The drill needs a client on the Enschede LAN and stops a pod and then a node, so it is run with the maintainer present, against a throwaway Service on a spare pool address.

  1. Run two replicas of a UDP responder on two Enschede nodes, behind one LoadBalancer Service with the Local traffic policy.
  2. From a LAN client, query the address several times a second and log every answer with its time.
  3. Delete the pod on the announcing node. Record the gap.
  4. Stop the announcing node, or its speaker and its pod together. Record the gap, from a client that held the old hardware address.
  5. Remove the Service and the workload.

Done when

  • The gap is recorded for a pod failure and for a node failure.
  • The result is posted here: either the gap is acceptable for DNS, or the number is given so the one-address decision can be reopened.
  • Nothing the drill created is left in the cluster.

Notes

This runs before the utility Project (adguard-ha) hands over. It sits outside the map Map: re-establish deploy-kit's goals, rewrite its spec, and order the work until the estate is handed over, which is not held up by it.

Activity

  1. added
    type: choreMaintenance work without intended behavior change.
    area: deployhomelab-deploy, deploy-v2, manifests, and rollout flow.
    component: deployDeployment pipeline, manifests, or release rollout.
    priority: P2Medium; normal planned work.
    on Oct 12, 2026
  2. ExtraToast commented on Oct 29, 2026

    @ExtraToast
    ContributorAuthor

    Warning

    The node-failure row and the verdict below are invalid. The drill's link cut on enschede-pi-3 never ran: its pod started three minutes late, after the drill had taken one stray lost query for the outage. pi-3 answered on both sides of that query, and Kubernetes never marked it NotReady. The pod-failure row (6.6 s) stands. A corrected run follows.

    Drill result: the failover gap of one pool address in front of two replicas

    Run 372-20261029T112700Z of drills/pool-address-failover.sh (estate a316c8b, with local changes), against kubectl context personal, 2026-10-29 11:27–11:40 UTC.

    Two CoreDNS responders on enschede-pi-3 and enschede-pi-2, behind one LoadBalancer Service at 192.168.0.93 (pool drill-372) with externalTrafficPolicy: Local. A LAN client (192.168.0.204 on en0) asked version.bind every 100 ms with a 250 ms timeout; every answer names the node that gave it.

    failure answered by, before → after gap unanswered queries
    pod on enschede-pi-3 deleted enschede-pi-3 → enschede-pi-2 6.6 s 26
    enschede-pi-3 off the network not measured: the node never went off the network — —
    • The client's ARP entry for 192.168.0.93 went from none to none across the node failure.
    • Kubernetes marked enschede-pi-3 NotReady not at all while it was off.
    • The gap runs from the last answer before the failure to the first answer after it; the full log is probe.log in the run's record.

    Verdict: pending the corrected node-failure run.

    Done when

    • The gap is recorded for a pod failure and for a node failure.
    • The result is posted here.
    • Nothing the drill created is left in the cluster.
  3. ExtraToast commented on Oct 29, 2026

    @ExtraToast
    ContributorAuthor

    Drill result: the failover gap of one pool address in front of two replicas

    Run 372-20261029T115711Z of drills/pool-address-failover.sh (estate b8b9a48), against kubectl context personal, 2026-10-29 11:57–12:07 UTC.

    Two CoreDNS responders on enschede-pi-3 and enschede-pi-2, behind one LoadBalancer Service at 192.168.0.93 (pool drill-372) with externalTrafficPolicy: Local. A LAN client (192.168.0.204 on en0) asked version.bind every 100 ms with a 250 ms timeout; every answer names the node that gave it.

    failure answered by, before → after gap unanswered queries
    pod on enschede-pi-3 deleted enschede-pi-3 → enschede-pi-2 5.3 s 21
    enschede-pi-3 off the network enschede-pi-3 → enschede-pi-2 6.6 s 26
    • Kubernetes marked enschede-pi-3 NotReady 50s after it was taken off.
    • The gap runs from the last answer before the failure to the first answer after it; the full log is probe.log in the run's record.

    Verdict: the gap is acceptable for DNS; one pool address in front of two replicas stands as failover.

    Done when

    • The gap is recorded for a pod failure and for a node failure.
    • The result is posted here.
    • Nothing the drill created is left in the cluster.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: deployhomelab-deploy, deploy-v2, manifests, and rollout flow.component: deployDeployment pipeline, manifests, or release rollout.priority: P2Medium; normal planned work.type: choreMaintenance work without intended behavior change.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions