Watchdog journals on proxy-1/proxy-2 for the morning roll, plus a
controlled experiment (three routing-peer kills probed from proxy-2 at
2 s; the LAN cannot probe this path, the UDM hairpin-DNATs the proxy
addresses to the VIP):
- a pinned-peer loss wedges the whole proxy process; the flood watchdog
restarts it within 2 s, the probe sees one failed round (~3 s)
- inside the flood watchdog 600 s cooldown the restart is suppressed and
the URL watchdog needs three one-minute rounds: 3.5 min of 000 on every
public domain, measured; the morning k8s-2 roll hit the same suppression
- subnet-target services: HTTP mode + IP target -> Host header is the IP,
Traefik 404; HTTP mode + domain target -> SERVFAIL, no mesh DNS on the
proxy; TLS passthrough (mode tls, listen_port 443) + subnet target works
end to end and coexists on 443 -- but dies with the wedge as long as any
domain resource exists
Stage 5 rewritten: 5a cooldown 600->60 s (ships first), 5b identity
persistence as a hypothesis to measure, 5c all-passthrough as the
structural exit with its VIP reconciler cost. Side findings: proxy clocks
3 min slow, ACME on the v6-only member ~20 min late, no proxy syslog in
Loki.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Public traffic is distinguishable in the Traefik log (127.0.0.1 = the
netbird-ingress peer, 10.2.x = LAN); at that hour it was only the proxies
watchdog, a flat 4 req/min, so it doubles as a synthetic probe. It dropped
to 2, then 0, then back to 4 around the k8s-1 reboot, halved at k8s-3,
untouched at k8s-2: ~2 min of public blackout per roll whose peer the
proxies had pinned.
Mechanism is the one the repo already documents in the proxy watchdog
role: routes pinned to a peer identity, fresh identity per pod start,
upstream never rebinds, proxy serves 502 until its watchdog restarts it.
Stage 5 becomes the second PR: a StatefulSet with a persisted NetBird
state volume so a rescheduled peer returns as the same identity; a
deterministic proxy restart in the roll script as the stopgap; proxy
syslog into Loki to close the measurement gap.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Grounded in the 2026-09-07 SAN rollout: Traefik 5xx by router from Loki,
Cilium BGP Down/Up gaps, drain logs. The ingress served every request; the
5xx were single-replica backends and databases mid-move, doubled by pods
landing on the next drain target and by --disable-eviction skipping the
CNPG switchover. BGP was never on the traffic path (Local policy, endpoints
withdrawn during the drain).
Four stages by measured impact: drain procedure as a checked-in script
(cordon-next, no disable-eviction, Multus/OpenBao/Ceph gates), honest PDBs,
Traefik 3 replicas with anti-affinity/PDB/graceful stop, instances: 2 for
ha-pg and gf-pg.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Since the host-device rollout (#801) Rook cannot finish a CephCluster
reconcile: it runs a canary pod with OSD placement to read the cluster
CIDR off the attachment, the OSD on that node already holds the NIC, and
the canary fails "error adding container to network ceph-san" until the
15-minute discovery timeout, then the next reconcile repeats it. Under
macvlan the canary could sit beside the OSD; a whole-device attachment has
exactly one consumer per node.
Discovery is skipped when addressRanges.cluster is set (Rook: "if user
specifies CIDRs in the network config, that is the definitive source of
truth"). The value is what discovery produced and what ceph config already
holds, so no daemon changes. The old comment claiming addressRanges is
honoured only under provider: host was wrong — the CRD documents it for
host and multus.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Every node has a second, address-less NIC (enp87s0) up on the untagged
fallback network, which shares the mgmt VLAN's broadcast domain. With
the Linux default arp_ignore=0 the host answers ARP for the node IP from
that NIC too, so the UDM can learn 10.2.40.x against enp87s0's MAC.
Inbound IPv4 then arrives on a device Cilium is not attached to, never
reaches cil_from_netdev, and is routed straight back to the UDM by the
default route — a loop that made every IPv4 LoadBalancer VIP on the
affected node unreachable for 13.5 hours. IPv6 was untouched because
NDP only answers on the interface that owns the address.
The flux was measurable on all three nodes: an ARP request for a node
IP from a neighbour returned replies from two MACs. Which node's entry
had actually flipped at the UDM was a race, and it moved during the
diagnosis.
arp_ignore=1 answers only when the target address is configured on the
receiving interface; arp_announce=2 stops the host from sourcing ARP
from an interface that does not own the address. Applied live with
talosctl on all three nodes before this commit and verified with
enp87s0 up: each node now answers from its mgmt0 MAC only.
A node property, so it lives next to the existing enp87s0 sysctls in
each machine patch rather than in the site patch.
Refs #793, #576
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
All three OSD prepare jobs on the Hetzner rehearsal finished with zero
OSDs:
cephosd: skipping device "sdb1": ["Used by ceph-disk"]
The partition is exactly what the machine config asked for (PARTLABEL
r-ceph-osd, plain Linux partition type). ceph-volume rejects it anyway —
its ceph-disk-member test is `"ceph" in PARTLABEL or PARTTYPE in
ceph_disk_guids` (ceph_volume/util/device.py) — so any label containing
"ceph" reads as a legacy ceph-disk partition and is never provisioned.
Talos derives the label from the RawVolumeConfig name (r-<name>), so the
name changes: ceph-osd -> osd-data, label r-osd-data. This is why the
rebuild branch called it osd-data; the #798 review renamed it back for
symmetry with the node label without this failure being known.
Production is unaffected today: the MS-01 OSDs match on the by-id half of
devicePathFilter and no r-ceph-osd partition exists there. The partlabel
half is the migration target and would have failed on the first
repartitioned drive.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A cold rebuild stops permanently at the infrastructure Kustomization:
ServersTransport/crowdsec/crowdsec-lapi dry-run failed: no matches for
kind "ServersTransport" in version "traefik.io/v1alpha1"
Flux dry-runs the whole apply set, so this one unknown kind rejects all of
it — including the Traefik HelmRelease that installs the CRD. Measured on
the Hetzner rehearsal from master: zero HelmReleases, zero CRDs. The
public LAPI endpoint (2026-09-02) landed after the post-crds sweep and put
a traefik.io consumer back into the layer that creates traefik.io.
Phase 1 only adds the object under post-crds; crowdsec/lapi-ingress.yaml
keeps its copy until infrastructure-crds has applied once, because both
Kustomizations prune and a one-commit move deletes before the new owner
applies. Phase 2 removes the original.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.