You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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 Exclusivebuilds 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.
Follow-up to #17096. That umbrella flipped the
meshServices.modedefault toExclusive(#17102). This one removes the field and harvests the legacy code it was keeping alive.Why now
!removals ofkuma.io/service-era code have landed in the last two weeks.docs/madr/decisions/103-universal-meshservice-generation.md) already commits to tags-removed-by-default in 3.0.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()toExclusivebuilds clean (go build ./...). Only 7 packages fail tests:api/mesh/v1alpha1pkg/insightspkg/zonepkg/core/managers/apis/dataplanepkg/plugins/runtime/k8s/controllerspkg/api-server_ruleslegacy ToRulespkg/core/resources/apis/meshidentity/statusMeshServicesDisabledcondition(
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.FromJSONwithAllowUnknownFields: true(pkg/util/proto/proto.go:55), and the Mesh CRD isx-kubernetes-preserve-unknown-fields. Existing YAML carryingmeshServiceskeeps 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:172is the only non-self-referential reader of persisted VIPs. Removing that branch makespkg/dns/vips_allocator.go,pkg/dns/vips/,configmap_controller.go,kube_hosts_converter.goandxds_topology.VIPOutboundsdead — roughly 1,700 LOC prod + 1,900 LOC test.Traps found during the spike
Three things look dead but are not:
LegacyInboundInterfacesForis not dead. It is gated by the separateInboundTagsDisabledexperimental flag (defaultfalse), andGatewayByServiceForcalls it unconditionally for delegated gateways. Only themsMode ==conjunct goes away. Killing the function is a different project.MeshServiceExclusivePredicatedies, but its watch must not. The type embedspredicate.Funcs, which defaults Create/Delete/Generic totrue. 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.Servicesmap) 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+ theVirtualOutboundresource stay reachable viapkg/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.
unified_naming.Enabled. Highest fanout (~30 indirect sites), no behavior change.!= Exclusiverejections with no legacy path.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 themesh_context_builderbranch gone) but is otherwise independent of #17443 and can run alongside it.Open questions
meshServicesoutright, so users explicitly onDisabledget 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?VirtualOutboundbecomes inert-but-alive after subissue 5. Deprecate separately?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.