Add a primary (write) Service routing to pod-0
ci/woodpecker/pr/build Pipeline was successful
ci/woodpecker/pr/pre-commit Pipeline was successful
ci/woodpecker/pr/test Pipeline was successful

Secondaries reject RFC2136/nsupdate writes, but the read Service round-
robins across all pods. Add an optional per-cluster write endpoint that
targets only the primary pod (ordinal 0) via the StatefulSet pod-name
label. Reads keep using the all-pods Service.

- api: BindCluster.spec.primaryService (*ClusterServiceSpec) — ClusterIP
  for in-cluster writers (external-dns) or LoadBalancer for external
- reconcilePrimaryService creates <cluster>-primary selecting pod-0 when
  set, deletes it when unset
- regenerate CRDs + install.yaml
This commit is contained in:
2026-07-04 22:29:55 +10:00
parent e0bd3973ed
commit 28ae6538cb
6 changed files with 148 additions and 9 deletions
@@ -1013,6 +1013,41 @@ spec:
type: string
description: NodeSelector for the BIND pods.
type: object
primaryService:
description: |-
PrimaryService, when set, creates an additional Service routing only to the
primary pod (ordinal 0) — the write endpoint for RFC2136/nsupdate, since
secondaries reject updates. Reads still use Service (all pods). Use
ClusterIP for in-cluster writers (e.g. external-dns) or LoadBalancer for
external writers.
properties:
annotations:
additionalProperties:
type: string
description: Annotations added to the client-facing Service (e.g.
PureLB/MetalLB hints).
type: object
externalTrafficPolicy:
description: |-
ExternalTrafficPolicy for a LoadBalancer/NodePort Service. Local preserves
client source IPs (required for source-IP ACLs on the DNS servers) but
only routes to nodes running a pod. Defaults to Cluster.
enum:
- Cluster
- Local
type: string
loadBalancerIP:
description: LoadBalancerIP requests a specific address when Type
is LoadBalancer.
type: string
type:
description: Type of the client-facing Service. Defaults to ClusterIP.
enum:
- ClusterIP
- LoadBalancer
- NodePort
type: string
type: object
recursion:
description: |-
Recursion overrides the default per-mode recursion setting. When nil,
@@ -1086,7 +1121,8 @@ spec:
type: object
type: object
service:
description: Service controls how the cluster is exposed.
description: Service controls how the cluster is exposed for reads
(all pods).
properties:
annotations:
additionalProperties:
+37 -1
View File
@@ -1318,6 +1318,41 @@ spec:
type: string
description: NodeSelector for the BIND pods.
type: object
primaryService:
description: |-
PrimaryService, when set, creates an additional Service routing only to the
primary pod (ordinal 0) — the write endpoint for RFC2136/nsupdate, since
secondaries reject updates. Reads still use Service (all pods). Use
ClusterIP for in-cluster writers (e.g. external-dns) or LoadBalancer for
external writers.
properties:
annotations:
additionalProperties:
type: string
description: Annotations added to the client-facing Service (e.g.
PureLB/MetalLB hints).
type: object
externalTrafficPolicy:
description: |-
ExternalTrafficPolicy for a LoadBalancer/NodePort Service. Local preserves
client source IPs (required for source-IP ACLs on the DNS servers) but
only routes to nodes running a pod. Defaults to Cluster.
enum:
- Cluster
- Local
type: string
loadBalancerIP:
description: LoadBalancerIP requests a specific address when Type
is LoadBalancer.
type: string
type:
description: Type of the client-facing Service. Defaults to ClusterIP.
enum:
- ClusterIP
- LoadBalancer
- NodePort
type: string
type: object
recursion:
description: |-
Recursion overrides the default per-mode recursion setting. When nil,
@@ -1391,7 +1426,8 @@ spec:
type: object
type: object
service:
description: Service controls how the cluster is exposed.
description: Service controls how the cluster is exposed for reads
(all pods).
properties:
annotations:
additionalProperties: