DNSZone
The DNSZone resource defines a DNS zone with its SOA record and references a specific BIND9 cluster.
Overview
A DNSZone represents:
- Zone name (e.g., example.com)
- SOA (Start of Authority) record
- Cluster reference to a Bind9Instance
- Default TTL for records
The zone is created on the referenced BIND9 cluster using the RNDC protocol.
Example
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: example-com
namespace: dns-system
spec:
zoneName: example.com
clusterRef: my-dns-cluster # References Bind9Instance name
soaRecord:
primaryNs: ns1.example.com.
adminEmail: admin.example.com. # Note: @ replaced with .
serial: 2024010101
refresh: 3600
retry: 600
expire: 604800
negativeTtl: 86400
ttl: 3600
status:
conditions:
- type: Ready
status: "True"
reason: Synchronized
message: "Zone created for cluster: my-dns-cluster"
observedGeneration: 1
Specification
Required Fields
spec.zoneName- The DNS zone name (e.g., example.com)spec.clusterRef- Name of the Bind9Instance to host this zonespec.soaRecord- Start of Authority record configuration
SOA Record Fields
primaryNs- Primary nameserver (must end with.)adminEmail- Zone administrator email (@ replaced with., must end with.)serial- Zone serial number (typically YYYYMMDDNN format)refresh- Refresh interval in seconds (how often secondaries check for updates)retry- Retry interval in seconds (retry delay after failed refresh)expire- Expiry time in seconds (when to stop serving if primary unreachable)negativeTtl- Negative caching TTL (cache duration for NXDOMAIN responses)
Optional Fields
spec.ttl- Default TTL for records in seconds (default: 3600)
How Zones Are Created
When you create a DNSZone resource:
- Controller discovers pods - Finds BIND9 pods with label
instance={clusterRef} - Loads RNDC key - Retrieves Secret named
{clusterRef}-rndc-key - Connects via RNDC - Establishes connection to
{clusterRef}.{namespace}.svc.cluster.local:953 - Executes addzone - Runs
rndc addzonecommand with zone configuration - BIND9 creates zone - BIND9 creates the zone file and starts serving the zone
- Updates status - Controller updates DNSZone status to Ready
Cluster References
Zones reference a specific BIND9 cluster by name:
spec:
clusterRef: my-dns-cluster
This references a Bind9Instance resource:
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Instance
metadata:
name: my-dns-cluster # Referenced by DNSZone
namespace: dns-system
spec:
role: primary
replicas: 2
RNDC Key Discovery
The controller automatically finds the RNDC key using the cluster reference:
DNSZone.spec.clusterRef = "my-dns-cluster"
↓
Secret name = "my-dns-cluster-rndc-key"
↓
RNDC authentication to: my-dns-cluster.dns-system.svc.cluster.local:953
Status
The controller reports zone status with granular condition types that provide real-time visibility into the reconciliation process.
Status During Reconciliation
# Phase 1: Configuring primary instances
status:
conditions:
- type: Progressing
status: "True"
reason: PrimaryReconciling
message: "Configuring zone on primary instances"
lastTransitionTime: "2024-11-26T10:00:00Z"
observedGeneration: 1
# Phase 2: Primary success, configuring secondaries
status:
conditions:
- type: Progressing
status: "True"
reason: SecondaryReconciling
message: "Configured on 2 primary server(s), now configuring secondaries"
lastTransitionTime: "2024-11-26T10:00:01Z"
observedGeneration: 1
secondaryIps:
- "10.42.0.5"
- "10.42.0.6"
Status After Successful Reconciliation
status:
conditions:
- type: Ready
status: "True"
reason: ReconcileSucceeded
message: "Configured on 2 primary server(s) and 3 secondary server(s)"
lastTransitionTime: "2024-11-26T10:00:02Z"
observedGeneration: 1
recordCount: 5
secondaryIps:
- "10.42.0.5"
- "10.42.0.6"
- "10.42.0.7"
records:
- apiVersion: bindy.firestoned.io/v1beta1
kind: ARecord
name: web-a-record
- apiVersion: bindy.firestoned.io/v1beta1
kind: AAAARecord
name: web-aaaa-record
- apiVersion: bindy.firestoned.io/v1beta1
kind: CNAMERecord
name: www-cname-record
- apiVersion: bindy.firestoned.io/v1beta1
kind: MXRecord
name: mail-mx-record
- apiVersion: bindy.firestoned.io/v1beta1
kind: TXTRecord
name: spf-txt-record
Note: The records field is only available in v1beta1 and tracks all DNS records successfully associated with this zone. This field does not exist in the deprecated v1alpha1 API.
Status After Partial Failure (Degraded)
status:
conditions:
- type: Degraded
status: "True"
reason: SecondaryFailed
message: "Configured on 2 primary server(s), but secondary configuration failed: connection timeout"
lastTransitionTime: "2024-11-26T10:00:02Z"
observedGeneration: 1
recordCount: 5
secondaryIps:
- "10.42.0.5"
- "10.42.0.6"
Condition Types
DNSZone uses the following condition types:
-
Progressing - Zone is being configured
PrimaryReconciling: Configuring on primary instancesPrimaryReconciled: Primary configuration successfulSecondaryReconciling: Configuring on secondary instancesSecondaryReconciled: Secondary configuration successful
-
Ready - Zone fully configured and operational
ReconcileSucceeded: All primaries and secondaries configured successfully
-
Degraded - Partial or complete failure
PrimaryFailed: Primary configuration failed (zone not functional)SecondaryFailed: Secondary configuration failed (primaries work, but secondaries unavailable)
Status Field: records (v1beta1 only)
The status.records field provides a real-time inventory of all DNS records successfully associated with this zone. This field is only available in the v1beta1 API and does not exist in the deprecated v1alpha1 API.
How It Works
When a DNS record (ARecord, AAAARecord, CNAMERecord, MXRecord, NSRecord, SRVRecord, TXTRecord, or CAARecord) is successfully reconciled and added to the zone, the record reconciler automatically adds a reference to the DNSZone.status.records list.
Each record reference contains:
apiVersion- The API version of the record resource (alwaysbindy.firestoned.io/v1beta1)kind- The record type (e.g.,ARecord,CNAMERecord,MXRecord)name- The name of the record resource in Kubernetes
Example
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: example-com
namespace: dns-system
status:
conditions:
- type: Ready
status: "True"
records:
- apiVersion: bindy.firestoned.io/v1beta1
kind: ARecord
name: web-server
- apiVersion: bindy.firestoned.io/v1beta1
kind: AAAARecord
name: web-server-ipv6
- apiVersion: bindy.firestoned.io/v1beta1
kind: CNAMERecord
name: www-alias
- apiVersion: bindy.firestoned.io/v1beta1
kind: MXRecord
name: mail-server
Use Cases
-
Operational Visibility - Quickly see which records are managed by this zone:
kubectl get dnszone example-com -o jsonpath='{.status.records[*].name}' # Output: web-server web-server-ipv6 www-alias mail-server -
Debugging - Verify a record was successfully added to the zone:
kubectl get dnszone example-com -o yaml | grep -A3 "kind: ARecord" # Output: # - apiVersion: bindy.firestoned.io/v1beta1 # kind: ARecord # name: web-server -
Auditing - Count how many records of each type are associated:
kubectl get dnszone example-com -o json | jq '.status.records | group_by(.kind) | map({kind: .[0].kind, count: length})' # Output: [{"kind":"ARecord","count":1},{"kind":"AAAARecord","count":1},{"kind":"CNAMERecord","count":1},{"kind":"MXRecord","count":1}] -
Automation - Build tools that react to zone record changes:
# Watch for changes to the records list kubectl get dnszone example-com -o jsonpath='{.status.records}' --watch
Important Notes
- v1beta1 Only: This field does not exist in v1alpha1. If you’re still using v1alpha1, upgrade to v1beta1 to access this feature.
- Read-Only: The
recordsfield is managed automatically by the controller. Do not manually edit it. - Eventually Consistent: After creating a new record, it may take a few seconds for it to appear in the zone’s
status.recordslist. - Duplicate Prevention: The controller automatically prevents duplicate record references from being added.
- Serialization: When the
recordsfield is empty, it is omitted from the YAML/JSON output to reduce clutter.
Benefits of Granular Status
- Real-time visibility - See which reconciliation phase is running
- Better debugging - Know exactly which phase failed (primary vs secondary)
- Graceful degradation - Secondary failures don’t break the zone (primaries still work)
- Accurate counts - Status shows exact number of configured servers
- Record inventory - Track all DNS records associated with each zone (v1beta1 only)
Use Cases
Simple Zone
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: simple-com
spec:
zoneName: simple.com
clusterRef: primary-dns
soaRecord:
primaryNs: ns1.simple.com.
adminEmail: admin.simple.com.
serial: 2024010101
refresh: 3600
retry: 600
expire: 604800
negativeTtl: 86400
Production Zone with Custom TTL
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: api-example-com
spec:
zoneName: api.example.com
clusterRef: production-dns
ttl: 300 # 5 minute default TTL for faster updates
soaRecord:
primaryNs: ns1.api.example.com.
adminEmail: ops.example.com.
serial: 2024010101
refresh: 1800 # Check every 30 minutes
retry: 300 # Retry after 5 minutes
expire: 604800
negativeTtl: 300 # Short negative cache
Next Steps
- DNS Records - Add records to zones
- RNDC-Based Architecture - Learn how RNDC protocol works
- Bind9Instance - Learn about BIND9 instance resources
- Creating Zones - Zone management guide