Skip to content

VMCluster/VMAlertmanager: reject serviceSpec.type override with useAsDefault - #2491

Open
mehrdadbn9 wants to merge 3 commits into
VictoriaMetrics:masterfrom
mehrdadbn9:fix/vmcluster-service-type-override-validation
Open

VMCluster/VMAlertmanager: reject serviceSpec.type override with useAsDefault#2491
mehrdadbn9 wants to merge 3 commits into
VictoriaMetrics:masterfrom
mehrdadbn9:fix/vmcluster-service-type-override-validation

Conversation

@mehrdadbn9

@mehrdadbn9 mehrdadbn9 commented Aug 12, 2026

Copy link
Copy Markdown

What

Follows up on #2487. As discussed in the issue, the default Service of vmselect, vmstorage and vmalertmanager is intentionally headless (clusterIP: None) because it also exposes cluster-native / gossip ports. Because of that, combining serviceSpec.useAsDefault: true with an explicit spec.type silently produces a service that is still headless - the user gets no error and no VIP, which is confusing.

Per the maintainer's suggestion in #2487 (comment) (prohibit overriding the service type for these components when useAsDefault: true), this PR makes the operator reject that combination with a clear error message instead of silently ignoring it.

Changes

  • AdditionalServiceSpec.ValidateNoServiceTypeOverrideWithUseAsDefault(component) - new helper that rejects an explicit spec.type when useAsDefault is set.
  • Wired into VMCluster.Validate() for vmselect and vmstorage.
  • Wired into VMAlertmanager.Validate() for vmalertmanager.
  • vminsert is intentionally left allowed: its default Service is not headless, so an explicit type override there works as expected.

Users who need a different service type can still create a separate additional Service by setting serviceSpec.useAsDefault: false with a distinct metadata.name.

Tests

Added unit test cases covering: reject for vmselect/vmstorage/vmalertmanager, allow when no explicit type is set, allow separate additional services, and allow type override for vminsert.

go build ./...          # OK
go vet ./operator/v1beta1/  # OK
go test ./operator/v1beta1/  # ok (full package)

Feedback welcome - happy to adjust the error message wording or the scope if you'd rather also cover vminsert.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 5 files

Reply with feedback, questions, or to request a fix.

Fix all with cubic | Re-trigger cubic

Comment thread api/operator/v1beta1/vmextra_types.go Outdated

@AndrewChubatiuk AndrewChubatiuk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for a PR! Overall it's good, left some comments. Same changes probably should be propagated to all select and storage components as they also unconditionally set ClusterIP type

Comment thread api/operator/v1beta1/vmextra_types.go Outdated
Comment on lines +399 to +407
// ValidateNoServiceTypeOverrideWithUseAsDefault rejects an explicit service type
// combined with useAsDefault for components whose default service is headless
// (vmselect, vmstorage, vmalertmanager). Those services must stay headless
// (clusterIP: None) for cluster-native communication: an explicit type: ClusterIP
// would be silently ignored (the headless clusterIP is inherited from the default
// service), while type: LoadBalancer/NodePort would be honored and produce a
// non-headless service that breaks cluster-native discovery. Reject the combination
// loudly so users pick an intended setup: drop the type override, or create a
// separate additional service (useAsDefault=false with a distinct metadata.name).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please make this comment brief, it's a trivial check not need to have this multiline explanantion

Comment thread api/operator/v1beta1/vmextra_types.go Outdated
return nil
}
if asc.Spec.Type != "" {
return fmt.Errorf("serviceSpec.useAsDefault cannot be combined with an explicit spec.type=%q for %s: the default service is headless (clusterIP: None) and must stay headless for cluster-native communication (an explicit type is either silently ignored or produces a non-headless service that breaks it). Remove spec.type from the serviceSpec override, or create a separate service by setting serviceSpec.useAsDefault=false with a distinct metadata.name", asc.Spec.Type, component)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same is here, additionally no need to pass component name here,

…tion (VictoriaMetrics#2491)

- Shorten the helper GoDoc/rationale comment (it was a trivial check,
  no need for the multiline explanation).
- Remove the unused component-name parameter from
  ValidateNoServiceTypeOverrideWithUseAsDefault(); the error message no
  longer references a specific component.
- Correct the rationale: the default service must stay headless
  (clusterIP: None) for cluster-native communication; an explicit
  spec.type with useAsDefault=true is rejected so users pick an intended
  setup (per VictoriaMetrics#2487).
- Applied to vmselect, vmstorage (VMCluster) and vmalertmanager.

vminsert is intentionally left allowed: its default Service is not
headless, so an explicit type override there works as expected.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Mehrdad Biukian Naeini <mehrdad.biu@mtnirancell.ir>
@mehrdadbn9

Copy link
Copy Markdown
Author

Thanks @AndrewChubatiuk — addressed the feedback:

  • Shortened the helper GoDoc/rationale (it was a trivial check, no need for the multiline explanation).
  • Removed the component parameter from ValidateNoServiceTypeOverrideWithUseAsDefault(); the error message no longer names a specific component.
  • Corrected the rationale: the default service must stay headless (clusterIP: None) for cluster-native communication; an explicit spec.type with useAsDefault=true is rejected (per VMCluster: serviceSpec.useAsDefault cannot change vmselect Service from headless to ClusterIP #2487). (The earlier wording about "silently ignored" was inaccurate — build.Service does honor an explicit type override.)
  • Applied to vmselect, vmstorage (VMCluster) and vmalertmanager.

On propagation to all select/storage components: I deliberately kept vminsert allowed, because its default Service is not headless (unlike vmselect/vmstorage/vmalertmanager), so an explicit type override there works as intended and shouldn't be rejected. If you'd still like vminsert covered (or the standalone CRDs like VMAgent/VMAlert/VMSingle), let me know and I'll extend it.

Force-pushed 84715de. Full api module test suite passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants