Compare commits

...
Author SHA1 Message Date
claude-botandClaude Opus 5.5 be643533f6 feat(talos): node IP and etcd on VLAN 46 (#576 step 3)
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
Records the live state after moving all three nodes:
- site-homelab.yaml: kubelet nodeIP.validSubnets fd02:46::/64 and
  10.2.46.0/24 (was 10.2.40.0/24 and the legacy fd40::/64).
- cluster.yaml: etcd advertisedSubnets 10.2.46.0/24.
- mgmt0 comments: VLAN 40 is world-to-node only now.

Applied per node (k8s-3, k8s-2, k8s-1): drain, stage the config (delete
the old lists, set the new ones, one staged patch call), etcd
forfeit-leadership and leave, reboot. Each node rejoined etcd with its
VLAN 46 peer URL; EPHEMERAL was not wiped.

Refs #576

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 14:43:17 +02:00
k.renner 311b4639a6 Merge pull request 'feat(bird): put node0 in the pod routing table (#576 step 2)' (#919) from feat/bird-attached-node0 into master
ci/woodpecker/cron/e2e Pipeline failed
ci/woodpecker/cron/security-scan Pipeline was successful
ci/woodpecker/cron/issue-fix Pipeline was successful
ci/woodpecker/cron/alert-monitor Pipeline was successful
Reviewed-on: k.renner/homelab#919
2026-09-23 11:31:32 +00:00
k.renner a95efdef33 Merge pull request 'feat(talos): node network on VLAN 46, etcd pinned to VLAN 40 (#576 step 1)' (#918) from feat/node-vlan-46-link into master
Reviewed-on: k.renner/homelab#918
2026-09-23 11:31:23 +00:00
claude-botandClaude Opus 5.5 07dd6097ec feat(talos): node network on VLAN 46, etcd pinned to VLAN 40 (#576 step 1)
ci/woodpecker/pr/ci-scripts-test Pipeline was successful
ci/woodpecker/pr/ci-manifests-test Pipeline was successful
ci/woodpecker/pr/pr-review Pipeline was successful
- node0: VLANConfig on the uplink trunk, VLAN 46, static fd02:46::1x/64
  and 10.2.46.1x/24, accept_ra 0. Closed like pod0. Unused until the node
  IP moves there (step 3).
- cluster.etcd.advertisedSubnets pinned to 10.2.40.0/24 so a reboot
  cannot pick a node0 address: Talos never updates an existing member's
  peer URLs.

Applied live with talosctl patch --mode=no-reboot, k8s-3 first. Node IPs
unchanged, etcd 3/3 healthy, node0 reachable node to node over v6 and v4.

Refs #576

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-23 13:25:12 +02:00
5 changed files with 55 additions and 14 deletions
+6
View File
@@ -58,6 +58,12 @@ machine:
imageGCHighThresholdPercent: 70
imageGCLowThresholdPercent: 60
cluster:
# etcd peers on node0, VLAN 46 (#576). Pinned: Talos never updates an
# existing member's peer URLs, so changing this subnet means leave + rejoin
# per member (talosctl etcd leave, reboot).
etcd:
advertisedSubnets:
- 10.2.46.0/24
# controlPlane.endpoint is NOT here: `talosctl gen config` takes it as its
# second argument, and bootstrap.sh already passes https://k8s.renner.uno:6443
# there. Setting it again in this patch restated the same value in a second
+17 -2
View File
@@ -17,6 +17,8 @@ machine:
# pod0 is a closed L2 fabric between the three nodes: statically
# addressed, no gateway, nothing to learn from an RA.
net.ipv6.conf.pod0.accept_ra: "0"
# node0 is closed the same way.
net.ipv6.conf.node0.accept_ra: "0"
# ingress0 keeps RAs, at the default accept_ra of 2: an IPv6 default
# router is a link-local address learned only from the RA, and with
# net.ipv6.conf.all.forwarding=1 — which Cilium sets — Linux ignores RAs
@@ -122,8 +124,8 @@ kind: LinkConfig
name: uplink
up: true
---
# Management, VLAN 40. Carries the node IP, etcd, the API and Ceph's public
# network.
# Management, VLAN 40: world↔node. The API VIP, admin access to the nodes, and
# node egress (DNS, NTP, image pulls). Node↔node traffic is on node0 (#576).
apiVersion: v1alpha1
kind: VLANConfig
name: mgmt0
@@ -177,6 +179,19 @@ addresses:
- address: 10.2.48.11/24
- address: fd02:48::11/64
---
# Node network, VLAN 46: traffic among the three nodes themselves (#576) — the
# node IP, etcd, apiserver↔kubelet. Closed like pod0: statically addressed, no
# gateway, never routed via the UDM.
apiVersion: v1alpha1
kind: VLANConfig
name: node0
vlanID: 46
parent: uplink
up: true
addresses:
- address: fd02:46::11/64
- address: 10.2.46.11/24
---
# Ingress network, VLAN 47. World-to-pod: the BGP session, the next hop for
# every advertised LoadBalancer VIP, and the masquerade source for pod egress.
# Publicly routed, which is what separates it from pod0.
+13 -1
View File
@@ -16,6 +16,7 @@ machine:
# ingress0 keeps RAs: it learns its IPv6 router and its address from them,
# and only the default route is held back — see k8s-1.yaml.
net.ipv6.conf.pod0.accept_ra: "0"
net.ipv6.conf.node0.accept_ra: "0"
net.ipv6.conf.ingress0.accept_ra_defrtr: "0"
# Answer ARP only on the link that owns the address — see k8s-1.yaml (#793).
net.ipv4.conf.all.arp_ignore: "1"
@@ -82,7 +83,7 @@ kind: LinkConfig
name: uplink
up: true
---
# Management, VLAN 40. Node IP, etcd, the API and Ceph's public network.
# Management, VLAN 40: world↔node — see k8s-1.yaml.
apiVersion: v1alpha1
kind: VLANConfig
name: mgmt0
@@ -122,6 +123,17 @@ addresses:
- address: 10.2.48.12/24
- address: fd02:48::12/64
---
# Node network, VLAN 46 — see k8s-1.yaml.
apiVersion: v1alpha1
kind: VLANConfig
name: node0
vlanID: 46
parent: uplink
up: true
addresses:
- address: fd02:46::12/64
- address: 10.2.46.12/24
---
# Ingress network, VLAN 47. World-to-pod, publicly routed, statically
# addressed — see k8s-1.yaml for why it is not leased.
apiVersion: v1alpha1
+12
View File
@@ -12,6 +12,7 @@ machine:
# ingress0 keeps RAs: it learns its IPv6 router and its address from them,
# and only the default route is held back — see k8s-1.yaml.
net.ipv6.conf.pod0.accept_ra: "0"
net.ipv6.conf.node0.accept_ra: "0"
net.ipv6.conf.ingress0.accept_ra_defrtr: "0"
# Answer ARP only on the link that owns the address — see k8s-1.yaml (#793).
net.ipv4.conf.all.arp_ignore: "1"
@@ -109,6 +110,17 @@ addresses:
- address: 10.2.48.13/24
- address: fd02:48::13/64
---
# Node network, VLAN 46 — see k8s-1.yaml.
apiVersion: v1alpha1
kind: VLANConfig
name: node0
vlanID: 46
parent: uplink
up: true
addresses:
- address: fd02:46::13/64
- address: 10.2.46.13/24
---
# Ingress network, VLAN 47. World-to-pod, publicly routed, statically
# addressed — see k8s-1.yaml for why it is not leased.
apiVersion: v1alpha1
+7 -11
View File
@@ -7,19 +7,15 @@
# part of the config that could not be true anywhere but here.
machine:
kubelet:
# Constrain kubelet's auto-picked node IP to the mgmt LAN. Without this,
# kubelet picks the first non-loopback IP, which could land on the v30iot
# NIC (ens19, 10.2.30.0/24). Control-plane traffic and hostNetwork pod IPs
# must stay on mgmt LAN.
# fd40::/64 is the mgmt LAN ULA, and it is listed so the Node object carries
# an IPv6 InternalIP at all. Without one, Cilium falls back to detecting the
# node's IPv6 from mgmt0 and picks the SLAAC address from the dynamic
# provider prefix, which it then probes until the agent restarts (#789).
# The GUA is not a control-plane address: BGP peers on fd40::/64 too.
# The node IP lives on node0, VLAN 46: the closed node↔node network (#576).
# Both families are listed so the Node object carries an IPv6 InternalIP at
# all; without one Cilium detects the node's IPv6 itself and picks a SLAAC
# address from the dynamic provider prefix (#789). Talos picks one address
# per family, IPv4 first, whatever the order here.
nodeIP:
validSubnets:
- 10.2.40.0/24
- fd40::/64
- fd02:46::/64
- 10.2.46.0/24
# The UDM on the ingress segment. Published here rather than as a route
# because bird owns table 47 and originates the default from it; this is the
# one place the address is stated.