Architecture Diagrams
Comprehensive visual diagrams showing Bindy’s architecture, components, and data flows.
System Architecture
graph TB
subgraph "Kubernetes Cluster"
subgraph "Custom Resources"
BC[Bind9Cluster]
BI[Bind9Instance]
DZ[DNSZone]
AR[ARecord]
CR[CNAMERecord]
MR[MXRecord]
TR[TXTRecord]
end
subgraph "Bindy Controller (Rust)"
WA[Watch API<br/>kube-rs]
subgraph "Reconcilers"
BCR[Bind9Cluster<br/>Reconciler]
BIR[Bind9Instance<br/>Reconciler]
DZR[DNSZone<br/>Reconciler]
RR[Record<br/>Reconcilers]
end
subgraph "Core Components"
BM[Bind9Manager<br/>RNDC Client]
RES[Resource<br/>Builders]
end
end
subgraph "Kubernetes Resources"
DEP[Deployments]
CM[ConfigMaps]
SEC[Secrets]
SVC[Services]
end
subgraph "BIND9 Pods"
P1[Primary DNS<br/>us-east]
P2[Secondary DNS<br/>us-west]
P3[Secondary DNS<br/>eu]
end
end
subgraph "External"
CLI[DNS Clients]
end
%% Custom Resource relationships
BC -.inherits.-> BI
BI -.references.-> DZ
DZ -.contains.-> AR
DZ -.contains.-> CR
DZ -.contains.-> MR
DZ -.contains.-> TR
%% Watch relationships
BC --> WA
BI --> WA
DZ --> WA
AR --> WA
CR --> WA
MR --> WA
TR --> WA
%% Reconciler routing
WA --> BCR
WA --> BIR
WA --> DZR
WA --> RR
%% Component interactions
BCR --> RES
BIR --> RES
DZR --> BM
RR --> BM
%% K8s resource creation
RES --> DEP
RES --> CM
RES --> SEC
RES --> SVC
%% RNDC communication
BM -.RNDC:953.-> P1
BM -.RNDC:953.-> P2
BM -.RNDC:953.-> P3
%% DNS deployment
DEP --> P1
DEP --> P2
DEP --> P3
CM --> P1
CM --> P2
CM --> P3
SEC --> P1
%% Zone transfers
P1 -.AXFR/IXFR.-> P2
P1 -.AXFR/IXFR.-> P3
%% DNS queries
CLI -.DNS:53.-> P1
CLI -.DNS:53.-> P2
CLI -.DNS:53.-> P3
style BC fill:#e1f5ff
style BI fill:#e1f5ff
style DZ fill:#e1f5ff
style AR fill:#fff4e1
style CR fill:#fff4e1
style MR fill:#fff4e1
style TR fill:#fff4e1
style WA fill:#f0f0f0
style BCR fill:#d4e8d4
style BIR fill:#d4e8d4
style DZR fill:#d4e8d4
style RR fill:#d4e8d4
style BM fill:#ffd4d4
style RES fill:#ffd4d4
Rust Component Architecture
graph TB
subgraph "Main Process"
MAIN[main.rs<br/>Tokio Runtime]
end
subgraph "CRD Definitions (src/crd.rs)"
CRD_BC[Bind9Cluster]
CRD_BI[Bind9Instance]
CRD_DZ[DNSZone]
CRD_REC[Record Types<br/>A, AAAA, CNAME,<br/>MX, NS, TXT,<br/>SRV, CAA]
end
subgraph "Reconcilers (src/reconcilers/)"
RECON_BC[bind9cluster.rs]
RECON_BI[bind9instance.rs]
RECON_DZ[dnszone.rs]
RECON_REC[records.rs]
end
subgraph "BIND9 Management (src/bind9/)"
BM_MGR[Bind9Manager]
BM_KEY[RndcKeyData]
BM_CMD[Zone Operations<br/>HTTP API & RNDC<br/>addzone, delzone,<br/>reload, freeze,<br/>thaw, notify]
end
subgraph "Resource Builders (src/bind9_resources.rs)"
RB_DEP[build_deployment]
RB_CM[build_configmap]
RB_SVC[build_service]
RB_VOL[build_volumes]
RB_POD[build_podspec]
end
subgraph "External Dependencies"
KUBE[kube-rs<br/>Kubernetes Client]
RNDC[rndc-rs<br/>RNDC Protocol]
TOKIO[tokio<br/>Async Runtime]
SERDE[serde<br/>Serialization]
end
%% Main process spawns reconcilers
MAIN --> RECON_BC
MAIN --> RECON_BI
MAIN --> RECON_DZ
MAIN --> RECON_REC
%% Reconcilers use CRD types
RECON_BC -.uses.-> CRD_BC
RECON_BI -.uses.-> CRD_BI
RECON_DZ -.uses.-> CRD_DZ
RECON_REC -.uses.-> CRD_REC
%% Reconcilers call managers
RECON_BI --> RB_DEP
RECON_BI --> RB_CM
RECON_BI --> RB_SVC
RECON_DZ --> BM_MGR
RECON_REC --> BM_MGR
%% Resource builders use components
RB_DEP --> RB_POD
RB_DEP --> RB_VOL
RB_CM --> RB_VOL
%% BIND9 manager components
BM_MGR --> BM_KEY
BM_MGR --> BM_CMD
%% External dependencies
MAIN --> TOKIO
RECON_BC --> KUBE
RECON_BI --> KUBE
RECON_DZ --> KUBE
RECON_REC --> KUBE
BM_CMD --> RNDC
CRD_BC --> SERDE
CRD_BI --> SERDE
CRD_DZ --> SERDE
CRD_REC --> SERDE
style MAIN fill:#e1f5ff
style CRD_BC fill:#d4e8d4
style CRD_BI fill:#d4e8d4
style CRD_DZ fill:#d4e8d4
style CRD_REC fill:#d4e8d4
style RECON_BC fill:#fff4e1
style RECON_BI fill:#fff4e1
style RECON_DZ fill:#fff4e1
style RECON_REC fill:#fff4e1
style BM_MGR fill:#ffd4d4
style BM_KEY fill:#ffd4d4
style BM_CMD fill:#ffd4d4
style RB_DEP fill:#e8d4f8
style RB_CM fill:#e8d4f8
style RB_SVC fill:#e8d4f8
style RB_VOL fill:#e8d4f8
style RB_POD fill:#e8d4f8
DNS Record Creation Data Flow
sequenceDiagram
participant User
participant K8sAPI as Kubernetes API
participant Watch as Watch Stream
participant RecRec as Record Reconciler
participant ZoneRec as DNSZone Reconciler
participant BindMgr as Bind9Manager
participant Primary as Primary BIND9
participant Secondary as Secondary BIND9
participant Client as DNS Client
Note over User,Client: Record Creation Flow
User->>K8sAPI: kubectl apply -f arecord.yaml
K8sAPI->>K8sAPI: Validate CRD schema
K8sAPI->>K8sAPI: Store in etcd
K8sAPI-->>User: ARecord created
K8sAPI->>Watch: Event: ARecord Added
Watch->>RecRec: Trigger reconciliation
RecRec->>K8sAPI: Get referenced DNSZone
K8sAPI-->>RecRec: DNSZone details
RecRec->>K8sAPI: Get Bind9Instance (via clusterRef)
K8sAPI-->>RecRec: Bind9Instance details
RecRec->>K8sAPI: Get RNDC Secret
K8sAPI-->>RecRec: RNDC key data
RecRec->>BindMgr: Call add_a_record()
Note over BindMgr: Currently placeholder<br/>Will use nsupdate
BindMgr-->>RecRec: Ok(())
RecRec->>BindMgr: Call reload_zone(zone_name)
BindMgr->>Primary: RNDC reload zone
activate Primary
Primary->>Primary: Reload zone file
Primary-->>BindMgr: Success
deactivate Primary
BindMgr-->>RecRec: Zone reloaded
RecRec->>K8sAPI: Update ARecord status
K8sAPI-->>RecRec: Status updated
Note over Primary,Secondary: Zone Transfer (AXFR/IXFR)
Primary->>Secondary: NOTIFY (zone updated)
activate Secondary
Secondary->>Primary: SOA query (check serial)
Primary-->>Secondary: SOA record
alt Serial increased
Secondary->>Primary: IXFR/AXFR request
Primary-->>Secondary: Zone transfer
Secondary->>Secondary: Update zone
else Serial unchanged
Secondary->>Secondary: No update needed
end
deactivate Secondary
Note over Client,Secondary: DNS Query
Client->>Secondary: DNS query (www.example.com A?)
activate Secondary
Secondary->>Secondary: Lookup in zone
Secondary-->>Client: Answer: 192.0.2.1
deactivate Secondary
Zone Creation and Synchronization Flow
stateDiagram-v2
[*] --> ZoneCreated: User creates DNSZone
ZoneCreated --> Validating: Controller watches event
Validating --> ValidatingInstance: Validate zone spec
ValidatingInstance --> ValidatingCluster: Find Bind9Instance
ValidatingCluster --> GeneratingConfig: Find Bind9Cluster
GeneratingConfig --> CreatingRNDCKey: Generate zone config
CreatingRNDCKey --> StoringSecret: Generate RNDC key
StoringSecret --> AddingZone: Store in Secret
AddingZone --> ConnectingRNDC: Call rndc addzone
ConnectingRNDC --> ExecutingCommand: Connect via port 953
ExecutingCommand --> VerifyingZone: Execute addzone command
VerifyingZone --> Ready: Verify zone exists
Ready --> [*]: Update status to Ready
ValidatingInstance --> Failed: Instance not found
ValidatingCluster --> Failed: Cluster not found
AddingZone --> Failed: RNDC command failed
ConnectingRNDC --> Failed: Connection failed
Failed --> [*]: Update status conditions
note right of GeneratingConfig
Creates zone with:
- SOA record
- Default TTL
- Zone file path
end note
note right of AddingZone
Uses RNDC protocol:
addzone example.com
'{ type master;
file "zones/example.com"; }'
end note
Primary to Secondary Zone Transfer Flow
sequenceDiagram
participant Ctl as Bindy Controller
participant Pri as Primary BIND9<br/>(us-east)
participant Sec1 as Secondary BIND9<br/>(us-west)
participant Sec2 as Secondary BIND9<br/>(eu)
Note over Ctl,Sec2: Initial Zone Setup
Ctl->>Pri: RNDC addzone example.com
activate Pri
Pri->>Pri: Create zone file
Pri-->>Ctl: Zone added
deactivate Pri
Ctl->>Sec1: RNDC addzone example.com (type secondary)
activate Sec1
Sec1->>Sec1: Configure as secondary
Sec1-->>Ctl: Zone added as secondary
deactivate Sec1
Ctl->>Sec2: RNDC addzone example.com (type secondary)
activate Sec2
Sec2->>Sec2: Configure as secondary
Sec2-->>Ctl: Zone added as secondary
deactivate Sec2
Note over Pri,Sec2: Initial Zone Transfer
Sec1->>Pri: SOA query (get serial)
Pri-->>Sec1: SOA serial=2024010101
Sec1->>Pri: AXFR request (full transfer)
Pri-->>Sec1: Complete zone data
Sec1->>Sec1: Write zone file
Sec2->>Pri: SOA query (get serial)
Pri-->>Sec2: SOA serial=2024010101
Sec2->>Pri: AXFR request (full transfer)
Pri-->>Sec2: Complete zone data
Sec2->>Sec2: Write zone file
Note over Ctl,Sec2: Record Update
Ctl->>Ctl: User adds new ARecord
Ctl->>Pri: Update zone + reload
activate Pri
Pri->>Pri: Update zone file
Pri->>Pri: Increment serial to 2024010102
Pri-->>Ctl: Zone reloaded
deactivate Pri
Note over Pri,Sec2: NOTIFY and Incremental Transfer
Pri->>Sec1: NOTIFY (zone updated)
Pri->>Sec2: NOTIFY (zone updated)
activate Sec1
Sec1->>Pri: SOA query (check serial)
Pri-->>Sec1: SOA serial=2024010102
Sec1->>Sec1: Compare: 2024010102 > 2024010101
Sec1->>Pri: IXFR request (incremental)
Pri-->>Sec1: Only changed records
Sec1->>Sec1: Apply changes
Sec1-->>Pri: ACK
deactivate Sec1
activate Sec2
Sec2->>Pri: SOA query (check serial)
Pri-->>Sec2: SOA serial=2024010102
Sec2->>Sec2: Compare: 2024010102 > 2024010101
Sec2->>Pri: IXFR request (incremental)
Pri-->>Sec2: Only changed records
Sec2->>Sec2: Apply changes
Sec2-->>Pri: ACK
deactivate Sec2
Note over Pri,Sec2: All zones synchronized
Reconciliation Loop
flowchart TD
Start([Watch Event Received]) --> CheckType{Event Type?}
CheckType -->|Added/Modified| GetResource[Get Resource from API]
CheckType -->|Deleted| Cleanup[Run Cleanup Logic]
CheckType -->|Restarted| RefreshAll[Refresh All Resources]
GetResource --> CheckGen{observedGeneration<br/>== metadata.generation?}
CheckGen -->|Yes| SkipRecon[Skip: Already reconciled]
CheckGen -->|No| ValidateSpec[Validate Spec]
ValidateSpec --> CheckValid{Valid?}
CheckValid -->|No| UpdateFailed[Update Status: Failed]
CheckValid -->|Yes| Reconcile[Execute Reconciliation]
Reconcile --> ReconcileResult{Success?}
ReconcileResult -->|Yes| UpdateReady[Update Status: Ready]
ReconcileResult -->|No| CheckRetry{Retryable?}
CheckRetry -->|Yes| Requeue[Requeue with backoff]
CheckRetry -->|No| UpdateError[Update Status: Error]
UpdateReady --> UpdateGen[Update observedGeneration]
UpdateError --> Requeue
UpdateFailed --> End
UpdateGen --> End([Done])
Cleanup --> End
RefreshAll --> End
SkipRecon --> End
Requeue --> End
style Start fill:#e1f5ff
style End fill:#e1f5ff
style Reconcile fill:#d4e8d4
style UpdateReady fill:#d4f8d4
style UpdateError fill:#f8d4d4
style UpdateFailed fill:#f8d4d4
style CheckType fill:#fff4e1
style CheckGen fill:#fff4e1
style CheckValid fill:#fff4e1
style ReconcileResult fill:#fff4e1
style CheckRetry fill:#fff4e1
RNDC Protocol Communication
sequenceDiagram
participant BM as Bind9Manager<br/>(Rust)
participant RC as RNDC Client<br/>(rndc-rs)
participant Net as TCP Socket<br/>:953
participant BIND as BIND9 Server<br/>(rndc daemon)
Note over BM,BIND: RNDC Key Setup (One-time)
BM->>BM: generate_rndc_key()
BM->>BM: Create HMAC-SHA256 key
BM->>BM: Store in K8s Secret
Note over BM,BIND: RNDC Command Execution
BM->>RC: new(server, algorithm, secret)
RC->>RC: Parse RNDC key
RC->>RC: Prepare TSIG signature
BM->>RC: rndc_command("reload zone")
RC->>Net: Connect to server:953
Net->>BIND: TCP handshake
RC->>RC: Create RNDC message
RC->>RC: Sign with HMAC-SHA256
RC->>Net: Send signed message
Net->>BIND: Forward RNDC message
activate BIND
BIND->>BIND: Verify TSIG signature
BIND->>BIND: Execute: reload zone
BIND->>BIND: Reload zone file
BIND->>Net: Response + TSIG
deactivate BIND
Net->>RC: Receive response
RC->>RC: Verify response TSIG
RC->>RC: Parse result
RC-->>BM: Ok(result.text)
alt Authentication Failed
BIND-->>Net: Error: TSIG verification failed
Net-->>RC: Error response
RC-->>BM: Err("RNDC authentication failed")
end
alt Command Failed
BIND-->>Net: Error: Zone not found
Net-->>RC: Error response
RC-->>BM: Err("Zone not found")
end
Multi-Cluster Deployment
graph TB
subgraph "Cluster: us-east-1"
BC1[Bind9Cluster:<br/>production-dns]
BI1[Bind9Instance:<br/>primary-dns]
DZ1[DNSZone:<br/>example.com]
P1[Primary BIND9<br/>172.16.1.10]
BC1 -.-> BI1
BI1 -.-> DZ1
DZ1 --> P1
end
subgraph "Cluster: us-west-2"
BC2[Bind9Cluster:<br/>production-dns]
BI2[Bind9Instance:<br/>secondary-dns-west]
DZ2[DNSZone:<br/>example.com]
S1[Secondary BIND9<br/>172.16.2.10]
BC2 -.-> BI2
BI2 -.-> DZ2
DZ2 --> S1
end
subgraph "Cluster: eu-central-1"
BC3[Bind9Cluster:<br/>production-dns]
BI3[Bind9Instance:<br/>secondary-dns-eu]
DZ3[DNSZone:<br/>example.com]
S2[Secondary BIND9<br/>172.16.3.10]
BC3 -.-> BI3
BI3 -.-> DZ3
DZ3 --> S2
end
P1 -.AXFR/IXFR.-> S1
P1 -.AXFR/IXFR.-> S2
LB[Global Load Balancer<br/>GeoDNS]
LB -.US Traffic.-> P1
LB -.US Traffic.-> S1
LB -.EU Traffic.-> S2
style BC1 fill:#e1f5ff
style BC2 fill:#e1f5ff
style BC3 fill:#e1f5ff
style BI1 fill:#d4e8d4
style BI2 fill:#d4e8d4
style BI3 fill:#d4e8d4
style P1 fill:#ffd4d4
style S1 fill:#fff4e1
style S2 fill:#fff4e1
style LB fill:#f0f0f0
Related Documentation
- Architecture Overview - Detailed text description
- RNDC Architecture - RNDC protocol details
- Technical Architecture - Implementation specifics
- CRD Specifications - Custom resource definitions