Declarative DNS management for Kubernetes. Manage BIND9 infrastructure as code using Custom Resources. Built in Rust for high performance and security.
Built for Regulated Environments: Full SOX, NIST 800-53, and CIS compliance documentation. Designed for banking and financial services.
Bindy is a Kubernetes operator that manages BIND9 DNS infrastructure declaratively. Instead of manually configuring DNS servers, you define DNS resources in YAML and Bindy handles:
- Deploying and configuring BIND9 instances
- Creating DNS zones with SOA records
- Adding/updating DNS records dynamically via RNDC
- Platform-managed DNS accessible cluster-wide
# 1. Create a DNS cluster
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Cluster
metadata:
name: my-dns
namespace: dns-system
spec:
primary:
replicas: 2
secondary:
replicas: 2
---
# 2. Create a zone
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: example-com
namespace: dns-system
spec:
zoneName: example.com
clusterRef: my-dns
---
# 3. Add DNS records
apiVersion: bindy.firestoned.io/v1beta1
kind: ARecord
metadata:
name: www
namespace: dns-system
spec:
zoneRef: example-com
name: www
ipv4Address: "192.0.2.1"Apply and you're done:
kubectl apply -f dns.yaml
dig @<dns-service-ip> www.example.com # Works!Bindy provides 4 types of resources:
| Resource | Purpose |
|---|---|
| Bind9Cluster | Logical DNS cluster (manages multiple instances) |
| Bind9GlobalCluster | Cluster-scoped DNS infrastructure (platform-managed) |
| Bind9Instance | Individual BIND9 server deployment |
| Resource | Purpose |
|---|---|
| DNSZone | DNS zone with SOA record |
| ARecord | IPv4 address (A) |
| AAAARecord | IPv6 address (AAAA) |
| CNAMERecord | Alias (CNAME) |
| MXRecord | Mail server (MX) |
| TXTRecord | Text data (TXT, SPF, DKIM) |
| NSRecord | Nameserver delegation (NS) |
| SRVRecord | Service location (SRV) |
| CAARecord | Certificate authority authorization (CAA) |
┌─────────────────┐ ┌──────────────────┐ ┌─────────────┐
│ Bind9Cluster │────▶│ Bind9Instance │────▶│ BIND9 Pod │
│ (Logical) │ │ (Physical) │ │ + Service │
└─────────────────┘ └──────────────────┘ └─────────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐
│ DNSZone │────▶│ Zone on BIND9 │
│ (example.com) │ │ via RNDC │
└─────────────────┘ └──────────────────┘
│
▼
┌─────────────────┐ ┌──────────────────┐
│ ARecord │────▶│ DNS Record │
│ (www) │ │ via RNDC │
└─────────────────┘ └──────────────────┘
Key Points:
- Bind9Cluster creates and manages Bind9Instance resources automatically
- Bind9Instance generates Kubernetes Deployments, Services, ConfigMaps, and Secrets
- DNSZone creates the zone on target BIND9 instances
- Record resources add DNS records dynamically (no zone file edits!)
For platform-managed DNS infrastructure accessible from all namespaces:
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9GlobalCluster
metadata:
name: shared-dns
# No namespace - cluster-scoped resource
spec:
version: "9.18"
primary:
replicas: 3
secondary:
replicas: 2Application teams can then reference this global cluster from any namespace using clusterProviderRef. See Multi-Tenancy Guide for details.
kubectl create namespace dns-system
kubectl create -f https://github.com/firestoned/bindy/releases/latest/download/crds.yamlkubectl apply -f https://github.com/firestoned/bindy/releases/latest/download/bindy.yamlkubectl wait --for=condition=available --timeout=300s deployment/bindy -n dns-systemThat's it! Now create DNS resources.
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Cluster
metadata:
name: simple-dns
namespace: dns-system
spec:
primary:
replicas: 1Creates 1 primary BIND9 instance. No secondaries needed for dev/test.
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Cluster
metadata:
name: prod-dns
namespace: dns-system
spec:
global:
recursion: false
allowQuery: ["0.0.0.0/0"]
allowTransfer: ["10.0.0.0/8"]
primary:
replicas: 3
config:
dnssec:
enabled: true
secondary:
replicas: 2Creates 3 primaries + 2 secondaries with DNSSEC enabled and zone transfers configured.
# Zone
apiVersion: bindy.firestoned.io/v1beta1
kind: DNSZone
metadata:
name: example-com
namespace: dns-system
spec:
zoneName: example.com
clusterRef: prod-dns
soaRecord:
primaryNS: ns1.example.com.
adminEmail: admin.example.com.
ttl: 3600
---
# A Record
apiVersion: bindy.firestoned.io/v1beta1
kind: ARecord
metadata:
name: www
namespace: dns-system
spec:
zoneRef: example-com
name: www
ipv4Address: "192.0.2.1"
ttl: 300
---
# CNAME
apiVersion: bindy.firestoned.io/v1beta1
kind: CNAMERecord
metadata:
name: blog
namespace: dns-system
spec:
zoneRef: example-com
name: blog
target: www.example.com.
---
# MX Record
apiVersion: bindy.firestoned.io/v1beta1
kind: MXRecord
metadata:
name: mail
namespace: dns-system
spec:
zoneRef: example-com
name: "@"
priority: 10
mailServer: mail.example.com.
---
# TXT (SPF)
apiVersion: bindy.firestoned.io/v1beta1
kind: TXTRecord
metadata:
name: spf
namespace: dns-system
spec:
zoneRef: example-com
name: "@"
text:
- "v=spf1 include:_spf.example.com ~all"Skip the cluster abstraction and create a single instance directly:
apiVersion: bindy.firestoned.io/v1beta1
kind: Bind9Instance
metadata:
name: standalone
namespace: dns-system
spec:
replicas: 1
version: "9.18"
role: primary
config:
recursion: false
allowQuery: ["0.0.0.0/0"]Useful for testing or when you need full control over a single instance.
✅ Declarative - Manage DNS as Kubernetes resources (GitOps-ready) ✅ Dynamic Updates - Records added via RNDC (no zone file restarts) ✅ High Performance - Written in Rust, minimal overhead ✅ Cluster-Scoped - Bind9GlobalCluster for platform-managed DNS ✅ DNSSEC - Automatic key management and zone signing ✅ High Availability - Leader election, automatic failover ✅ Compliance - SOX, NIST 800-53, CIS documented ✅ Secure - Non-root containers, RBAC, signed releases
The controller is configured via environment variables in the deployment:
| Variable | Default | Description |
|---|---|---|
RUST_LOG |
info |
Log level (debug, info, warn, error) |
BINDY_ENABLE_LEADER_ELECTION |
true |
Enable leader election for HA |
BINDY_LEASE_DURATION_SECONDS |
15 |
Lease duration |
See deployment.yaml for all options.
Check resource status:
# Clusters
kubectl get bind9clusters -n dns-system
# Instances
kubectl get bind9instances -n dns-system
# Zones
kubectl get dnszones -n dns-system
# Records
kubectl get arecords,cnamerecords,mxrecords,txtrecords -n dns-systemView detailed status:
kubectl describe arecord www -n dns-systemOutput includes annotations showing cluster, instance, and zone:
metadata:
annotations:
bindy.firestoned.io/cluster: prod-dns
bindy.firestoned.io/instance: primary-0
bindy.firestoned.io/zone: example.com
status:
conditions:
- type: Ready
status: "True"
reason: RecordCreated
message: A record www.example.com created successfullyController logs:
kubectl logs -n dns-system -l app=bindy -fTest DNS resolution:
# Get service IP
kubectl get svc -n dns-system
# Query DNS
dig @<service-ip> www.example.com AVerify BIND9 config:
# Find BIND9 pod
kubectl get pods -n dns-system -l app.kubernetes.io/name=bind9
# Check config
kubectl exec -it <pod> -n dns-system -- named-checkconf /etc/bind/named.confCommon issues:
- Records not appearing? Check
kubectl describe <record>for error status - BIND9 not starting? Check RNDC key in Secret:
kubectl get secret -n dns-system - Cluster not creating instances? Check Bind9Cluster status:
kubectl describe bind9cluster
📚 Complete docs: https://firestoned.github.io/bindy/
Includes:
- Installation guide
- Multi-tenancy patterns
- High availability setup
- DNSSEC configuration
- Compliance documentation (SOX, NIST, CIS)
- API reference
Prerequisites:
- Rust 1.85+
- Kubernetes 1.27+
Build & Test:
cargo build
cargo testSee the Developer Guide for detailed development instructions.
Contributions welcome! Please:
- Sign commits with GPG/SSH (required for compliance)
- Run
cargo fmtandcargo clippy - Add tests for new features
- Update CHANGELOG.md
See CONTRIBUTING.md for details.
- Signed Releases: All releases signed with Cosign (keyless). Verify releases →
- SLSA Level 3: Build provenance for supply chain security
- SBOM: CycloneDX SBOM included with every release
- Vulnerability Scanning: Daily
cargo auditruns
Report security issues to: security@firestoned.io
MIT License - see LICENSE
Copyright (c) 2025 Erick Bourgeois, firestoned
Need help?
