Expand description
Pod placement: topology spreading, node selection, tolerations, affinity.
§Why this module exists
A DNS server is not an anonymous replica. A zone’s NS records name the
individual servers authoritative for it, so every primary needs a stable
identity and its own address. Bindy models that by giving each nameserver
its own Bind9Instance, its own Deployment, and its own Service — which
means a Bind9Cluster with primary.replicas: 3 produces three
single-Pod Deployments, not one three-Pod Deployment.
That shape breaks the obvious implementation of zone spreading. A
topologySpreadConstraint balances the set of Pods matched by its
labelSelector, counted per value of topologyKey. If the operator
generated a selector matching a Deployment’s own Pods, the set would have
exactly one member — always trivially balanced, so the constraint would be
satisfied by any placement and all three primaries could still land in one
zone.
The fix is SpreadScope: the selector is generated to match sibling
instances via bindy.firestoned.io/cluster + bindy.firestoned.io/role,
so the scheduler counts all primaries of a cluster as one set. Users never
write that selector themselves — they cannot know the operator’s internal
Pod labels, and a wrong selector fails silently rather than loudly.
§Defaults
With no placement block anywhere, the operator emits a single soft
(ScheduleAnyway) zone-spread constraint whenever the resolved Pod set has
two or more members. Soft is deliberate: a hard constraint turns a
single-zone cluster — or a zone outage, the very thing this feature guards
against — into Pending DNS Pods, trading degraded availability for a
total outage.
§Scope
This module handles topology spreading and nothing else. It deliberately
does not accept nodeSelector, tolerations, or affinity: those are
general pod-spec passthrough, they inflated the generated CRDs by ~450KB,
and they are exactly the primitives a namespace tenant would need to place
an operator-credentialed Pod onto a control-plane node. Keeping them out
removes that threat model rather than mitigating it. See
docs/adr/0003-pod-placement-and-zone-spreading.md.
What remains to validate is correctness, not security: rules Kubernetes
would reject, caught here so the user sees a clear condition on the CR they
edited instead of an opaque Deployment failure. Structural limits that the
CRD schema can express (rule count, label-key syntax, value ranges, and
the minDomains/DoNotSchedule pairing) are enforced at admission by the
generated schema; this module is the backstop.
Structs§
- Placement
Context - Everything
build_pod_placementneeds to know about the instance whose Pod spec is being built. - Resolved
Placement - The Pod-spec field this module produces.
Enums§
- Placement
Rejection - Rejection reasons returned by
validate_placement.
Functions§
- build_
pod_ placement - Builds the Pod-spec placement fields for an instance.
- resolve_
placement - Resolves which
placementblock applies to an instance. - validate_
optional_ placement - Convenience wrapper for the common
Option<&PlacementConfig>shape. - validate_
placement - Validates a user-supplied
placementblock.