Skip to content

Allow excluding the arbiter from the per-pod LoadBalancer/external Service when a replset is exposed #2414

Description

@DrFaust92

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):

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions