fix: convert Technitium zone sync from one-time Job to CronJob
Secondary/tertiary DNS instances had no custom zones — only the primary had viktorbarzin.lan and viktorbarzin.me. The old setup Job ran once at deployment and never synced new zones. New CronJob runs every 30 minutes: - Gets all zones from primary - Enables zone transfer on primary - Creates missing zones as Secondary type on replicas - Resyncs existing zones via AXFR Fixes .lan resolution failures (2/3 queries returned NXDOMAIN). [ci skip] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c0a33b5157
commit
803cb5fd26
1 changed files with 73 additions and 66 deletions
|
|
@ -356,88 +356,95 @@ resource "kubernetes_pod_disruption_budget_v1" "technitium_dns" {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Setup Job — configures secondary + tertiary zones via Technitium REST API
|
# Setup Job — configures secondary + tertiary zones via Technitium REST API
|
||||||
resource "kubernetes_job" "technitium_secondary_setup" {
|
# Zone sync CronJob — replicates all primary zones to secondary/tertiary
|
||||||
|
# Runs every 30 minutes. Idempotent: skips zones that already exist on replicas.
|
||||||
|
resource "kubernetes_cron_job_v1" "technitium_zone_sync" {
|
||||||
metadata {
|
metadata {
|
||||||
name = "technitium-replica-setup"
|
name = "technitium-zone-sync"
|
||||||
namespace = kubernetes_namespace.technitium.metadata[0].name
|
namespace = kubernetes_namespace.technitium.metadata[0].name
|
||||||
}
|
}
|
||||||
spec {
|
spec {
|
||||||
backoff_limit = 5
|
schedule = "*/30 * * * *"
|
||||||
template {
|
successful_jobs_history_limit = 3
|
||||||
|
failed_jobs_history_limit = 3
|
||||||
|
concurrency_policy = "Forbid"
|
||||||
|
job_template {
|
||||||
metadata {}
|
metadata {}
|
||||||
spec {
|
spec {
|
||||||
restart_policy = "OnFailure"
|
backoff_limit = 2
|
||||||
container {
|
template {
|
||||||
name = "setup"
|
metadata {}
|
||||||
image = "curlimages/curl:latest"
|
spec {
|
||||||
command = ["/bin/sh", "-c", <<-SCRIPT
|
restart_policy = "OnFailure"
|
||||||
set -e
|
container {
|
||||||
PRIMARY="http://technitium-primary.technitium.svc.cluster.local:5380"
|
name = "zone-sync"
|
||||||
REPLICAS="http://technitium-secondary-web.technitium.svc.cluster.local:5380 http://technitium-tertiary-web.technitium.svc.cluster.local:5380"
|
image = "curlimages/curl:latest"
|
||||||
|
command = ["/bin/sh", "-c", <<-SCRIPT
|
||||||
|
set -e
|
||||||
|
PRIMARY="http://technitium-primary.technitium.svc.cluster.local:5380"
|
||||||
|
REPLICAS="http://technitium-secondary-web.technitium.svc.cluster.local:5380 http://technitium-tertiary-web.technitium.svc.cluster.local:5380"
|
||||||
|
|
||||||
# Wait for primary
|
# Login to primary
|
||||||
until curl -sf "$PRIMARY/api/user/login?user=$TECH_USER&pass=$TECH_PASS" -o /tmp/p.json; do echo "Waiting for primary..."; sleep 5; done
|
P_TOKEN=$(curl -sf "$PRIMARY/api/user/login?user=$TECH_USER&pass=$TECH_PASS" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
|
||||||
P_TOKEN=$(cat /tmp/p.json | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
|
if [ -z "$P_TOKEN" ]; then echo "ERROR: Cannot login to primary"; exit 1; fi
|
||||||
|
|
||||||
# Get zones from primary
|
# Get zones from primary (excluding default zones that don't need replication)
|
||||||
curl -sf "$PRIMARY/api/zones/list?token=$P_TOKEN" | tr ',' '\n' | sed -n 's/.*"name":"\([^"]*\)".*/\1/p' > /tmp/zones.txt
|
curl -sf "$PRIMARY/api/zones/list?token=$P_TOKEN" | tr ',' '\n' | sed -n 's/.*"name":"\([^"]*\)".*/\1/p' | \
|
||||||
echo "Found zones:"; cat /tmp/zones.txt
|
grep -v -E '^(localhost|0\.in-addr\.arpa|127\.in-addr\.arpa|255\.in-addr\.arpa|1\.0\.0.*ip6\.arpa)$$' > /tmp/primary_zones.txt
|
||||||
|
echo "Primary has $(wc -l < /tmp/primary_zones.txt) zones to replicate"
|
||||||
|
|
||||||
# Enable zone transfers on primary
|
# Enable zone transfers on primary for all zones
|
||||||
while read -r zone; do
|
while read -r zone; do
|
||||||
echo "Enabling zone transfer for: $zone"
|
curl -sf "$PRIMARY/api/zones/options/set?token=$P_TOKEN&zone=$zone&zoneTransfer=Allow" > /dev/null || true
|
||||||
curl -sf "$PRIMARY/api/zones/options/set?token=$P_TOKEN&zone=$zone&zoneTransfer=Allow" || true
|
done < /tmp/primary_zones.txt
|
||||||
done < /tmp/zones.txt
|
|
||||||
|
|
||||||
# Configure each replica
|
# Sync to each replica
|
||||||
for REPLICA in $REPLICAS; do
|
SYNCED=0
|
||||||
echo "=== Configuring replica: $REPLICA ==="
|
for REPLICA in $REPLICAS; do
|
||||||
until curl -sf "$REPLICA/api/user/login?user=$TECH_USER&pass=$TECH_PASS" -o /tmp/r.json; do echo "Waiting for $REPLICA..."; sleep 5; done
|
R_TOKEN=$(curl -sf "$REPLICA/api/user/login?user=$TECH_USER&pass=$TECH_PASS" | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
|
||||||
R_TOKEN=$(cat /tmp/r.json | sed -n 's/.*"token":"\([^"]*\)".*/\1/p')
|
if [ -z "$R_TOKEN" ]; then echo "WARN: Cannot login to $REPLICA, skipping"; continue; fi
|
||||||
|
|
||||||
while read -r zone; do
|
# Get existing zones on this replica
|
||||||
echo "Creating secondary zone: $zone on $REPLICA"
|
curl -sf "$REPLICA/api/zones/list?token=$R_TOKEN" | tr ',' '\n' | sed -n 's/.*"name":"\([^"]*\)".*/\1/p' > /tmp/replica_zones.txt
|
||||||
curl -sf "$REPLICA/api/zones/create?token=$R_TOKEN&zone=$zone&type=Secondary&primaryNameServerAddresses=$PRIMARY_IP" || true
|
|
||||||
done < /tmp/zones.txt
|
|
||||||
|
|
||||||
while read -r zone; do
|
while read -r zone; do
|
||||||
echo "Resyncing: $zone on $REPLICA"
|
if grep -qx "$zone" /tmp/replica_zones.txt; then
|
||||||
curl -sf "$REPLICA/api/zones/resync?token=$R_TOKEN&zone=$zone" || true
|
# Zone exists — just resync
|
||||||
done < /tmp/zones.txt
|
curl -sf "$REPLICA/api/zones/resync?token=$R_TOKEN&zone=$zone" > /dev/null || true
|
||||||
done
|
else
|
||||||
|
# New zone — create as Secondary and sync
|
||||||
|
echo "NEW: Creating $zone on $REPLICA"
|
||||||
|
curl -sf "$REPLICA/api/zones/create?token=$R_TOKEN&zone=$zone&type=Secondary&primaryNameServerAddresses=$PRIMARY_IP" > /dev/null || true
|
||||||
|
SYNCED=$((SYNCED + 1))
|
||||||
|
fi
|
||||||
|
done < /tmp/primary_zones.txt
|
||||||
|
done
|
||||||
|
|
||||||
echo "Replica zone setup complete"
|
echo "Zone sync complete. $$SYNCED new zone(s) created."
|
||||||
SCRIPT
|
SCRIPT
|
||||||
]
|
]
|
||||||
env {
|
env {
|
||||||
name = "TECH_USER"
|
name = "TECH_USER"
|
||||||
value = var.technitium_username
|
value = var.technitium_username
|
||||||
}
|
}
|
||||||
env {
|
env {
|
||||||
name = "TECH_PASS"
|
name = "TECH_PASS"
|
||||||
value = var.technitium_password
|
value = var.technitium_password
|
||||||
}
|
}
|
||||||
env {
|
env {
|
||||||
name = "PRIMARY_IP"
|
name = "PRIMARY_IP"
|
||||||
value = kubernetes_service.technitium_primary.spec[0].cluster_ip
|
value = kubernetes_service.technitium_primary.spec[0].cluster_ip
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dns_config {
|
dns_config {
|
||||||
option {
|
option {
|
||||||
name = "ndots"
|
name = "ndots"
|
||||||
value = "2"
|
value = "2"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
depends_on = [
|
|
||||||
kubernetes_deployment.technitium,
|
|
||||||
kubernetes_deployment.technitium_secondary,
|
|
||||||
kubernetes_deployment.technitium_tertiary,
|
|
||||||
kubernetes_service.technitium_primary,
|
|
||||||
kubernetes_service.technitium_secondary_web,
|
|
||||||
kubernetes_service.technitium_tertiary_web,
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue