Skip to content

☂️ Remove meshServices.mode API and harvest legacy paths (3.0) #17439

Description

@Automaat

Follow-up to #17096. That umbrella flipped the meshServices.mode default to Exclusive (#17102). This one removes the field and harvests the legacy code it was keeping alive.

Why now

  • Master is the 3.0 line, and ~14 breaking ! removals of kuma.io/service-era code have landed in the last two weeks.
  • MADR 103 (docs/madr/decisions/103-universal-meshservice-generation.md) already commits to tags-removed-by-default in 3.0.
  • feat(mesh): default nil meshServices to Exclusive #17102 flipped the nil default to Exclusive, so the non-Exclusive branches are already unreachable for any mesh that never set the field. This is the deliberate follow-through.

Findings from the removal spike

Hardcoding MeshServicesMode() to Exclusive builds clean (go build ./...). Only 7 packages fail tests:

Package Cause
api/mesh/v1alpha1 the helper's own test
pkg/insights ServiceInsight / MeshInsight service stats
pkg/zone ExternalService available-services
pkg/core/managers/apis/dataplane zone tag generation
pkg/plugins/runtime/k8s/controllers pod_converter inbounds
pkg/api-server _rules legacy ToRules
pkg/core/resources/apis/meshidentity/status MeshServicesDisabled condition

(pkg/plugins/runtime/k8s/webhooks{,/injector} also fail, but they fail on a clean tree too — missing local envtest assets, unrelated.)

Removal is not a hard break on apply. All specs unmarshal via util_proto.FromJSON with AllowUnknownFields: true (pkg/util/proto/proto.go:55), and the Mesh CRD is x-kubernetes-preserve-unknown-fields. Existing YAML carrying meshServices keeps applying — silently ignored. No upgrade cliff, but a silent behavior flip for anyone explicitly on a non-Exclusive mode. See open question below.

The real prize is the VIPs subsystem. pkg/xds/context/mesh_context_builder.go:172 is the only non-self-referential reader of persisted VIPs. Removing that branch makes pkg/dns/vips_allocator.go, pkg/dns/vips/, configmap_controller.go, kube_hosts_converter.go and xds_topology.VIPOutbounds dead — roughly 1,700 LOC prod + 1,900 LOC test.

Traps found during the spike

Three things look dead but are not:

  • LegacyInboundInterfacesFor is not dead. It is gated by the separate InboundTagsDisabled experimental flag (default false), and GatewayByServiceFor calls it unconditionally for delegated gateways. Only the msMode == conjunct goes away. Killing the function is a different project.
  • MeshServiceExclusivePredicate dies, but its watch must not. The type embeds predicate.Funcs, which defaults Create/Delete/Generic to true. Deleting it naively either loses pod reconciliation on Mesh create/delete, or floods reconciles on every Mesh update. Replace with a drop-updates-only predicate.
  • ServiceInsight is not dead. It is still upserted (with an empty Services map) under Exclusive, still KDS-synced global→zone, still served by the api-server, kumactl and the GUI. Removing the type is a separate user-facing break, out of scope here.

Also: resolveTLSReadiness (mesh_context_builder.go:527-550) reads ServiceInsight services, which are always empty under Exclusive, so PERMISSIVE-mTLS readiness silently stops resolving. Guarded, so no crash, but it needs an explicit decision rather than being left to rot.

And dns.Match + the VirtualOutbound resource stay reachable via pkg/xds/generator/zoneproxy/destinations.go:292, which is not mode-gated. Do not delete them with the allocator.

Subissues

Ordered lowest-risk-first. Each sized to keep PRs small.

Parallelism: #17440 and #17441 are independent and can run in parallel. #17442 conflicts with #17441 in pkg/api-server, so sequence those two. #17443 must land after #17440#17442 (it deletes the helper they all call). #17444 must land after #17442 (it needs the mesh_context_builder branch gone) but is otherwise independent of #17443 and can run alongside it.

Open questions

  • Silent flip or loud reject? Should a Mesh validator reject meshServices outright, so users explicitly on Disabled get an error instead of a silent behavior change? There is no validator for this field today.
  • resolveTLSReadiness — delete the PERMISSIVE readiness path, or rewire it off MeshService?
  • VirtualOutbound becomes inert-but-alive after subissue 5. Deprecate separately?
  • MADR 060 (060-meshservice-migration.md) states the new behavior stays off by default and users must opt in. That premise is already stale on master. Supersede it as part of subissue 4.

Metadata

Metadata

Assignees

No one assigned

    Labels

    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