Summary
Implement automatic detection of RNDC secret changes and hot reload BIND9 configuration via SIGHUP signal, enabling secure key rotation without downtime.
Problem
Currently, when an RNDC secret is updated (manually or via external secret manager):
- BIND9 continues using the old key loaded at startup
- The new key is mounted but BIND9 doesn't reload it
- Management operations fail (controller has new key, BIND9 expects old key)
- Manual intervention required: Restart pods or manually exec SIGHUP
This prevents:
- Security best practices (regular key rotation)
- Integration with external secret managers (Vault, sealed-secrets)
- Automated secret lifecycle management
Proposed Solution
See ADR-0001: RNDC Secret Reload for full design.
High-level approach:
- Track RNDC secret
resourceVersion in Bind9InstanceStatus
- Detect version changes in reconciler
- Send SIGHUP to affected pods only (selective reload)
- Update status to reflect new version
Key benefits:
- ✅ Zero downtime (hot reload vs pod restart)
- ✅ Selective (only affected instances reload)
- ✅ Secure (enables key rotation best practices)
- ✅ Observable (status tracks loaded version)
Implementation Phases
Phase 1: MVP - Basic Secret Tracking
Phase 2: Secret Watch
Phase 3: Observability
Phase 4: Advanced (Future)
Technical Details
CRD Changes
// src/crd.rs
#[derive(Clone, Debug, Default, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "camelCase")]
pub struct Bind9InstanceStatus {
pub conditions: Option<Vec<Condition>>,
pub observed_generation: Option<i64>,
pub replicas: Option<i32>,
pub ready_replicas: Option<i32>,
// NEW: Track RNDC secret version
#[serde(skip_serializing_if = "Option::is_none")]
pub rndc_secret_version: Option<String>,
}
SIGHUP Implementation
// src/reconcilers/bind9instance.rs
async fn send_sighup_to_bind9_pods(
client: &Client,
namespace: &str,
instance_name: &str,
) -> Result<()> {
let pod_api: Api<Pod> = Api::namespaced(client.clone(), namespace);
// Find pods for this instance
let selector = format!("app=bind9,instance={}", instance_name);
let pods = pod_api.list(&ListParams::default().labels(&selector)).await?;
for pod in pods.items {
let pod_name = pod.metadata.name.unwrap();
// Send SIGHUP to BIND9 process (PID 1)
let attach_params = AttachParams {
container: Some("bind9".to_string()),
..Default::default()
};
match pod_api.exec(&pod_name, vec!["kill", "-HUP", "1"], &attach_params).await {
Ok(_) => info!("Sent SIGHUP to pod {}/{}", namespace, pod_name),
Err(e) => warn!("Failed to send SIGHUP to {}: {}", pod_name, e),
}
}
Ok(())
}
RBAC Changes
# deploy/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: bindy-operator
rules:
# ... existing rules ...
# NEW: Permission to exec into pods for SIGHUP
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
Testing Plan
Unit Tests
Integration Tests
# Test secret rotation
kubectl apply -f examples/bind9instance.yaml
kubectl wait --for=condition=Ready bind9instance/test-instance
# Rotate secret
kubectl delete secret test-instance-rndc-key
sleep 10
# Verify BIND9 reloaded
kubectl logs -l app=bind9,instance=test-instance | grep "reloading configuration"
rndc -s test-instance status # Should succeed with new key
# Verify status updated
kubectl get bind9instance test-instance -o jsonpath='{.status.rndcSecretVersion}'
Security Considerations
⚠️ RBAC Permission: This feature requires pods/exec permission, which allows executing commands in pods.
Mitigations:
- Use label selectors to limit scope to BIND9 pods only
- Audit log all exec operations
- Document security implications clearly
- Consider making this feature opt-in via configuration flag
Documentation Updates
Required documentation:
- User Guide: "RNDC Key Rotation" - How to rotate secrets manually and integrate with external secret managers
- Operations Guide: "Monitoring Secret Reloads" - Metrics, verification, troubleshooting
- Development Guide: "Secret Watch Implementation" - Architecture and code walkthrough
- Security Guide: "RBAC and Pod Exec" - Security implications and audit process
Success Criteria
Related
References
Summary
Implement automatic detection of RNDC secret changes and hot reload BIND9 configuration via SIGHUP signal, enabling secure key rotation without downtime.
Problem
Currently, when an RNDC secret is updated (manually or via external secret manager):
This prevents:
Proposed Solution
See ADR-0001: RNDC Secret Reload for full design.
High-level approach:
resourceVersioninBind9InstanceStatusKey benefits:
Implementation Phases
Phase 1: MVP - Basic Secret Tracking
rndc_secret_version: Option<String>toBind9InstanceStatusCRDcargo run --bin crdgensend_sighup_to_bind9_pods()helper functionreconcile_bind9_instance()pods/execpermissionPhase 2: Secret Watch
bind9_rndc_secret_reloads_total{status="success|failed"}Phase 3: Observability
RndcSecretReloadedRndcSecretReloaded,RndcSecretReloadFailedPhase 4: Advanced (Future)
Technical Details
CRD Changes
SIGHUP Implementation
RBAC Changes
Testing Plan
Unit Tests
test_secret_version_change_triggers_reload()test_sighup_sent_to_all_pod_replicas()test_sighup_failure_handling()test_no_reload_when_version_unchanged()Integration Tests
Security Considerations
pods/execpermission, which allows executing commands in pods.Mitigations:
Documentation Updates
Required documentation:
Success Criteria
Related
References