Proposal
When a replset is exposed (replsets[].expose.enabled: true, e.g. exposeType: LoadBalancer), the operator creates a per-pod external Service for every pod in the replset — data members, non-voting members, and the arbiter. There is currently no way to opt the arbiter out.
Please add a way to skip external Service creation for arbiter pods, e.g. one of:
- a
replsets[].arbiter.expose.enabled: false override (defaulting to true for backward compatibility), or
- when the replset is exposed, have the arbiter advertise its internal cluster FQDN and skip the per-pod
Service for arbiter pods.
Use-Case
A MongoDB arbiter holds no data and never serves client reads/writes — drivers never open connections to it. In split-horizon / external-exposure deployments the external Service created for the arbiter is therefore never used by any client. It only provisions a cloud LoadBalancer (forwarding rule + external IP) and an external-DNS record per arbiter — pure cost and operational surface with no function.
Today this can't be configured away:
ensureExternalServices ranges over the full replset pod list (incl. the arbiter) and creates an ExternalService for each — there is no component filter. (pkg/controller/perconaservermongodb/external_service.go)
removeOutdatedServices explicitly preserves …-<rs>-arbiter-N services when replset.Expose.Enabled is set, so they can't simply be deleted out-of-band — the reconcile recreates them.
- The
Arbiter API type only carries enabled / size (MultiAZ inline) — there is no expose field, unlike MongosExpose. Confirmed still the case on v1.22.0.
Important nuance so this doesn't regress existing behavior: the arbiter still needs a horizon name entry. MongoDB's ReplSetConfig::_validate() requires "the same set of horizon names across all members" (otherwise replSetReconfig fails with "Saw a replica set member with a different horizon mapping than the others"). So the arbiter must keep a horizon mapping — but its value can be the internal FQDN; the horizon validation only checks name-uniformity, non-IP, and uniqueness, not external reachability. So an arbiter can participate in a split-horizon replset without needing an externally-reachable LoadBalancer.
Is this a feature you are interested in implementing yourself?
Maybe
Anything else?
Relevant code (as of v1.17.0, unchanged through v1.22.0):
ensureExternalServices, removeOutdatedServices (arbiter whitelist) — pkg/controller/perconaservermongodb/external_service.go
ExternalService() — pkg/psmdb/service.go
Arbiter struct (no expose) — pkg/apis/psmdb/v1/psmdb_types.go
Prior art that intentionally made the arbiter exposed when the replset is exposed (the behavior this request seeks to make optional):
Proposal
When a replset is exposed (
replsets[].expose.enabled: true, e.g.exposeType: LoadBalancer), the operator creates a per-pod externalServicefor every pod in the replset — data members, non-voting members, and the arbiter. There is currently no way to opt the arbiter out.Please add a way to skip external
Servicecreation for arbiter pods, e.g. one of:replsets[].arbiter.expose.enabled: falseoverride (defaulting totruefor backward compatibility), orServicefor arbiter pods.Use-Case
A MongoDB arbiter holds no data and never serves client reads/writes — drivers never open connections to it. In split-horizon / external-exposure deployments the external
Servicecreated for the arbiter is therefore never used by any client. It only provisions a cloud LoadBalancer (forwarding rule + external IP) and an external-DNS record per arbiter — pure cost and operational surface with no function.Today this can't be configured away:
ensureExternalServicesranges over the full replset pod list (incl. the arbiter) and creates anExternalServicefor each — there is no component filter. (pkg/controller/perconaservermongodb/external_service.go)removeOutdatedServicesexplicitly preserves…-<rs>-arbiter-Nservices whenreplset.Expose.Enabledis set, so they can't simply be deleted out-of-band — the reconcile recreates them.ArbiterAPI type only carriesenabled/size(MultiAZinline) — there is noexposefield, unlikeMongosExpose. Confirmed still the case onv1.22.0.Important nuance so this doesn't regress existing behavior: the arbiter still needs a horizon name entry. MongoDB's
ReplSetConfig::_validate()requires "the same set of horizon names across all members" (otherwisereplSetReconfigfails with "Saw a replica set member with a different horizon mapping than the others"). So the arbiter must keep a horizon mapping — but its value can be the internal FQDN; the horizon validation only checks name-uniformity, non-IP, and uniqueness, not external reachability. So an arbiter can participate in a split-horizon replset without needing an externally-reachable LoadBalancer.Is this a feature you are interested in implementing yourself?
Maybe
Anything else?
Relevant code (as of
v1.17.0, unchanged throughv1.22.0):ensureExternalServices,removeOutdatedServices(arbiter whitelist) —pkg/controller/perconaservermongodb/external_service.goExternalService()—pkg/psmdb/service.goArbiterstruct (noexpose) —pkg/apis/psmdb/v1/psmdb_types.goPrior art that intentionally made the arbiter exposed when the replset is exposed (the behavior this request seeks to make optional):