Repository: kumahq/kuma
Pull request #11545 (2024-09-24 16:48:31)

fix(MeshHealthCheck): apply to real resource targeted policies with MeshGateway
Needs https://github.com/kumahq/kuma/pull/11541

### Checklist prior to review

<!--
Each of these sections need to be filled by the author when opening the PR.

If something doesn't apply please check the box and add a justification after the `--`
-->

- [x] [Link to relevant issue][1] as well as docs and UI issues -- #11534 
- [x] This will not break child repos: it doesn't hardcode values (.e.g "kumahq" as a image registry) and it will work on Windows, system specific functions like `syscall.Mkfifo` have equivalent implementation on the other OS --
- [x] Tests (Unit test, E2E tests, manual test on universal and k8s) --
  - Don't forget `ci/` labels to run additional/fewer tests
- [x] Do you need to update [`UPGRADE.md`](../blob/master/UPGRADE.md)? --
- [x] Does it need to be backported according to the [backporting policy](../blob/master/CONTRIBUTING.md#backporting)? ([this](https://github.com/kumahq/kuma/actions/workflows/auto-backport.yaml) GH action will add "backport" label based on these [file globs](https://github.com/kumahq/kuma/blob/master/.github/workflows/auto-backport.yaml#L6), if you want to prevent it from adding the "backport" label use [no-backport-autolabel](https://github.com/kumahq/kuma/blob/master/.github/workflows/auto-backport.yaml#L8) label) --

<!--
> Changelog: skip
-->
<!--
Uncomment the above section to explicitly set a [`> Changelog:` entry here](https://github.com/kumahq/kuma/blob/master/CONTRIBUTING.md#submitting-a-patch)?
-->

[1]: https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword



Patch:
diff --git a/deployments/charts/kuma/crds/kuma.io_meshtraces.yaml b/deployments/charts/kuma/crds/kuma.io_meshtraces.yaml
index 19f58e12f..b16244ce6 100644
--- a/deployments/charts/kuma/crds/kuma.io_meshtraces.yaml
+++ b/deployments/charts/kuma/crds/kuma.io_meshtraces.yaml
@@ -142,7 +142,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -153,13 +153,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -169,7 +169,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.
diff --git a/docs/generated/openapi.yaml b/docs/generated/openapi.yaml
index 8af55e013..62a797174 100644
--- a/docs/generated/openapi.yaml
+++ b/docs/generated/openapi.yaml
@@ -10653,7 +10653,7 @@ components:
                       anyOf:
                         - type: integer
                         - type: string
-                      default: 100%
+                      default: 100
                       description: >-
                         Target percentage of requests that will be force traced
                         if the
@@ -10669,7 +10669,7 @@ components:
                       anyOf:
                         - type: integer
                         - type: string
-                      default: 100%
+                      default: 100
                       description: >-
                         Target percentage of requests will be traced
 
@@ -10679,11 +10679,11 @@ components:
                         random sampling). This field functions as an upper limit
                         on the total
 
-                        configured sampling rate. For instance, setting
-                        client_sampling to 100%
+                        configured sampling rate. For instance, setting client
+                        to 100
 
-                        but overall_sampling to 1% will result in only 1% of
-                        client requests with
+                        but overall to 1 will result in only 1% of client
+                        requests with
 
                         the appropriate headers to be force traced. Mirror of
 
@@ -10697,7 +10697,7 @@ components:
                       anyOf:
                         - type: integer
                         - type: string
-                      default: 100%
+                      default: 100
                       description: >-
                         Target percentage of requests that will be randomly
                         selected for trace
diff --git a/docs/generated/raw/crds/kuma.io_meshtraces.yaml b/docs/generated/raw/crds/kuma.io_meshtraces.yaml
index 19f58e12f..b16244ce6 100644
--- a/docs/generated/raw/crds/kuma.io_meshtraces.yaml
+++ b/docs/generated/raw/crds/kuma.io_meshtraces.yaml
@@ -142,7 +142,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -153,13 +153,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -169,7 +169,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.
diff --git a/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin.go b/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin.go
index ed8d658bb..6db92ca71 100644
--- a/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin.go
+++ b/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin.go
@@ -8,6 +8,7 @@ import (
 	core_plugins "github.com/kumahq/kuma/pkg/core/plugins"
 	core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh"
 	meshexternalservice_api "github.com/kumahq/kuma/pkg/core/resources/apis/meshexternalservice/api/v1alpha1"
+	core_model "github.com/kumahq/kuma/pkg/core/resources/model"
 	core_xds "github.com/kumahq/kuma/pkg/core/xds"
 	xds_types "github.com/kumahq/kuma/pkg/core/xds/types"
 	"github.com/kumahq/kuma/pkg/plugins/policies/core/matchers"
@@ -51,7 +52,7 @@ func (p plugin) Apply(rs *core_xds.ResourceSet, ctx xds_context.Context, proxy *
 		return err
 	}
 
-	if err := applyToGateways(policies.GatewayRules, clusters.Gateway, proxy); err != nil {
+	if err := applyToGateways(ctx.Mesh, proxy, rs, policies.GatewayRules, clusters.Gateway); err != nil {
 		return err
 	}
 
@@ -86,10 +87,14 @@ func applyToOutbounds(
 }
 
 func applyToGateways(
+	meshCtx xds_context.MeshContext,
+	proxy *core_xds.Proxy,
+	rs *core_xds.ResourceSet,
 	gatewayRules core_rules.GatewayRules,
 	gatewayClusters map[string]*envoy_cluster.Cluster,
-	proxy *core_xds.Proxy,
 ) error {
+	resourcesByOrigin := rs.IndexByOrigin(core_xds.NonMeshExternalService)
+
 	for _, listenerInfo := range gateway_plugin.ExtractGatewayListeners(proxy) {
 		for _, listenerHostname := range listenerInfo.ListenerHostnames {
 			inboundListener := rules.NewInboundListenerHostname(
@@ -124,6 +129,22 @@ func applyToGateways(
 					); err != nil {
 						return err
 					}
+
+					if dest.BackendRef == nil {
+						continue
+					}
+					if realRef := dest.BackendRef.ResourceOrNil(); realRef != nil {
+						resources := resourcesByOrigin[*realRef]
+						if err := applyToRealResource(
+							meshCtx,
+							rules.ResourceRules,
+							proxy.Dataplane.Spec.TagSet(),
+							*realRef,
+							resources,
+						); err != nil {
+							return err
+						}
+					}
 				}
 			}
 		}
@@ -201,23 +222,31 @@ func applyToEgressRealResources(rs *core_xds.ResourceSet, proxy *core_xds.Proxy)
 	return nil
 }
 
-func applyToRealResources(rs *core_xds.ResourceSet, rules core_rules.ResourceRules, meshCtx xds_context.MeshContext, tagSet mesh_proto.MultiValueTagSet) error {
-	for uri, resType := range rs.IndexByOrigin(core_xds.NonMeshExternalService) {
-		conf := rules.Compute(uri, meshCtx.Resources)
-		if conf == nil {
-			continue
-		}
+func applyToRealResource(meshCtx xds_context.MeshContext, rules core_rules.ResourceRules, tagSet mesh_proto.MultiValueTagSet, uri core_model.TypedResourceIdentifier, resourcesByType core_xds.ResourcesByType) error {
+	conf := rules.Compute(uri, meshCtx.Resources)
+	if conf == nil {
+		return nil
+	}
 
-		for typ, resources := range resType {
-			switch typ {
-			case envoy_resource.ClusterType:
-				err := configureClusters(resources, conf.Conf[0].(api.Conf), tagSet)
-				if err != nil {
-					return err
-				}
+	for typ, resources := range resourcesByType {
+		switch typ {
+		case envoy_resource.ClusterType:
+			err := configureClusters(resources, conf.Conf[0].(api.Conf), tagSet)
+			if err != nil {
+				return err
 			}
 		}
 	}
+
+	return nil
+}
+
+func applyToRealResources(rs *core_xds.ResourceSet, rules core_rules.ResourceRules, meshCtx xds_context.MeshContext, tagSet mesh_proto.MultiValueTagSet) error {
+	for uri, resType := range rs.IndexByOrigin(core_xds.NonMeshExternalService) {
+		if err := applyToRealResource(meshCtx, rules, tagSet, uri, resType); err != nil {
+			return err
+		}
+	}
 	return nil
 }
 
diff --git a/pkg/plugins/policies/meshtrace/api/v1alpha1/meshtrace.go b/pkg/plugins/policies/meshtrace/api/v1alpha1/meshtrace.go
index 475206295..c2b01d83e 100644
--- a/pkg/plugins/policies/meshtrace/api/v1alpha1/meshtrace.go
+++ b/pkg/plugins/policies/meshtrace/api/v1alpha1/meshtrace.go
@@ -103,26 +103,26 @@ type Sampling struct {
 	// Target percentage of requests will be traced
 	// after all other sampling checks have been applied (client, force tracing,
 	// random sampling). This field functions as an upper limit on the total
-	// configured sampling rate. For instance, setting client_sampling to 100%
-	// but overall_sampling to 1% will result in only 1% of client requests with
+	// configured sampling rate. For instance, setting client to 100
+	// but overall to 1 will result in only 1% of client requests with
 	// the appropriate headers to be force traced. Mirror of
 	// overall_sampling in Envoy
 	// https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
 	// Either int or decimal represented as string.
-	// +kubebuilder:default="100%"
+	// +kubebuilder:default=100
 	Overall *intstr.IntOrString `json:"overall,omitempty"`
 	// Target percentage of requests that will be force traced if the
 	// 'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
 	// https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L127-L133
 	// Either int or decimal represented as string.
-	// +kubebuilder:default="100%"
+	// +kubebuilder:default=100
 	Client *intstr.IntOrString `json:"client,omitempty"`
 	// Target percentage of requests that will be randomly selected for trace
 	// generation, if not requested by the client or not forced.
 	// Mirror of random_sampling in Envoy
 	// https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L135-L140
 	// Either int or decimal represented as string.
-	// +kubebuilder:default="100%"
+	// +kubebuilder:default=100
 	Random *intstr.IntOrString `json:"random,omitempty"`
 }
 
diff --git a/pkg/plugins/policies/meshtrace/api/v1alpha1/schema.yaml b/pkg/plugins/policies/meshtrace/api/v1alpha1/schema.yaml
index 605d9fca6..201175a2c 100644
--- a/pkg/plugins/policies/meshtrace/api/v1alpha1/schema.yaml
+++ b/pkg/plugins/policies/meshtrace/api/v1alpha1/schema.yaml
@@ -115,7 +115,7 @@ properties:
                 anyOf:
                   - type: integer
                   - type: string
-                default: 100%
+                default: 100
                 description: |-
                   Target percentage of requests that will be force traced if the
                   'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -126,13 +126,13 @@ properties:
                 anyOf:
                   - type: integer
                   - type: string
-                default: 100%
+                default: 100
                 description: |-
                   Target percentage of requests will be traced
                   after all other sampling checks have been applied (client, force tracing,
                   random sampling). This field functions as an upper limit on the total
-                  configured sampling rate. For instance, setting client_sampling to 100%
-                  but overall_sampling to 1% will result in only 1% of client requests with
+                  configured sampling rate. For instance, setting client to 100
+                  but overall to 1 will result in only 1% of client requests with
                   the appropriate headers to be force traced. Mirror of
                   overall_sampling in Envoy
                   https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -142,7 +142,7 @@ properties:
                 anyOf:
                   - type: integer
                   - type: string
-                default: 100%
+                default: 100
                 description: |-
                   Target percentage of requests that will be randomly selected for trace
                   generation, if not requested by the client or not forced.
diff --git a/pkg/plugins/policies/meshtrace/k8s/crd/kuma.io_meshtraces.yaml b/pkg/plugins/policies/meshtrace/k8s/crd/kuma.io_meshtraces.yaml
index 19f58e12f..b16244ce6 100644
--- a/pkg/plugins/policies/meshtrace/k8s/crd/kuma.io_meshtraces.yaml
+++ b/pkg/plugins/policies/meshtrace/k8s/crd/kuma.io_meshtraces.yaml
@@ -142,7 +142,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -153,13 +153,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -169,7 +169,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.


Test patch:
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml
index cb19c2f25..2e1a99c60 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.defaults.golden.yaml
@@ -6913,7 +6913,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -6924,13 +6924,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -6940,7 +6940,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml
index 28d114edc..7b33cc5c3 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.gateway-api-present.yaml
@@ -6913,7 +6913,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -6924,13 +6924,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -6940,7 +6940,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.
diff --git a/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml b/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml
index 8cfcf12e3..bc430e24e 100644
--- a/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml
+++ b/app/kumactl/cmd/install/testdata/install-control-plane.with-helm-set.yaml
@@ -6933,7 +6933,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -6944,13 +6944,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -6960,7 +6960,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.
diff --git a/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml b/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml
index c41ee65e9..f3cac3562 100644
--- a/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml
+++ b/app/kumactl/cmd/install/testdata/install-crds.all.golden.yaml
@@ -8399,7 +8399,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be force traced if the
                           'x-client-trace-id' header is set. Mirror of client_sampling in Envoy
@@ -8410,13 +8410,13 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests will be traced
                           after all other sampling checks have been applied (client, force tracing,
                           random sampling). This field functions as an upper limit on the total
-                          configured sampling rate. For instance, setting client_sampling to 100%
-                          but overall_sampling to 1% will result in only 1% of client requests with
+                          configured sampling rate. For instance, setting client to 100
+                          but overall to 1 will result in only 1% of client requests with
                           the appropriate headers to be force traced. Mirror of
                           overall_sampling in Envoy
                           https://github.com/envoyproxy/envoy/blob/v1.22.0/api/envoy/config/filter/network/http_connection_manager/v2/http_connection_manager.proto#L142-L150
@@ -8426,7 +8426,7 @@ spec:
                         anyOf:
                         - type: integer
                         - type: string
-                        default: 100%
+                        default: 100
                         description: |-
                           Target percentage of requests that will be randomly selected for trace
                           generation, if not requested by the client or not forced.
diff --git a/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin_test.go b/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin_test.go
index 1a0e8330f..46b847dff 100644
--- a/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin_test.go
+++ b/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/plugin_test.go
@@ -54,10 +54,8 @@ var _ = Describe("MeshHealthCheck", func() {
 
 	backendMeshServiceIdentifier := core_model.TypedResourceIdentifier{
 		ResourceIdentifier: core_model.ResourceIdentifier{
-			Name:      "backend",
-			Mesh:      "default",
-			Namespace: "backend-ns",
-			Zone:      "zone-1",
+			Name: "backend",
+			Mesh: "default",
 		},
 		ResourceType: "MeshService",
 		SectionName:  "",
@@ -662,6 +660,119 @@ var _ = Describe("MeshHealthCheck", func() {
 				},
 			},
 		}),
+		Entry("real MeshService targeted HTTP HealthCheck to real MeshService", gatewayTestCase{
+			name: "real-mesh-service-target-real-mesh-service-meshhttproute",
+			meshservices: []*meshservice_api.MeshServiceResource{
+				{
+					Meta: &test_model.ResourceMeta{Name: "backend", Mesh: "default"},
+					Spec: &meshservice_api.MeshService{
+						Selector: meshservice_api.Selector{},
+						Ports: []meshservice_api.Port{{
+							Port:        80,
+							TargetPort:  intstr.FromInt(8084),
+							AppProtocol: core_mesh.ProtocolHTTP,
+						}},
+						Identities: []meshservice_api.MeshServiceIdentity{
+							{
+								Type:  meshservice_api.MeshServiceIdentityServiceTagType,
+								Value: "backend",
+							},
+							{
+								Type:  meshservice_api.MeshServiceIdentityServiceTagType,
+								Value: "other-backend",
+							},
+						},
+					},
+					Status: &meshservice_api.MeshServiceStatus{
+						VIPs: []meshservice_api.VIP{{
+							IP: "10.0.0.1",
+						}},
+					},
+				},
+			},
+			meshhttproutes: core_rules.GatewayRules{
+				ToRules: core_rules.GatewayToRules{
+					ByListenerAndHostname: map[core_rules.InboundListenerHostname]core_rules.ToRules{
+						rules.NewInboundListenerHostname("192.168.0.1", 8080, "*"): {
+							Rules: core_rules.Rules{{
+								Subset: core_rules.MeshSubset(),
+								Conf: meshhttproute_api.PolicyDefault{
+									Rules: []meshhttproute_api.Rule{{
+										Matches: []meshhttproute_api.Match{{
+											Path: &meshhttproute_api.PathMatch{
+												Type:  meshhttproute_api.Exact,
+												Value: "/",
+											},
+										}},
+										Default: meshhttproute_api.RuleConf{
+											BackendRefs: &[]common_api.BackendRef{{
+												TargetRef: builders.TargetRefService("backend"),
+												Port:      pointer.To(uint32(80)),
+												Weight:    pointer.To(uint(100)),
+											}},
+										},
+									}},
+								},
+								Origin: []core_model.ResourceMeta{
+									&test_model.ResourceMeta{Mesh: "default", Name: "http-route"},
+								},
+								BackendRefOriginIndex: core_rules.BackendRefOriginIndex{
+									meshhttproute_api.HashMatches([]meshhttproute_api.Match{{Path: &meshhttproute_api.PathMatch{Type: meshhttproute_api.Exact, Value: "/"}}}): 0,
+								},
+							}},
+						},
+					},
+				},
+			},
+			rules: core_rules.GatewayRules{
+				ToRules: core_rules.GatewayToRules{
+					ByListenerAndHostname: map[core_rules.InboundListenerHostname]core_rules.ToRules{
+						rules.NewInboundListenerHostname("192.168.0.1", 8080, "*"): {
+							ResourceRules: map[core_model.TypedResourceIdentifier]core_rules.ResourceRule{
+								backendMeshServiceIdentifier: {
+									Conf: []interface{}{
+										api.Conf{
+											Interval:                     test.ParseDuration("10s"),
+											Timeout:                      test.ParseDuration("2s"),
+											UnhealthyThreshold:           pointer.To[int32](3),
+											HealthyThreshold:             pointer.To[int32](1),
+											InitialJitter:                test.ParseDuration("13s"),
+											IntervalJitter:               test.ParseDuration("15s"),
+											IntervalJitterPercent:        pointer.To[int32](10),
+											HealthyPanicThreshold:        pointer.To(intstr.FromString("62.9")),
+											FailTrafficOnPanic:           pointer.To(true),
+											EventLogPath:                 pointer.To("/tmp/log.txt"),
+											AlwaysLogHealthCheckFailures: pointer.To(false),
+											NoTrafficInterval:            test.ParseDuration("16s"),
+											Http: &api.HttpHealthCheck{
+												Disabled: pointer.To(false),
+												Path:     pointer.To("/health"),
+												RequestHeadersToAdd: &api.HeaderModifier{
+													Add: []api.HeaderKeyValue{
+														{
+															Name:  "x-some-header",
+															Value: "value",
+														},
+													},
+													Set: []api.HeaderKeyValue{
+														{
+															Name:  "x-some-other-header",
+															Value: "value",
+														},
+													},
+												},
+												ExpectedStatuses: &[]int32{200, 201},
+											},
+											ReuseConnection: pointer.To(true),
+										},
+									},
+								},
+							},
+						},
+					},
+				},
+			},
+		}),
 		Entry("basic outbound cluster with TCP/HTTP health check and MeshTCPRoute/MeshHTTPRoute", gatewayTestCase{
 			name: "basic-meshhttproute",
 			meshhttproutes: core_rules.GatewayRules{
diff --git a/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/testdata/real-mesh-service-target-real-mesh-service-meshhttproute.gateway_cluster.golden.yaml b/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/testdata/real-mesh-service-target-real-mesh-service-meshhttproute.gateway_cluster.golden.yaml
new file mode 100644
index 000000000..d9a2b0457
--- /dev/null
+++ b/pkg/plugins/policies/meshhealthcheck/plugin/v1alpha1/testdata/real-mesh-service-target-real-mesh-service-meshhttproute.gateway_cluster.golden.yaml
@@ -0,0 +1,55 @@
+resources:
+- name: default_backend___msvc_80-e3a0069bda479bd1
+  resource:
+    '@type': type.googleapis.com/envoy.config.cluster.v3.Cluster
+    commonLbConfig:
+      healthyPanicThreshold:
+        value: 62.9
+      zoneAwareLbConfig:
+        failTrafficOnPanic: true
+    edsClusterConfig:
+      edsConfig:
+        ads: {}
+        initialFetchTimeout: 0s
+        resourceApiVersion: V3
+    healthChecks:
+    - eventLogger:
+      - name: envoy.health_check.event_sinks.file
+        typedConfig:
+          '@type': type.googleapis.com/envoy.extensions.health_check.event_sinks.file.v3.HealthCheckEventFileSink
+          eventLogPath: /tmp/log.txt
+      healthyThreshold: 1
+      httpHealthCheck:
+        expectedStatuses:
+        - end: "201"
+          start: "200"
+        - end: "202"
+          start: "201"
+        path: /health
+        requestHeadersToAdd:
+        - header:
+            key: x-kuma-tags
+            value: '&kuma.io/service=sample-gateway&'
+        - header:
+            key: x-some-header
+            value: value
+        - appendAction: OVERWRITE_IF_EXISTS_OR_ADD
+          header:
+            key: x-some-other-header
+            value: value
+      initialJitter: 13s
+      interval: 10s
+      intervalJitter: 15s
+      intervalJitterPercent: 10
+      noTrafficInterval: 16s
+      reuseConnection: true
+      timeout: 2s
+      unhealthyThreshold: 3
+    name: default_backend___msvc_80-e3a0069bda479bd1
+    perConnectionBufferLimitBytes: 32768
+    type: EDS
+    typedExtensionProtocolOptions:
+      envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
+        '@type': type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
+        explicitHttpConfig:
+          httpProtocolOptions: {}
diff --git a/test/e2e/helm/kuma_helm_upgrade_multizone.go b/test/e2e/helm/kuma_helm_upgrade_multizone.go
index 83ac2ed85..9b4f20807 100644
--- a/test/e2e/helm/kuma_helm_upgrade_multizone.go
+++ b/test/e2e/helm/kuma_helm_upgrade_multizone.go
@@ -20,6 +20,7 @@ import (
 )
 
 func UpgradingWithHelmChartMultizone() {
+	namespace := "helm-upgrade-ns"
 	var global, zoneK8s, zoneUniversal Cluster
 	var globalCP ControlPlane
 
@@ -42,7 +43,7 @@ func UpgradingWithHelmChartMultizone() {
 		}()
 		go func() {
 			defer grp.Done()
-			Expect(zoneK8s.DeleteNamespace(TestNamespace)).To(Succeed())
+			Expect(zoneK8s.DeleteNamespace(namespace)).To(Succeed())
 			Expect(zoneK8s.DeleteKuma()).To(Succeed())
 			Expect(zoneK8s.DismissCluster()).To(Succeed())
 		}()
@@ -114,8 +115,8 @@ spec:
 			By("Sync DPPs from Zone to Global")
 			// when start test server on Zone
 			err = NewClusterSetup().
-				Install(NamespaceWithSidecarInjection(TestNamespace)).
-				Install(testserver.Install()).Setup(zoneK8s)
+				Install(NamespaceWithSidecarInjection(namespace)).
+				Install(testserver.Install(testserver.WithNamespace(namespace))).Setup(zoneK8s)
 			Expect(err).ToNot(HaveOccurred())
 
 			Eventually(func(g Gomega) (int, error) {
diff --git a/test/e2e_env/universal/universal_suite_test.go b/test/e2e_env/universal/universal_suite_test.go
index bc5f21e69..d27bd4d7b 100644
--- a/test/e2e_env/universal/universal_suite_test.go
+++ b/test/e2e_env/universal/universal_suite_test.go
@@ -91,7 +91,8 @@ var (
 	_ = Describe("Reachable Services", reachableservices.ReachableServices, Ordered)
 	_ = Describe("Apis", api.Api, Ordered)
 	_ = Describe("Traffic Permission", trafficpermission.TrafficPermission, Ordered)
-	_ = Describe("Traffic Route", trafficroute.TrafficRoute, Ordered)
+	// FlakeAttempts to cover https://github.com/kumahq/kuma/issues/11546
+	_ = Describe("Traffic Route", trafficroute.TrafficRoute, Ordered, FlakeAttempts(3))
 	_ = Describe("Zone Egress", zoneegress.ExternalServices, Ordered)
 	_ = Describe("Virtual Outbound", virtualoutbound.VirtualOutbound, Ordered)
 	_ = Describe("Transparent Proxy", transparentproxy.TransparentProxy, Ordered)
diff --git a/test/framework/deployments/observability/kubernetes.go b/test/framework/deployments/observability/kubernetes.go
index bfddaf476..c08976329 100644
--- a/test/framework/deployments/observability/kubernetes.go
+++ b/test/framework/deployments/observability/kubernetes.go
@@ -76,5 +76,5 @@ func (t *k8SDeployment) Deploy(cluster framework.Cluster) error {
 }
 
 func (t *k8SDeployment) Delete(cluster framework.Cluster) error {
-	return cluster.DeleteNamespace(t.namespace)
+	return cluster.(*framework.K8sCluster).TriggerDeleteNamespace(t.namespace)
 }