[technitium] zone-sync now reconciles primaryNameServerAddresses
When a zone is created against a stale primary IP (e.g. the old primary pod IP 10.10.36.189 before the technitium-primary ClusterIP service existed), AXFR refresh keeps failing forever while every other zone on the same replica refreshes fine from 10.110.37.186. The resync-only branch didn't touch zone options, so the bad IP was pinned indefinitely. This surfaced as rpi-sofia.viktorbarzin.lan returning 192.168.1.16 (pre-move) on secondaries while primary had the correct .10 from 2026-04-22 morning — Uptime Kuma Sofia RPI monitor DOWN, cluster cluster_healthcheck FAIL. The sync loop now re-applies primaryNameServerAddresses on every run for existing zones. Idempotent — Technitium accepts identical values — and self-heals any drift within 30 min. Env renamed PRIMARY_IP → PRIMARY_HOST for consistency with the reconcile semantics. Hostname form (technitium-primary.technitium.svc.cluster.local) was tried but Technitium's own resolver doesn't forward svc.cluster.local, so the field must stay a literal IP. Terraform tracks the ClusterIP on every apply and the reconcile loop propagates it to replicas.
This commit is contained in:
parent
7dfe89a6e0
commit
f1f723be83
1 changed files with 15 additions and 3 deletions
|
|
@ -434,12 +434,17 @@ resource "kubernetes_cron_job_v1" "technitium_zone_sync" {
|
|||
|
||||
while read -r zone; do
|
||||
if grep -qx "$zone" /tmp/replica_zones.txt; then
|
||||
# Zone exists — just resync
|
||||
# Zone exists — reconcile primaryNameServerAddresses to the
|
||||
# stable FQDN before resync. Without this, a zone created
|
||||
# against an old pod IP (pre-service-ClusterIP era) stays
|
||||
# pinned to that dead IP forever and zone transfers fail
|
||||
# silently. Idempotent — Technitium accepts identical values.
|
||||
curl -sf "$REPLICA/api/zones/options/set?token=$R_TOKEN&zone=$zone&primaryNameServerAddresses=$PRIMARY_HOST" > /dev/null || true
|
||||
curl -sf "$REPLICA/api/zones/resync?token=$R_TOKEN&zone=$zone" > /dev/null || true
|
||||
else
|
||||
# New zone — create as Secondary and validate response
|
||||
echo "NEW: Creating $zone on $REPLICA"
|
||||
RESP=$(curl -sf "$REPLICA/api/zones/create?token=$R_TOKEN&zone=$zone&type=Secondary&primaryNameServerAddresses=$PRIMARY_IP" || echo '{"status":"error"}')
|
||||
RESP=$(curl -sf "$REPLICA/api/zones/create?token=$R_TOKEN&zone=$zone&type=Secondary&primaryNameServerAddresses=$PRIMARY_HOST" || echo '{"status":"error"}')
|
||||
if echo "$RESP" | grep -q '"status":"ok"'; then
|
||||
SYNCED=$((SYNCED + 1))
|
||||
else
|
||||
|
|
@ -486,7 +491,14 @@ resource "kubernetes_cron_job_v1" "technitium_zone_sync" {
|
|||
value = var.technitium_password
|
||||
}
|
||||
env {
|
||||
name = "PRIMARY_IP"
|
||||
# Service ClusterIP — Terraform tracks it on every apply, and the
|
||||
# reconcile loop below re-applies it to every existing zone on
|
||||
# every run (*/30m), so any drift (e.g. service recreate → new
|
||||
# ClusterIP, or historical pod-IP values still pinned on replicas)
|
||||
# self-heals within a sync cycle. Hostname form was tried but
|
||||
# Technitium's own resolver doesn't forward svc.cluster.local,
|
||||
# so `primaryNameServerAddresses` must be a literal IP.
|
||||
name = "PRIMARY_HOST"
|
||||
value = kubernetes_service.technitium_primary.spec[0].cluster_ip
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue