Module placement

Module placement 

Source
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§

PlacementContext
Everything build_pod_placement needs to know about the instance whose Pod spec is being built.
ResolvedPlacement
The Pod-spec field this module produces.

Enums§

PlacementRejection
Rejection reasons returned by validate_placement.

Functions§

build_pod_placement
Builds the Pod-spec placement fields for an instance.
resolve_placement
Resolves which placement block applies to an instance.
validate_optional_placement
Convenience wrapper for the common Option<&PlacementConfig> shape.
validate_placement
Validates a user-supplied placement block.