OpenStack Error Guide: 'Zone ... in ERROR status' — Fix Designate DNS Zone Propagation
Fix Designate 'zone in ERROR status' DNS failures: diagnose the mDNS-to-backend path, pool_manager/worker propagation, BIND/PowerDNS backend errors, TSIG keys, and NOTIFY/AXFR in Kolla-Ansible OpenStack.
- #openstack
- #troubleshooting
- #errors
- #designate
Fixing errors like this? Get 500 free DevOps AI prompts
500 copy-paste AI prompts for the stack you actually run — one PDF, free.
Overview
Zone ... in ERROR status is the state Designate reports when a DNS zone fails to propagate from Designate’s storage to the backend DNS servers (BIND9, PowerDNS) that actually answer queries. Designate accepts the change into its database, then the worker/producer pushes it to the pool’s nameservers via mDNS and NOTIFY/AXFR; if that push fails or the backend rejects it, the zone lands in ERROR and DNS resolution for that zone is stale or broken.
The literal errors you will see:
openstack zone show example.com.
| status | ERROR |
| action | CREATE |
WARNING designate.worker.tasks.zone Could not update zone example.com. on nameserver ns1 (10.0.0.31:53): timeout
It occurs after openstack zone create/set/delete or a recordset change. The tell is that Designate’s API succeeded (the zone exists in the DB) but the backend push failed — a propagation/transport problem between Designate and its nameservers, not a client error.
Symptoms
openstack zone listshows zones withstatus ERROR.- Recordset changes don’t resolve even though the API accepted them.
- designate-worker/producer logs propagation timeouts or backend errors.
openstack zone list -c name -c status -c action
+--------------+--------+--------+
| name | status | action |
+--------------+--------+--------+
| example.com. | ERROR | CREATE |
+--------------+--------+--------+
docker logs designate_worker 2>&1 | grep -iE "ERROR|could not update zone|timeout" | tail -5
WARNING designate.worker Could not update zone example.com. on nameserver 10.0.0.31:53: timeout
Common Root Causes
1. Backend nameserver unreachable
Designate pushes via mDNS/NOTIFY to the pool’s nameservers; if 53 is unreachable the update times out.
docker exec designate_worker grep -A15 'pools' /etc/designate/pools.yaml 2>/dev/null | grep -iE 'host|port'
nc -vz <ns-ip> 53
dig @<ns-ip> example.com. SOA +short
Connection to 10.0.0.31 53 port [tcp/*] failed: Connection timed out
A timeout to the backend’s port 53 means the propagation path is broken.
2. TSIG key mismatch
Designate signs zone transfers with a TSIG key the backend must share; a mismatch causes the backend to refuse updates.
docker exec designate_worker grep -iE 'tsig' /etc/designate/pools.yaml 2>/dev/null
docker logs designate_worker 2>&1 | grep -iE "tsig|bad.?key|refused" | tail -5
ERROR ... NOTIFY refused: TSIG verify failure (BADKEY)
A BADKEY/TSIG error is an authentication mismatch between Designate and the nameserver.
3. mDNS service down or misconfigured
designate-mdns serves zone data for AXFR; if it’s down or bound wrong, backends can’t pull the zone.
docker ps --filter name=designate_mdns --format '{{.Names}} {{.Status}}'
docker exec designate_mdns grep -A5 '\[service:mdns\]' /etc/designate/designate.conf
ss -ltnp | grep 5354
designate_mdns Restarting (1) 6 seconds ago
If mDNS isn’t running/listening, backends have nothing to transfer from.
4. Backend (BIND/PowerDNS) rejecting the zone
The backend may reject a malformed zone, a duplicate, or hit its own error (permissions, DB).
docker logs designate_worker 2>&1 | grep -iE "REFUSED|SERVFAIL|rejected|backend" | tail -5
# On a BIND backend host
sudo journalctl -u named --no-pager | tail -20
ERROR ... backend returned REFUSED for zone example.com.
5. NOTIFY/AXFR blocked by firewall
Zone propagation needs NOTIFY (UDP/TCP 53) out and AXFR (TCP) back; a firewall change can break one direction.
nc -vz <ns-ip> 53 # Designate -> backend NOTIFY
# From the backend host, AXFR from mdns:
dig @<mdns-ip> -p 5354 example.com. AXFR | head
; Transfer failed.
6. Pool target misconfiguration
A wrong pools.yaml (wrong nameserver IP, missing target) means Designate pushes to the wrong place or nowhere.
docker exec designate_worker grep -A20 'targets' /etc/designate/pools.yaml 2>/dev/null
openstack zone show example.com. -c pool_id -f value
# target host doesn't match the actual nameserver IP
Diagnostic Workflow
Step 1: Confirm the zone status and action
openstack zone list -c name -c status -c action
openstack zone show <zone> -c status -c action -c pool_id
ERROR with action CREATE/UPDATE means the last propagation failed.
Step 2: Reach the backend nameservers
docker exec designate_worker grep -iE 'host|port' /etc/designate/pools.yaml 2>/dev/null
for ns in <ns-ip-1> <ns-ip-2>; do nc -vz $ns 53; done
dig @<ns-ip> <zone> SOA +short
Step 3: Read the worker/producer log for the exact failure
docker logs designate_worker 2>&1 | grep -iE "<zone>|tsig|refused|timeout|REFUSED" | tail -10
docker logs designate_producer 2>&1 | grep -iE "<zone>|error" | tail -10
timeout → network; TSIG/BADKEY → key; REFUSED → backend rejecting.
Step 4: Verify mDNS is serving AXFR
docker ps --filter name=designate_mdns
dig @<mdns-ip> -p 5354 <zone> AXFR | head
Step 5: Recover the zone once the path is fixed
openstack zone set <zone> --description "retry" # nudge, or:
# Designate producer periodically retries ERROR zones; confirm it flips to ACTIVE
openstack zone show <zone> -c status
Example Root Cause Analysis
After adding a second nameserver to the pool, half the zones flip to ERROR. openstack zone show confirms failed propagation:
openstack zone show example.com. -c status -c action
| status | ERROR |
| action | UPDATE |
The worker log names the new nameserver:
docker logs designate_worker 2>&1 | grep -iE "example.com|10.0.0.32" | tail -3
WARNING designate.worker Could not update zone example.com. on nameserver 10.0.0.32:53: timeout
Testing reachability to the new nameserver:
nc -vz 10.0.0.32 53
Connection to 10.0.0.32 53 port [tcp/*] failed: Connection timed out
The new nameserver was added to pools.yaml but its host firewall never got a rule allowing Designate’s mDNS/NOTIFY traffic on 53. Because the pool now requires both nameservers to succeed, every update fails. Opening 53 on the new backend and letting the producer retry recovers the zones:
# after opening 53 on 10.0.0.32 and confirming NOTIFY/AXFR both ways:
openstack zone set example.com. --ttl 3600 # trigger an update
openstack zone show example.com. -c status # ACTIVE
Longer term, add reachability and TSIG-verification checks to the pool-onboarding runbook so a new nameserver isn’t added to pools.yaml before its firewall and keys are in place.
Prevention Best Practices
- Monitor
openstack zone listfor any zone inERROR, and alert — a zone in ERROR means stale DNS that users will notice. - Before adding a nameserver to
pools.yaml, verify 53 reachability (NOTIFY both ways, AXFR from mDNS) and the TSIG key on that backend. - Keep TSIG keys consistent between Designate and every backend; a
BADKEYerror blocks all propagation to that server. - Watch designate-mdns health and its listen port (5354 by default); backends can’t AXFR if mDNS is down.
- Pre-open DNS ports (53 UDP/TCP to backends, mDNS port from backends) in firewalls and test after any network change.
- Validate
pools.yamltargets against the actual nameserver inventory whenever the pool changes; a wrong IP silently sends updates nowhere. - Paste the worker log and zone status into the free incident assistant to separate a network timeout from a TSIG or backend-reject failure, and see more OpenStack guides.
Quick Command Reference
# Zone status and action
openstack zone list -c name -c status -c action
openstack zone show <zone> -c status -c action -c pool_id
# Reach the backend nameservers
docker exec designate_worker grep -iE 'host|port' /etc/designate/pools.yaml 2>/dev/null
for ns in <ns-ip-1> <ns-ip-2>; do nc -vz $ns 53; done
dig @<ns-ip> <zone> SOA +short
# Exact failure in the logs
docker logs designate_worker 2>&1 | grep -iE "<zone>|tsig|refused|timeout|REFUSED" | tail -10
docker logs designate_producer 2>&1 | grep -iE "<zone>|error" | tail -10
# mDNS serving AXFR?
docker ps --filter name=designate_mdns
dig @<mdns-ip> -p 5354 <zone> AXFR | head
# Nudge a retry after fixing the path
openstack zone set <zone> --ttl 3600
openstack zone show <zone> -c status
Conclusion
Zone ... in ERROR status means Designate accepted the change but failed to propagate it to the backend nameservers, so DNS is stale even though the API succeeded. Typical root causes:
- A backend nameserver unreachable on port 53.
- A TSIG key mismatch causing the backend to refuse updates.
- designate-mdns down or misconfigured, so backends can’t AXFR.
- The backend (BIND/PowerDNS) rejecting the zone.
- A firewall blocking NOTIFY or AXFR in one direction.
- A
pools.yamltarget pointing at the wrong nameserver.
Read the worker log for the exact failure first: timeout vs TSIG/BADKEY vs REFUSED tells you whether you’re chasing the network, the key material, or the backend — then let the producer retry the zone back to ACTIVE.
Get 500 Battle-Tested DevOps AI Prompts — Free
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.