Repository: envoyproxy/gateway
Pull request #4173 (2024-09-07 01:49:55)

[release/v1.1] Cherry-pick commits for v1.1.1
Brings in

* https://github.com/envoyproxy/gateway/pull/3990
* https://github.com/envoyproxy/gateway/pull/4000
* https://github.com/envoyproxy/gateway/pull/4008
* https://github.com/envoyproxy/gateway/pull/4021
* https://github.com/envoyproxy/gateway/pull/4031
* https://github.com/envoyproxy/gateway/pull/4073
* https://github.com/envoyproxy/gateway/pull/4090
* https://github.com/envoyproxy/gateway/pull/4126
* https://github.com/envoyproxy/gateway/pull/4144
* https://github.com/envoyproxy/gateway/pull/4074
* https://github.com/envoyproxy/gateway/pull/4175

arkodg: note I didnt bring in https://github.com/envoyproxy/gateway/pull/4095 since the cherry-pick was non trivial
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) Report
Attention: Patch coverage is `62.96296%` with `30 lines` in your changes missing coverage. Please review.
> Project coverage is 67.33%. Comparing base [(`d5da74f`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/d5da74f16046fc6d0dd13655fa8a44129a5d2d27?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`9a5e78c`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/9a5e78c1085869139238847efac2683b60d23105?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).
> Report is 1 commits behind head on release/v1.1.

| [Files with missing lines](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) | Patch % | Lines |
|---|---|---|
| [internal/provider/kubernetes/controller.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?src=pr&el=tree&filepath=internal%2Fprovider%2Fkubernetes%2Fcontroller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvcHJvdmlkZXIva3ViZXJuZXRlcy9jb250cm9sbGVyLmdv) | 0.00% | [19 Missing :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/xds/translator/route.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?src=pr&el=tree&filepath=internal%2Fxds%2Ftranslator%2Froute.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwveGRzL3RyYW5zbGF0b3Ivcm91dGUuZ28=) | 57.14% | [7 Missing and 2 partials :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/gatewayapi/helpers.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?src=pr&el=tree&filepath=internal%2Fgatewayapi%2Fhelpers.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwvZ2F0ZXdheWFwaS9oZWxwZXJzLmdv) | 90.00% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |

<details><summary>Additional details and impacted files</summary>


```diff
@@               Coverage Diff                @@
##           release/v1.1    #4173      +/-   ##
================================================
- Coverage         67.42%   67.33%   -0.09%     
================================================
  Files               183      183              
  Lines             22435    22476      +41     
================================================
+ Hits              15126    15134       +8     
- Misses             6221     6249      +28     
- Partials           1088     1093       +5     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/4173?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

zirain: we may need https://github.com/envoyproxy/gateway/pull/4175?

Patch:
diff --git a/examples/extension-server/go.mod b/examples/extension-server/go.mod
index b5ebd93dc..91f5323ca 100644
--- a/examples/extension-server/go.mod
+++ b/examples/extension-server/go.mod
@@ -1,6 +1,6 @@
 module github.com/exampleorg/envoygateway-extension
 
-go 1.22.5
+go 1.22.7
 
 require (
 	github.com/envoyproxy/gateway v1.0.2
diff --git a/examples/extension-server/tools/src/controller-gen/go.mod b/examples/extension-server/tools/src/controller-gen/go.mod
index 3b5da982d..e1eab3409 100644
--- a/examples/extension-server/tools/src/controller-gen/go.mod
+++ b/examples/extension-server/tools/src/controller-gen/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require sigs.k8s.io/controller-tools v0.15.0
 
diff --git a/examples/kubernetes/ext-proc-grpc-service.yaml b/examples/kubernetes/ext-proc-grpc-service.yaml
index 23b90b104..de94ccf90 100644
--- a/examples/kubernetes/ext-proc-grpc-service.yaml
+++ b/examples/kubernetes/ext-proc-grpc-service.yaml
@@ -361,7 +361,7 @@ spec:
             - sh
             - "-c"
             - "cp -a /app /app-live && cd /app-live && go  run . --certPath=/app-live/certs/ "
-          image: golang:1.22.5-alpine
+          image: golang:1.22.7-alpine
           ports:
             - containerPort: 8000
           volumeMounts:
diff --git a/go.mod b/go.mod
index 9f3ccfb95..6891c1acb 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway
 
-go 1.22.5
+go 1.22.7
 
 replace github.com/imdario/mergo => github.com/imdario/mergo v0.3.16
 
diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index 6babdfa81..190df4f5d 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -10,6 +10,7 @@ import (
 	"fmt"
 	"math"
 	"math/big"
+	"net/http"
 	"sort"
 	"strings"
 	"time"
@@ -962,6 +963,12 @@ func (t *Translator) buildHTTPActiveHealthChecker(h *egv1a1.HTTPActiveHealthChec
 	for _, r := range h.ExpectedStatuses {
 		statusSet.Insert(int(r))
 	}
+
+	// If no ExpectedStatus was set, use the default value (200)
+	if statusSet.Len() == 0 {
+		statusSet.Insert(http.StatusOK)
+	}
+
 	irStatuses := make([]ir.HTTPStatus, 0, statusSet.Len())
 
 	for _, r := range statusSet.List() {
diff --git a/internal/gatewayapi/conformance/suite.go b/internal/gatewayapi/conformance/suite.go
index 4637e0237..4fafa0089 100644
--- a/internal/gatewayapi/conformance/suite.go
+++ b/internal/gatewayapi/conformance/suite.go
@@ -15,7 +15,6 @@ import (
 // SkipTests is a list of tests that are skipped in the conformance suite.
 var SkipTests = []suite.ConformanceTest{
 	tests.GatewayStaticAddresses,
-	tests.GatewayHTTPListenerIsolation, // https://github.com/envoyproxy/gateway/issues/3352
 }
 
 func skipTestsShortNames(skipTests []suite.ConformanceTest) []string {
diff --git a/internal/gatewayapi/filters.go b/internal/gatewayapi/filters.go
index b3d2ddb40..aecc2e811 100644
--- a/internal/gatewayapi/filters.go
+++ b/internal/gatewayapi/filters.go
@@ -445,7 +445,7 @@ func (t *Translator) processRequestHeaderModifierFilter(
 			newHeader := ir.AddHeader{
 				Name:   headerKey,
 				Append: true,
-				Value:  addHeader.Value,
+				Value:  strings.Split(addHeader.Value, ","),
 			}
 
 			filterContext.AddRequestHeaders = append(filterContext.AddRequestHeaders, newHeader)
@@ -500,7 +500,7 @@ func (t *Translator) processRequestHeaderModifierFilter(
 			newHeader := ir.AddHeader{
 				Name:   string(setHeader.Name),
 				Append: false,
-				Value:  setHeader.Value,
+				Value:  strings.Split(setHeader.Value, ","),
 			}
 
 			filterContext.AddRequestHeaders = append(filterContext.AddRequestHeaders, newHeader)
@@ -617,7 +617,7 @@ func (t *Translator) processResponseHeaderModifierFilter(
 			newHeader := ir.AddHeader{
 				Name:   headerKey,
 				Append: true,
-				Value:  addHeader.Value,
+				Value:  strings.Split(addHeader.Value, ","),
 			}
 
 			filterContext.AddResponseHeaders = append(filterContext.AddResponseHeaders, newHeader)
@@ -672,7 +672,7 @@ func (t *Translator) processResponseHeaderModifierFilter(
 			newHeader := ir.AddHeader{
 				Name:   string(setHeader.Name),
 				Append: false,
-				Value:  setHeader.Value,
+				Value:  strings.Split(setHeader.Value, ","),
 			}
 
 			filterContext.AddResponseHeaders = append(filterContext.AddResponseHeaders, newHeader)
diff --git a/internal/gatewayapi/helpers.go b/internal/gatewayapi/helpers.go
index 22c81032e..a6e13720e 100644
--- a/internal/gatewayapi/helpers.go
+++ b/internal/gatewayapi/helpers.go
@@ -262,12 +262,12 @@ func servicePortToContainerPort(servicePort int32, envoyProxy *egv1a1.EnvoyProxy
 	return servicePort
 }
 
-// computeHosts returns a list of the intersecting hostnames between the route
-// and the listener.
-func computeHosts(routeHostnames []string, listenerHostname *gwapiv1.Hostname) []string {
+// computeHosts returns a list of intersecting listener hostnames and route hostnames
+// that don't intersect with other listener hostnames.
+func computeHosts(routeHostnames []string, listenerContext *ListenerContext) []string {
 	var listenerHostnameVal string
-	if listenerHostname != nil {
-		listenerHostnameVal = string(*listenerHostname)
+	if listenerContext != nil && listenerContext.Hostname != nil {
+		listenerHostnameVal = string(*listenerContext.Hostname)
 	}
 
 	// No route hostnames specified: use the listener hostname if specified,
@@ -280,8 +280,9 @@ func computeHosts(routeHostnames []string, listenerHostname *gwapiv1.Hostname) [
 		return []string{"*"}
 	}
 
-	var hostnames []string
+	hostnamesSet := sets.NewString()
 
+	// Find intersecting hostnames
 	for i := range routeHostnames {
 		routeHostname := routeHostnames[i]
 
@@ -290,28 +291,47 @@ func computeHosts(routeHostnames []string, listenerHostname *gwapiv1.Hostname) [
 		switch {
 		// No listener hostname: use the route hostname.
 		case len(listenerHostnameVal) == 0:
-			hostnames = append(hostnames, routeHostname)
+			hostnamesSet.Insert(routeHostname)
 
 		// Listener hostname matches the route hostname: use it.
 		case listenerHostnameVal == routeHostname:
-			hostnames = append(hostnames, routeHostname)
+			hostnamesSet.Insert(routeHostname)
 
 		// Listener has a wildcard hostname: check if the route hostname matches.
 		case strings.HasPrefix(listenerHostnameVal, "*"):
 			if hostnameMatchesWildcardHostname(routeHostname, listenerHostnameVal) {
-				hostnames = append(hostnames, routeHostname)
+				hostnamesSet.Insert(routeHostname)
 			}
 
 		// Route has a wildcard hostname: check if the listener hostname matches.
 		case strings.HasPrefix(routeHostname, "*"):
 			if hostnameMatchesWildcardHostname(listenerHostnameVal, routeHostname) {
-				hostnames = append(hostnames, listenerHostnameVal)
+				hostnamesSet.Insert(listenerHostnameVal)
 			}
 
 		}
 	}
 
-	return hostnames
+	// Filter out route hostnames that intersect with other listener hostnames
+	var listeners []*ListenerContext
+	if listenerContext != nil && listenerContext.gateway != nil {
+		listeners = listenerContext.gateway.listeners
+	}
+
+	for _, listener := range listeners {
+		if listenerContext == listener {
+			continue
+		}
+		if listenerContext != nil && listenerContext.Port != listener.Port {
+			continue
+		}
+		if listener.Hostname == nil {
+			continue
+		}
+		hostnamesSet.Delete(string(*listener.Hostname))
+	}
+
+	return hostnamesSet.List()
 }
 
 // hostnameMatchesWildcardHostname returns true if hostname has the non-wildcard
diff --git a/internal/gatewayapi/route.go b/internal/gatewayapi/route.go
index 336e931cf..b113411b3 100644
--- a/internal/gatewayapi/route.go
+++ b/internal/gatewayapi/route.go
@@ -651,7 +651,7 @@ func (t *Translator) processHTTPRouteParentRefListener(route RouteContext, route
 	var hasHostnameIntersection bool
 
 	for _, listener := range parentRef.listeners {
-		hosts := computeHosts(GetHostnames(route), listener.Hostname)
+		hosts := computeHosts(GetHostnames(route), listener)
 		if len(hosts) == 0 {
 			continue
 		}
@@ -818,7 +818,7 @@ func (t *Translator) processTLSRouteParentRefs(tlsRoute *TLSRouteContext, resour
 
 		var hasHostnameIntersection bool
 		for _, listener := range parentRef.listeners {
-			hosts := computeHosts(GetHostnames(tlsRoute), listener.Hostname)
+			hosts := computeHosts(GetHostnames(tlsRoute), listener)
 			if len(hosts) == 0 {
 				continue
 			}
diff --git a/internal/gatewayapi/tls.go b/internal/gatewayapi/tls.go
index 1d38897ed..acde9bed3 100644
--- a/internal/gatewayapi/tls.go
+++ b/internal/gatewayapi/tls.go
@@ -88,10 +88,13 @@ func validateTLSSecretsData(secrets []*corev1.Secret, host *gwapiv1.Hostname) er
 func verifyHostname(cert *x509.Certificate, host *gwapiv1.Hostname) ([]string, error) {
 	var matchedHosts []string
 
+	listenerContext := ListenerContext{
+		Listener: &gwapiv1.Listener{Hostname: host},
+	}
 	if len(cert.DNSNames) > 0 {
-		matchedHosts = computeHosts(cert.DNSNames, host)
+		matchedHosts = computeHosts(cert.DNSNames, &listenerContext)
 	} else {
-		matchedHosts = computeHosts([]string{cert.Subject.CommonName}, host)
+		matchedHosts = computeHosts([]string{cert.Subject.CommonName}, &listenerContext)
 	}
 
 	if len(matchedHosts) > 0 {
diff --git a/internal/infrastructure/kubernetes/proxy/resource.go b/internal/infrastructure/kubernetes/proxy/resource.go
index f89491f43..6ff2c7b15 100644
--- a/internal/infrastructure/kubernetes/proxy/resource.go
+++ b/internal/infrastructure/kubernetes/proxy/resource.go
@@ -226,9 +226,9 @@ func expectedProxyContainers(infra *ir.ProxyInfra,
 					},
 				},
 				TimeoutSeconds:   1,
-				PeriodSeconds:    10,
+				PeriodSeconds:    5,
 				SuccessThreshold: 1,
-				FailureThreshold: 3,
+				FailureThreshold: 1,
 			},
 			Lifecycle: &corev1.Lifecycle{
 				PreStop: &corev1.LifecycleHandler{
diff --git a/internal/infrastructure/kubernetes/ratelimit/resource.go b/internal/infrastructure/kubernetes/ratelimit/resource.go
index 9353b0ced..a0c09aef2 100644
--- a/internal/infrastructure/kubernetes/ratelimit/resource.go
+++ b/internal/infrastructure/kubernetes/ratelimit/resource.go
@@ -184,9 +184,9 @@ func expectedRateLimitContainers(rateLimit *egv1a1.RateLimit, rateLimitDeploymen
 					},
 				},
 				TimeoutSeconds:   1,
-				PeriodSeconds:    10,
+				PeriodSeconds:    5,
 				SuccessThreshold: 1,
-				FailureThreshold: 3,
+				FailureThreshold: 1,
 			},
 		},
 	}
@@ -327,7 +327,11 @@ func expectedRateLimitContainerEnv(rateLimit *egv1a1.RateLimit, rateLimitDeploym
 		},
 		{
 			Name:  UseStatsdEnvVar,
-			Value: "false",
+			Value: "true",
+		},
+		{
+			Name:  "STATSD_PORT",
+			Value: "9125",
 		},
 		{
 			Name:  ConfigTypeEnvVar,
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 3d300f1a5..68f164394 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -1178,9 +1178,9 @@ func NewDestEndpoint(host string, port uint32) *DestinationEndpoint {
 // AddHeader configures a header to be added to a request or response.
 // +k8s:deepcopy-gen=true
 type AddHeader struct {
-	Name   string `json:"name" yaml:"name"`
-	Value  string `json:"value" yaml:"value"`
-	Append bool   `json:"append" yaml:"append"`
+	Name   string   `json:"name" yaml:"name"`
+	Value  []string `json:"value" yaml:"value"`
+	Append bool     `json:"append" yaml:"append"`
 }
 
 // Validate the fields within the AddHeader structure
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index 273eeb1c3..3262cf8d7 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -191,6 +191,11 @@ func (in *ActiveHealthCheck) DeepCopy() *ActiveHealthCheck {
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *AddHeader) DeepCopyInto(out *AddHeader) {
 	*out = *in
+	if in.Value != nil {
+		in, out := &in.Value, &out.Value
+		*out = make([]string, len(*in))
+		copy(*out, *in)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddHeader.
@@ -588,7 +593,9 @@ func (in *DestinationFilters) DeepCopyInto(out *DestinationFilters) {
 	if in.AddRequestHeaders != nil {
 		in, out := &in.AddRequestHeaders, &out.AddRequestHeaders
 		*out = make([]AddHeader, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	if in.RemoveRequestHeaders != nil {
 		in, out := &in.RemoveRequestHeaders, &out.RemoveRequestHeaders
@@ -598,7 +605,9 @@ func (in *DestinationFilters) DeepCopyInto(out *DestinationFilters) {
 	if in.AddResponseHeaders != nil {
 		in, out := &in.AddResponseHeaders, &out.AddResponseHeaders
 		*out = make([]AddHeader, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	if in.RemoveResponseHeaders != nil {
 		in, out := &in.RemoveResponseHeaders, &out.RemoveResponseHeaders
@@ -1234,7 +1243,9 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
 	if in.AddRequestHeaders != nil {
 		in, out := &in.AddRequestHeaders, &out.AddRequestHeaders
 		*out = make([]AddHeader, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	if in.RemoveRequestHeaders != nil {
 		in, out := &in.RemoveRequestHeaders, &out.RemoveRequestHeaders
@@ -1244,7 +1255,9 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
 	if in.AddResponseHeaders != nil {
 		in, out := &in.AddResponseHeaders, &out.AddResponseHeaders
 		*out = make([]AddHeader, len(*in))
-		copy(*out, *in)
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
 	}
 	if in.RemoveResponseHeaders != nil {
 		in, out := &in.RemoveResponseHeaders, &out.RemoveResponseHeaders
diff --git a/internal/logging/log.go b/internal/logging/log.go
index a4fb787f9..274f11f05 100644
--- a/internal/logging/log.go
+++ b/internal/logging/log.go
@@ -72,7 +72,7 @@ func (l Logger) WithName(name string) Logger {
 	return Logger{
 		Logger:        zapr.NewLogger(logger).WithName(name),
 		logging:       l.logging,
-		sugaredLogger: logger.Sugar(),
+		sugaredLogger: logger.Sugar().Named(name),
 	}
 }
 
diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go
index f7e88da22..31a54ec71 100644
--- a/internal/provider/kubernetes/controller.go
+++ b/internal/provider/kubernetes/controller.go
@@ -597,7 +597,7 @@ func (r *gatewayAPIReconciler) processSecretRef(
 		types.NamespacedName{Namespace: secretNS, Name: string(secretRef.Name)},
 		secret,
 	)
-	if err != nil && !kerrors.IsNotFound(err) {
+	if err != nil && kerrors.IsNotFound(err) {
 		return fmt.Errorf("unable to find the Secret: %s/%s", secretNS, string(secretRef.Name))
 	}
 
@@ -699,7 +699,7 @@ func (r *gatewayAPIReconciler) processConfigMapRef(
 		types.NamespacedName{Namespace: configMapNS, Name: string(configMapRef.Name)},
 		configMap,
 	)
-	if err != nil && !kerrors.IsNotFound(err) {
+	if err != nil && kerrors.IsNotFound(err) {
 		return fmt.Errorf("unable to find the ConfigMap: %s/%s", configMapNS, string(configMapRef.Name))
 	}
 
@@ -769,13 +769,35 @@ func (r *gatewayAPIReconciler) findReferenceGrant(ctx context.Context, from, to
 	}
 
 	for _, refGrant := range refGrants {
-		if refGrant.Namespace == to.namespace {
-			for _, src := range refGrant.Spec.From {
-				if src.Kind == gwapiv1a2.Kind(from.kind) && string(src.Namespace) == from.namespace {
-					return &refGrant, nil
-				}
+		if refGrant.Namespace != to.namespace {
+			continue
+		}
+
+		var fromAllowed bool
+		for _, refGrantFrom := range refGrant.Spec.From {
+			if string(refGrantFrom.Kind) == from.kind && string(refGrantFrom.Namespace) == from.namespace {
+				fromAllowed = true
+				break
 			}
 		}
+
+		if !fromAllowed {
+			continue
+		}
+
+		var toAllowed bool
+		for _, refGrantTo := range refGrant.Spec.To {
+			if string(refGrantTo.Kind) == to.kind && (refGrantTo.Name == nil || *refGrantTo.Name == "" || string(*refGrantTo.Name) == to.name) {
+				toAllowed = true
+				break
+			}
+		}
+
+		if !toAllowed {
+			continue
+		}
+
+		return &refGrant, nil
 	}
 
 	// No ReferenceGrant found.
diff --git a/internal/xds/translator/route.go b/internal/xds/translator/route.go
index 2b9c75a2e..6a9e72f49 100644
--- a/internal/xds/translator/route.go
+++ b/internal/xds/translator/route.go
@@ -401,7 +401,10 @@ func buildXdsURLRewriteAction(destName string, urlRewrite *ir.URLRewrite, pathMa
 			if useRegexRewriteForPrefixMatchReplace(pathMatch, *urlRewrite.Path.PrefixMatchReplace) {
 				routeAction.RegexRewrite = prefix2RegexRewrite(*pathMatch.Prefix)
 			} else {
-				routeAction.PrefixRewrite = *urlRewrite.Path.PrefixMatchReplace
+				// remove trailing / to fix #3989
+				// when the pathMath.Prefix has suffix / but EG has removed it,
+				// and the urlRewrite.Path.PrefixMatchReplace suffix with / the upstream will get unwanted /
+				routeAction.PrefixRewrite = strings.TrimSuffix(*urlRewrite.Path.PrefixMatchReplace, "/")
 			}
 		}
 	}
@@ -435,9 +438,9 @@ func buildXdsRequestMirrorPolicies(mirrorDestinations []*ir.RouteDestination) []
 }
 
 func buildXdsAddedHeaders(headersToAdd []ir.AddHeader) []*corev3.HeaderValueOption {
-	headerValueOptions := make([]*corev3.HeaderValueOption, len(headersToAdd))
+	headerValueOptions := []*corev3.HeaderValueOption{}
 
-	for i, header := range headersToAdd {
+	for _, header := range headersToAdd {
 		var appendAction corev3.HeaderValueOption_HeaderAppendAction
 
 		if header.Append {
@@ -445,18 +448,26 @@ func buildXdsAddedHeaders(headersToAdd []ir.AddHeader) []*corev3.HeaderValueOpti
 		} else {
 			appendAction = corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD
 		}
-
-		headerValueOptions[i] = &corev3.HeaderValueOption{
-			Header: &corev3.HeaderValue{
-				Key:   header.Name,
-				Value: header.Value,
-			},
-			AppendAction: appendAction,
-		}
-
 		// Allow empty headers to be set, but don't add the config to do so unless necessary
-		if header.Value == "" {
-			headerValueOptions[i].KeepEmptyValue = true
+		if len(header.Value) == 0 {
+			headerValueOptions = append(headerValueOptions, &corev3.HeaderValueOption{
+				Header: &corev3.HeaderValue{
+					Key: header.Name,
+				},
+				AppendAction:   appendAction,
+				KeepEmptyValue: true,
+			})
+		} else {
+			for _, val := range header.Value {
+				headerValueOptions = append(headerValueOptions, &corev3.HeaderValueOption{
+					Header: &corev3.HeaderValue{
+						Key:   header.Name,
+						Value: val,
+					},
+					AppendAction:   appendAction,
+					KeepEmptyValue: val == "",
+				})
+			}
 		}
 	}
 
diff --git a/site/go.mod b/site/go.mod
index 29d91dd00..c6b0df811 100644
--- a/site/go.mod
+++ b/site/go.mod
@@ -1,6 +1,6 @@
 module github.com/google/docsy-example
 
-go 1.22.5
+go 1.22.7
 
 require (
 	github.com/FortAwesome/Font-Awesome v0.0.0-20240402185447-c0f460dca7f7 // indirect
diff --git a/tools/src/buf/go.mod b/tools/src/buf/go.mod
index d2d02735a..a97763b29 100644
--- a/tools/src/buf/go.mod
+++ b/tools/src/buf/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require github.com/bufbuild/buf v1.34.0
 
diff --git a/tools/src/controller-gen/go.mod b/tools/src/controller-gen/go.mod
index 3b5da982d..e1eab3409 100644
--- a/tools/src/controller-gen/go.mod
+++ b/tools/src/controller-gen/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require sigs.k8s.io/controller-tools v0.15.0
 
diff --git a/tools/src/crd-ref-docs/go.mod b/tools/src/crd-ref-docs/go.mod
index e6ce178a9..c3f94ef1e 100644
--- a/tools/src/crd-ref-docs/go.mod
+++ b/tools/src/crd-ref-docs/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require github.com/elastic/crd-ref-docs v0.0.13-0.20240413123740-ea9fcaa0230f
 
diff --git a/tools/src/gci/go.mod b/tools/src/gci/go.mod
index dfb21a706..7d4fd7ca6 100644
--- a/tools/src/gci/go.mod
+++ b/tools/src/gci/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require github.com/daixiang0/gci v0.13.4
 
diff --git a/tools/src/golangci-lint/go.mod b/tools/src/golangci-lint/go.mod
index 9442b7aa8..4b92c196c 100644
--- a/tools/src/golangci-lint/go.mod
+++ b/tools/src/golangci-lint/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require github.com/golangci/golangci-lint v1.59.1
 
diff --git a/tools/src/helm-docs/go.mod b/tools/src/helm-docs/go.mod
index f90603ca8..84484217b 100644
--- a/tools/src/helm-docs/go.mod
+++ b/tools/src/helm-docs/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/helm-docs
 
-go 1.22.5
+go 1.22.7
 
 require github.com/norwoodj/helm-docs v1.14.2
 
diff --git a/tools/src/jb/go.mod b/tools/src/jb/go.mod
index f781b6f98..4b500d8ac 100644
--- a/tools/src/jb/go.mod
+++ b/tools/src/jb/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/jb
 
-go 1.22.5
+go 1.22.7
 
 require github.com/jsonnet-bundler/jsonnet-bundler v0.5.1
 
diff --git a/tools/src/jsonnet/go.mod b/tools/src/jsonnet/go.mod
index 2abb02009..27537f282 100644
--- a/tools/src/jsonnet/go.mod
+++ b/tools/src/jsonnet/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/jsonnet
 
-go 1.22.5
+go 1.22.7
 
 require github.com/google/go-jsonnet v0.20.0
 
diff --git a/tools/src/kind/go.mod b/tools/src/kind/go.mod
index ee24990f4..91c367c59 100644
--- a/tools/src/kind/go.mod
+++ b/tools/src/kind/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/kind
 
-go 1.22.5
+go 1.22.7
 
 require sigs.k8s.io/kind v0.23.0
 
diff --git a/tools/src/protoc-gen-go-grpc/go.mod b/tools/src/protoc-gen-go-grpc/go.mod
index f55603269..1e73e1c52 100644
--- a/tools/src/protoc-gen-go-grpc/go.mod
+++ b/tools/src/protoc-gen-go-grpc/go.mod
@@ -1,6 +1,6 @@
 module github.com/envoyproxy/gateway/tools/src/protoc-gen-go-grpc
 
-go 1.22.5
+go 1.22.7
 
 require google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0
 
diff --git a/tools/src/protoc-gen-go/go.mod b/tools/src/protoc-gen-go/go.mod
index 8f65aeda6..e24ee0529 100644
--- a/tools/src/protoc-gen-go/go.mod
+++ b/tools/src/protoc-gen-go/go.mod
@@ -1,5 +1,5 @@
 module github.com/envoyproxy/gateway/tools/src/protoc-gen-go
 
-go 1.22.5
+go 1.22.7
 
 require google.golang.org/protobuf v1.33.0


Test patch:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml
index 5cb832646..35f54fe3d 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.in.yaml
@@ -100,6 +100,25 @@ httpRoutes:
       backendRefs:
       - name: service-3
         port: 8080
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-4
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-2
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/v2"
+      backendRefs:
+      - name: service-2
+        port: 8080
 backendTrafficPolicies:
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
@@ -169,6 +188,29 @@ backendTrafficPolicies:
         consecutiveGatewayErrors: 0
         consecutiveLocalOriginFailures: 5
         splitExternalLocalOriginErrors: false
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route-4
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-4
+    healthCheck:
+      active:
+        timeout: "1s"
+        interval: "5s"
+        unhealthyThreshold: 3
+        healthyThreshold: 3
+        type: HTTP
+        http:
+          path: "/healthz"
+          method: "GET"
+          expectedResponse:
+            type: Text
+            text: pong
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
   metadata:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml
index 447a7df48..ef22b8bc0 100644
--- a/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-healthcheck.out.yaml
@@ -49,6 +49,45 @@ backendTrafficPolicies:
         status: "True"
         type: Accepted
       controllerName: gateway.envoyproxy.io/gatewayclass-controller
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-route-4
+    namespace: default
+  spec:
+    healthCheck:
+      active:
+        healthyThreshold: 3
+        http:
+          expectedResponse:
+            text: pong
+            type: Text
+          method: GET
+          path: /healthz
+        interval: 5s
+        timeout: 1s
+        type: HTTP
+        unhealthyThreshold: 3
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-4
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-2
+        namespace: envoy-gateway
+        sectionName: http
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
 - apiVersion: gateway.envoyproxy.io/v1alpha1
   kind: BackendTrafficPolicy
   metadata:
@@ -252,7 +291,7 @@ gateways:
       protocol: HTTP
   status:
     listeners:
-    - attachedRoutes: 3
+    - attachedRoutes: 4
       conditions:
       - lastTransitionTime: null
         message: Sending translated listener configuration to the data plane
@@ -424,6 +463,44 @@ httpRoutes:
         name: gateway-2
         namespace: envoy-gateway
         sectionName: http
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-4
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-2
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-2
+        port: 8080
+      matches:
+      - path:
+          value: /v2
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Resolved all the Object references for the Route
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-2
+        namespace: envoy-gateway
+        sectionName: http
 infraIR:
   envoy-gateway/gateway-1:
     proxy:
@@ -616,6 +693,41 @@ xdsIR:
               interval: 8ms
               maxEjectionPercent: 11
               splitExternalLocalOriginErrors: false
+      - destination:
+          name: httproute/default/httproute-4/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-4
+          namespace: default
+        name: httproute/default/httproute-4/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /v2
+        traffic:
+          healthCheck:
+            active:
+              healthyThreshold: 3
+              http:
+                expectedResponse:
+                  text: pong
+                expectedStatuses:
+                - 200
+                host: gateway.envoyproxy.io
+                method: GET
+                path: /healthz
+              interval: 5s
+              timeout: 1s
+              unhealthyThreshold: 3
       - destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.in.yaml b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.in.yaml
new file mode 100644
index 000000000..267fcbba5
--- /dev/null
+++ b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.in.yaml
@@ -0,0 +1,65 @@
+gateways:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: Gateway
+    metadata:
+      name: gateway-1
+      namespace: envoy-gateway
+    spec:
+      gatewayClassName: envoy-gateway-class
+      listeners:
+        - name: empty-hostname
+          port: 80
+          protocol: HTTP
+          allowedRoutes:
+            namespaces:
+              from: All
+        - name: wildcard-example-com
+          port: 80
+          protocol: HTTP
+          hostname: "*.example.com"
+          allowedRoutes:
+            namespaces:
+              from: All
+httpRoutes:
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      name: httproute-1
+      namespace: envoy-gateway
+    spec:
+      parentRefs:
+        - name: gateway-1
+          namespace: envoy-gateway
+          sectionName: empty-hostname
+      hostnames:
+        - "bar.com"
+        - "*.example.com" # request matching is prevented by the isolation wildcard-example-com listener
+      rules:
+        - matches:
+            - path:
+                type: PathPrefix
+                value: /empty-hostname
+          backendRefs:
+            - name: service-1
+              port: 8080
+  - apiVersion: gateway.networking.k8s.io/v1
+    kind: HTTPRoute
+    metadata:
+      name: httproute-2
+      namespace: envoy-gateway
+    spec:
+      parentRefs:
+        - name: gateway-1
+          namespace: envoy-gateway
+          sectionName: wildcard-example-com
+      hostnames:
+        - "bar.com" # doesn't match wildcard-example-com listener
+        - "*.example.com"
+      rules:
+        - matches:
+            - path:
+                type: PathPrefix
+                value: /wildcard-example-com
+          backendRefs:
+            - name: service-1
+              port: 8080
diff --git a/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml
new file mode 100644
index 000000000..cb47542a1
--- /dev/null
+++ b/internal/gatewayapi/testdata/gateway-http-listener-with-hostname-intersection.out.yaml
@@ -0,0 +1,238 @@
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-1
+    namespace: envoy-gateway
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: All
+      name: empty-hostname
+      port: 80
+      protocol: HTTP
+    - allowedRoutes:
+        namespaces:
+          from: All
+      hostname: '*.example.com'
+      name: wildcard-example-com
+      port: 80
+      protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 1
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: empty-hostname
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+    - attachedRoutes: 1
+      conditions:
+      - lastTransitionTime: null
+        message: Sending translated listener configuration to the data plane
+        reason: Programmed
+        status: "True"
+        type: Programmed
+      - lastTransitionTime: null
+        message: Listener has been successfully translated
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Listener references have been resolved
+        reason: ResolvedRefs
+        status: "True"
+        type: ResolvedRefs
+      name: wildcard-example-com
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-1
+    namespace: envoy-gateway
+  spec:
+    hostnames:
+    - bar.com
+    - '*.example.com'
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: empty-hostname
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          type: PathPrefix
+          value: /empty-hostname
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Service envoy-gateway/service-1 not found
+        reason: BackendNotFound
+        status: "False"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: empty-hostname
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-2
+    namespace: envoy-gateway
+  spec:
+    hostnames:
+    - bar.com
+    - '*.example.com'
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: wildcard-example-com
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          type: PathPrefix
+          value: /wildcard-example-com
+  status:
+    parents:
+    - conditions:
+      - lastTransitionTime: null
+        message: Route is accepted
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      - lastTransitionTime: null
+        message: Service envoy-gateway/service-1 not found
+        reason: BackendNotFound
+        status: "False"
+        type: ResolvedRefs
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+      parentRef:
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: wildcard-example-com
+infraIR:
+  envoy-gateway/gateway-1:
+    proxy:
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-1/empty-hostname
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-1
+          gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+      name: envoy-gateway/gateway-1
+xdsIR:
+  envoy-gateway/gateway-1:
+    accessLog:
+      text:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: empty-hostname
+      name: envoy-gateway/gateway-1/empty-hostname
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          name: httproute/envoy-gateway/httproute-1/rule/0
+          settings:
+          - weight: 1
+        directResponse:
+          statusCode: 500
+        hostname: bar.com
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-1
+          namespace: envoy-gateway
+        name: httproute/envoy-gateway/httproute-1/rule/0/match/0/bar_com
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /empty-hostname
+    - address: 0.0.0.0
+      hostnames:
+      - '*.example.com'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+        sectionName: wildcard-example-com
+      name: envoy-gateway/gateway-1/wildcard-example-com
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          name: httproute/envoy-gateway/httproute-2/rule/0
+          settings:
+          - weight: 1
+        directResponse:
+          statusCode: 500
+        hostname: '*.example.com'
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-2
+          namespace: envoy-gateway
+        name: httproute/envoy-gateway/httproute-2/rule/0/match/0/*_example_com
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /wildcard-example-com
diff --git a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml
index 2c48dad58..29fcb5a75 100644
--- a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml
+++ b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.in.yaml
@@ -26,6 +26,11 @@ grpcRoutes:
       sectionName: http
     rules:
     - filters:
+      - type: "RequestHeaderModifier"
+        requestHeaderModifier:
+          add:
+          - name: "my-header-multi-value"
+            value: "foo,bar"
       - type: "RequestHeaderModifier"
         requestHeaderModifier:
           add:
diff --git a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml
index f36c9c969..110d404c4 100644
--- a/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml
+++ b/internal/gatewayapi/testdata/grpcroute-with-request-header-modifier.out.yaml
@@ -56,6 +56,11 @@ grpcRoutes:
       - name: service-1
         port: 8080
       filters:
+      - requestHeaderModifier:
+          add:
+          - name: my-header-multi-value
+            value: foo,bar
+        type: RequestHeaderModifier
       - requestHeaderModifier:
           add:
           - name: my-header
@@ -117,9 +122,15 @@ xdsIR:
       port: 10080
       routes:
       - addRequestHeaders:
+        - append: true
+          name: my-header-multi-value
+          value:
+          - foo
+          - bar
         - append: true
           name: my-header
-          value: foo
+          value:
+          - foo
         destination:
           name: grpcroute/default/grpcroute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml
index 78655fc84..122d09efd 100644
--- a/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-backendref-add-multiple-filters.out.yaml
@@ -147,7 +147,8 @@ xdsIR:
               addRequestHeaders:
               - append: false
                 name: add-header-3
-                value: some-value
+                value:
+                - some-value
             protocol: HTTP
             weight: 1
         hostname: '*'
@@ -172,10 +173,12 @@ xdsIR:
               addRequestHeaders:
               - append: true
                 name: add-header-1
-                value: some-value
+                value:
+                - some-value
               - append: true
                 name: add-header-2
-                value: some-value
+                value:
+                - some-value
             protocol: HTTP
             weight: 8
           - addressType: IP
diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml
index a86e71b45..605aa384f 100644
--- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-add-multiple-filters.out.yaml
@@ -134,13 +134,16 @@ xdsIR:
       - addRequestHeaders:
         - append: true
           name: add-header-1
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: add-header-2
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: add-header-3
-          value: some-value
+          value:
+          - some-value
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml
index 39cc44429..f122fc17d 100644
--- a/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-header-filter-duplicate-adds.out.yaml
@@ -144,19 +144,24 @@ xdsIR:
       - addRequestHeaders:
         - append: true
           name: Set-Header-1
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-2
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-3
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-5
-          value: some-value
+          value:
+          - some-value
         - append: false
           name: set-header-4
-          value: some-value
+          value:
+          - some-value
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml
index b3814e2d4..67c14e133 100644
--- a/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-header-filter-empty-header-values.out.yaml
@@ -128,10 +128,12 @@ xdsIR:
       - addRequestHeaders:
         - append: true
           name: example-header-2
-          value: ""
+          value:
+          - ""
         - append: false
           name: example-header-1
-          value: ""
+          value:
+          - ""
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml
index 9aa6f0bf2..c6e534c9c 100644
--- a/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-mirror-filter-multiple.out.yaml
@@ -144,13 +144,16 @@ xdsIR:
       - addRequestHeaders:
         - append: true
           name: X-Header-Add
-          value: header-val-1
+          value:
+          - header-val-1
         - append: true
           name: X-Header-Add-Append
-          value: header-val-2
+          value:
+          - header-val-2
         - append: false
           name: X-Header-Set
-          value: set-overwrites-values
+          value:
+          - set-overwrites-values
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml
index 7b53542bd..6dcb4b287 100644
--- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-adds.out.yaml
@@ -140,19 +140,24 @@ xdsIR:
       - addResponseHeaders:
         - append: true
           name: Set-Header-1
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-2
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-3
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-5
-          value: some-value
+          value:
+          - some-value
         - append: false
           name: set-header-4
-          value: some-value
+          value:
+          - some-value
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml
index 459c42647..47d61c9fc 100644
--- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-add-multiple-filters.out.yaml
@@ -134,13 +134,16 @@ xdsIR:
       - addResponseHeaders:
         - append: true
           name: add-header-1
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: add-header-2
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: add-header-3
-          value: some-value
+          value:
+          - some-value
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml
index d2b4ffbe3..1d2f4f712 100644
--- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-duplicate-adds.out.yaml
@@ -144,19 +144,24 @@ xdsIR:
       - addResponseHeaders:
         - append: true
           name: Set-Header-1
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-2
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-3
-          value: some-value
+          value:
+          - some-value
         - append: true
           name: set-header-5
-          value: some-value
+          value:
+          - some-value
         - append: false
           name: set-header-4
-          value: some-value
+          value:
+          - some-value
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml
index 9d188a03d..723cabbe6 100644
--- a/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml
+++ b/internal/gatewayapi/testdata/httproute-with-response-header-filter-empty-header-values.out.yaml
@@ -128,10 +128,12 @@ xdsIR:
       - addResponseHeaders:
         - append: true
           name: example-header-2
-          value: ""
+          value:
+          - ""
         - append: false
           name: example-header-1
-          value: ""
+          value:
+          - ""
         destination:
           name: httproute/default/httproute-1/rule/0
           settings:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml
index 9065d07a5..7d6204be1 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/component-level.yaml
@@ -74,12 +74,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml
index fc524284f..14e8aca43 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/custom.yaml
@@ -258,12 +258,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml
index fbeddc169..0800a0a2a 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default-env.yaml
@@ -256,12 +256,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml
index 80cf7c12e..b8f895a11 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/default.yaml
@@ -241,12 +241,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml
index 81dda722f..803ef132d 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/disable-prometheus.yaml
@@ -212,12 +212,12 @@ spec:
           name: EnvoyHTTPSPort
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml
index 314e8bcea..8113f680b 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/extension-env.yaml
@@ -260,12 +260,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml
index 9ce0aa5a0..45a2000cb 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/override-labels-and-annotations.yaml
@@ -252,12 +252,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml
index 518f239a5..e752b1eb4 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/patch-daemonset.yaml
@@ -241,12 +241,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml
index 506a2824f..12cbeed20 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/shutdown-manager.yaml
@@ -242,12 +242,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml
index fc59ec673..5d35aacf5 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/volumes.yaml
@@ -260,12 +260,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml
index c19e55794..154049686 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-annotations.yaml
@@ -246,12 +246,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml
index f941541e7..ffe4bfe4b 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-concurrency.yaml
@@ -74,12 +74,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml
index 1d5c3c415..7d90fe750 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-extra-args.yaml
@@ -243,12 +243,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml
index f23530344..0287eadbc 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-image-pull-secrets.yaml
@@ -241,12 +241,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
index a7e467f7a..e4343479f 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-name.yaml
@@ -241,12 +241,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml
index bacf71180..1dacf4db5 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-node-selector.yaml
@@ -241,12 +241,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml
index 552012f77..61764b6a1 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/daemonsets/with-topology-spread-constraints.yaml
@@ -241,12 +241,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml
index e6574edec..26154b19b 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/bootstrap.yaml
@@ -77,12 +77,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml
index 19cd5ebb2..872d09449 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/component-level.yaml
@@ -78,12 +78,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml
index 0434fb4ca..919956eeb 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom.yaml
@@ -263,12 +263,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml
index 89c928708..437daee02 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/custom_with_initcontainers.yaml
@@ -263,12 +263,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml
index c5e2d4ce3..879d611ed 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default-env.yaml
@@ -261,12 +261,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml
index c5c17adaa..f022d0f8e 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/default.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml
index acaad907b..8a3094fdd 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/disable-prometheus.yaml
@@ -216,12 +216,12 @@ spec:
           name: EnvoyHTTPSPort
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml
index 4ff157e8c..3103d6175 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/extension-env.yaml
@@ -265,12 +265,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml
index bfaf6686d..992b63441 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/override-labels-and-annotations.yaml
@@ -256,12 +256,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml
index 2c4e97641..3095f5fb3 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/patch-deployment.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml
index c4c7be51f..f8c2ff795 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/shutdown-manager.yaml
@@ -246,12 +246,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml
index ea54e6252..697161e3f 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/volumes.yaml
@@ -265,12 +265,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml
index 819d66a8f..5d77a2414 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-annotations.yaml
@@ -250,12 +250,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml
index cc626d7eb..c13f44a1c 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-concurrency.yaml
@@ -78,12 +78,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml
index c20a70d36..1f2fca138 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-empty-memory-limits.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml
index f5fcb2bd8..86147f1fd 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-extra-args.yaml
@@ -247,12 +247,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml
index ebfa5b5fc..8be98c210 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-image-pull-secrets.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
index 1797b157e..19efd6b47 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-name.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml
index 13f8d10c7..b3568a146 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-node-selector.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml
index 7d2fa77e4..c1a81992c 100644
--- a/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml
+++ b/internal/infrastructure/kubernetes/proxy/testdata/deployments/with-topology-spread-constraints.yaml
@@ -245,12 +245,12 @@ spec:
           name: metrics
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /ready
             port: 19001
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml
index bfd2c28cc..8ce3ed3e7 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/custom.yaml
@@ -50,7 +50,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -87,12 +89,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml
index bfd2c28cc..8ce3ed3e7 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default-env.yaml
@@ -50,7 +50,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -87,12 +89,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml
index 17536708a..80c2be451 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/default.yaml
@@ -51,7 +51,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -88,12 +90,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml
index cc2011152..f145d7199 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/disable-prometheus.yaml
@@ -47,7 +47,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -84,12 +86,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml
index fa8916ed8..fd50e02d0 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing-custom.yaml
@@ -51,7 +51,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -103,12 +105,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml
index 9b364f887..052015be0 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/enable-tracing.yaml
@@ -51,7 +51,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -103,12 +105,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml
index 95516ce6c..954c9f5eb 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/extension-env.yaml
@@ -50,7 +50,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -91,12 +93,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml
index 8a9cfb60c..8ce3ed3e7 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/override-env.yaml
@@ -51,6 +51,8 @@ spec:
           value: info
         - name: USE_STATSD
           value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -87,12 +89,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml
index 7e0f600c0..78ce0a2aa 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/patch-deployment.yaml
@@ -51,7 +51,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -88,12 +90,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml
index 9854f37f4..7a8cc10e8 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/redis-tls-settings.yaml
@@ -51,6 +51,8 @@ spec:
           value: info
         - name: USE_STATSD
           value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -95,12 +97,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml
index 56fdb156d..d34ee5a9e 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/tolerations.yaml
@@ -51,6 +51,8 @@ spec:
           value: info
         - name: USE_STATSD
           value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -95,12 +97,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml
index 01e779e9e..78b9d1d83 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/volumes.yaml
@@ -51,6 +51,8 @@ spec:
           value: info
         - name: USE_STATSD
           value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -95,12 +97,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml
index e6105d591..fbd7c3af0 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-node-selector.yaml
@@ -51,7 +51,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -88,12 +90,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml
index d5c9a6d74..e3cae44e0 100644
--- a/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml
+++ b/internal/infrastructure/kubernetes/ratelimit/testdata/deployments/with-topology-spread-constraints.yaml
@@ -51,7 +51,9 @@ spec:
         - name: LOG_LEVEL
           value: info
         - name: USE_STATSD
-          value: "false"
+          value: "true"
+        - name: STATSD_PORT
+          value: "9125"
         - name: CONFIG_TYPE
           value: GRPC_XDS_SOTW
         - name: CONFIG_GRPC_XDS_SERVER_URL
@@ -88,12 +90,12 @@ spec:
           name: grpc
           protocol: TCP
         readinessProbe:
-          failureThreshold: 3
+          failureThreshold: 1
           httpGet:
             path: /healthcheck
             port: 8080
             scheme: HTTP
-          periodSeconds: 10
+          periodSeconds: 5
           successThreshold: 1
           timeoutSeconds: 1
         resources:
diff --git a/internal/ir/xds_test.go b/internal/ir/xds_test.go
index 9492c3783..6724549e3 100644
--- a/internal/ir/xds_test.go
+++ b/internal/ir/xds_test.go
@@ -338,17 +338,16 @@ var (
 		AddRequestHeaders: []AddHeader{
 			{
 				Name:   "example-header",
-				Value:  "example-value",
+				Value:  []string{"example-value"},
 				Append: true,
 			},
 			{
 				Name:   "example-header-2",
-				Value:  "example-value-2",
+				Value:  []string{"example-value-2"},
 				Append: false,
 			},
 			{
 				Name:   "empty-header",
-				Value:  "",
 				Append: false,
 			},
 		},
@@ -376,12 +375,12 @@ var (
 		AddRequestHeaders: []AddHeader{
 			{
 				Name:   "example-header",
-				Value:  "example-value",
+				Value:  []string{"example-value"},
 				Append: true,
 			},
 			{
 				Name:   "example-header",
-				Value:  "example-value-2",
+				Value:  []string{"example-value-2"},
 				Append: false,
 			},
 		},
@@ -401,7 +400,7 @@ var (
 		AddRequestHeaders: []AddHeader{
 			{
 				Name:   "",
-				Value:  "example-value",
+				Value:  []string{"example-value"},
 				Append: true,
 			},
 		},
@@ -416,17 +415,16 @@ var (
 		AddResponseHeaders: []AddHeader{
 			{
 				Name:   "example-header",
-				Value:  "example-value",
+				Value:  []string{"example-value"},
 				Append: true,
 			},
 			{
 				Name:   "example-header-2",
-				Value:  "example-value-2",
+				Value:  []string{"example-value-2"},
 				Append: false,
 			},
 			{
 				Name:   "empty-header",
-				Value:  "",
 				Append: false,
 			},
 		},
@@ -454,12 +452,12 @@ var (
 		AddResponseHeaders: []AddHeader{
 			{
 				Name:   "example-header",
-				Value:  "example-value",
+				Value:  []string{"example-value"},
 				Append: true,
 			},
 			{
 				Name:   "example-header",
-				Value:  "example-value-2",
+				Value:  []string{"example-value-2"},
 				Append: false,
 			},
 		},
@@ -479,7 +477,7 @@ var (
 		AddResponseHeaders: []AddHeader{
 			{
 				Name:   "",
-				Value:  "example-value",
+				Value:  []string{"example-value"},
 				Append: true,
 			},
 		},
diff --git a/internal/logging/log_test.go b/internal/logging/log_test.go
index 999f92275..0942910f7 100644
--- a/internal/logging/log_test.go
+++ b/internal/logging/log_test.go
@@ -75,3 +75,32 @@ func TestLoggerWithName(t *testing.T) {
 	assert.Contains(t, capturedOutput, "info message")
 	assert.Contains(t, capturedOutput, "debug message")
 }
+
+func TestLoggerSugarName(t *testing.T) {
+	originalStdout := os.Stdout
+	r, w, _ := os.Pipe()
+	os.Stdout = w
+
+	defer func() {
+		// Restore the original stdout and close the pipe
+		os.Stdout = originalStdout
+		err := w.Close()
+		require.NoError(t, err)
+	}()
+
+	const logName = "loggerName"
+
+	config := egv1a1.DefaultEnvoyGatewayLogging()
+	config.Level[logName] = egv1a1.LogLevelDebug
+
+	logger := NewLogger(config).WithName(logName)
+
+	logger.Sugar().Debugf("debugging message")
+
+	// Read from the pipe (captured stdout)
+	outputBytes := make([]byte, 200)
+	_, err := r.Read(outputBytes)
+	require.NoError(t, err)
+	capturedOutput := string(outputBytes)
+	assert.Contains(t, capturedOutput, "debugging message", logName)
+}
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml
index c3dc4417d..fb45b8db7 100644
--- a/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-request-headers.yaml
@@ -18,20 +18,30 @@ http:
         - host: "1.2.3.4"
           port: 50000
     addRequestHeaders:
+    - name: "some-header-multi-value"
+      value:
+      - "some-value"
+      - "some-additional-value"
+      append: true
     - name: "some-header"
-      value: "some-value"
+      value:
+      - "some-value"
       append: true
     - name: "some-header-2"
-      value: "some-value"
+      value:
+      - "some-value"
       append: true
     - name: "some-header3"
-      value: "some-value"
+      value:
+      - "some-value"
       append: false
     - name: "some-header4"
-      value: "some-value"
+      value:
+      - "some-value"
       append: false
     - name: "empty-header"
-      value: ""
+      value:
+      - ""
       append: false
     removeRequestHeaders:
     - "some-header5"
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml
index e3114e2d2..3cfaf5e49 100644
--- a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-headers.yaml
@@ -19,17 +19,22 @@ http:
           port: 50000
     addResponseHeaders:
     - name: "some-header"
-      value: "some-value"
+      value:
+      - "some-value"
       append: true
     - name: "some-header-2"
-      value: "some-value"
+      value:
+      - "some-value"
       append: true
     - name: "some-header3"
-      value: "some-value"
+      value:
+      - "some-value"
       append: false
     - name: "some-header4"
-      value: "some-value"
+      value:
+      - "some-value"
       append: false
     - name: "empty-header"
-      value: ""
+      value:
+      - ""
       append: false
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml
index 0e59f8f12..c97d927df 100644
--- a/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-response-add-remove-headers.yaml
@@ -19,19 +19,24 @@ http:
           port: 50000
     addResponseHeaders:
     - name: "some-header"
-      value: "some-value"
+      value:
+      - "some-value"
       append: true
     - name: "some-header-2"
-      value: "some-value"
+      value:
+      - "some-value"
       append: true
     - name: "some-header3"
-      value: "some-value"
+      value:
+      - "some-value"
       append: false
     - name: "some-header4"
-      value: "some-value"
+      value:
+      - "some-value"
       append: false
     - name: "empty-header"
-      value: ""
+      value:
+      - ""
       append: false
     removeResponseHeaders:
     - "some-header5"
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.yaml
new file mode 100644
index 000000000..97d0b5457
--- /dev/null
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.yaml
@@ -0,0 +1,27 @@
+name: "http-route"
+http:
+- name: "first-listener"
+  address: "0.0.0.0"
+  port: 10080
+  hostnames:
+  - "*"
+  path:
+    mergeSlashes: true
+    escapedSlashesAction: UnescapeAndRedirect
+  routes:
+  - name: "rewrite-route"
+    pathMatch:
+      prefix: "/origin/"
+    hostname: gateway.envoyproxy.io
+    headerMatches:
+    - name: ":authority"
+      exact: gateway.envoyproxy.io
+    destination:
+      name: "rewrite-route-dest"
+      settings:
+      - endpoints:
+        - host: "1.2.3.4"
+          port: 50000
+    urlRewrite:
+      path:
+        prefixMatchReplace: /rewrite/
diff --git a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml
index f8943d07f..8745e9893 100644
--- a/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml
+++ b/internal/xds/translator/testdata/in/xds-ir/http-route-weighted-backend-with-filters.yaml
@@ -19,7 +19,8 @@ http:
                 addRequestHeaders:
                   - append: false
                     name: add-header-3
-                    value: some-value
+                    value:
+                      - some-value
               protocol: HTTP
               weight: 1
         hostname: '*'
@@ -37,10 +38,12 @@ http:
                 addRequestHeaders:
                   - append: true
                     name: add-header-1
-                    value: some-value
+                    value:
+                      - some-value
                   - append: true
                     name: add-header-2
-                    value: some-value
+                    value:
+                      - some-value
               protocol: HTTP
               weight: 8
             - addressType: IP
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml
index f91a70cb2..1f2c6be40 100644
--- a/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-request-headers.routes.yaml
@@ -9,6 +9,12 @@
         prefix: /
       name: request-header-route
       requestHeadersToAdd:
+      - header:
+          key: some-header-multi-value
+          value: some-value
+      - header:
+          key: some-header-multi-value
+          value: some-additional-value
       - header:
           key: some-header
           value: some-value
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.clusters.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.clusters.yaml
new file mode 100644
index 000000000..027db39fb
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.clusters.yaml
@@ -0,0 +1,17 @@
+- circuitBreakers:
+    thresholds:
+    - maxRetries: 1024
+  commonLbConfig:
+    localityWeightedLbConfig: {}
+  connectTimeout: 10s
+  dnsLookupFamily: V4_ONLY
+  edsClusterConfig:
+    edsConfig:
+      ads: {}
+      resourceApiVersion: V3
+    serviceName: rewrite-route-dest
+  lbPolicy: LEAST_REQUEST
+  name: rewrite-route-dest
+  outlierDetection: {}
+  perConnectionBufferLimitBytes: 32768
+  type: EDS
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.endpoints.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.endpoints.yaml
new file mode 100644
index 000000000..256dda090
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.endpoints.yaml
@@ -0,0 +1,12 @@
+- clusterName: rewrite-route-dest
+  endpoints:
+  - lbEndpoints:
+    - endpoint:
+        address:
+          socketAddress:
+            address: 1.2.3.4
+            portValue: 50000
+      loadBalancingWeight: 1
+    loadBalancingWeight: 1
+    locality:
+      region: rewrite-route-dest/backend/0
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.listeners.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.listeners.yaml
new file mode 100644
index 000000000..67922c744
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.listeners.yaml
@@ -0,0 +1,35 @@
+- address:
+    socketAddress:
+      address: 0.0.0.0
+      portValue: 10080
+  defaultFilterChain:
+    filters:
+    - name: envoy.filters.network.http_connection_manager
+      typedConfig:
+        '@type': type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
+        commonHttpProtocolOptions:
+          headersWithUnderscoresAction: REJECT_REQUEST
+        http2ProtocolOptions:
+          initialConnectionWindowSize: 1048576
+          initialStreamWindowSize: 65536
+          maxConcurrentStreams: 100
+        httpFilters:
+        - name: envoy.filters.http.router
+          typedConfig:
+            '@type': type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
+            suppressEnvoyHeaders: true
+        mergeSlashes: true
+        normalizePath: true
+        pathWithEscapedSlashesAction: UNESCAPE_AND_REDIRECT
+        rds:
+          configSource:
+            ads: {}
+            resourceApiVersion: V3
+          routeConfigName: first-listener
+        serverHeaderTransformation: PASS_THROUGH
+        statPrefix: http
+        useRemoteAddress: true
+    name: first-listener
+  drainType: MODIFY_ONLY
+  name: first-listener
+  perConnectionBufferLimitBytes: 32768
diff --git a/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.routes.yaml b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.routes.yaml
new file mode 100644
index 000000000..84bc70f04
--- /dev/null
+++ b/internal/xds/translator/testdata/out/xds-ir/http-route-rewrite-sufixx-with-slash-url-prefix.routes.yaml
@@ -0,0 +1,19 @@
+- ignorePortInHostMatching: true
+  name: first-listener
+  virtualHosts:
+  - domains:
+    - gateway.envoyproxy.io
+    name: first-listener/gateway_envoyproxy_io
+    routes:
+    - match:
+        headers:
+        - name: :authority
+          stringMatch:
+            exact: gateway.envoyproxy.io
+        pathSeparatedPrefix: /origin
+      name: rewrite-route
+      route:
+        cluster: rewrite-route-dest
+        prefixRewrite: /rewrite
+        upgradeConfigs:
+        - upgradeType: websocket
diff --git a/test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml b/test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml
new file mode 100644
index 000000000..948503bea
--- /dev/null
+++ b/test/e2e/testdata/multi-referencegrants-same-namespace-services.yaml
@@ -0,0 +1,148 @@
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: multireferencegrants-ns
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: app-backend-v1
+  namespace: multireferencegrants-ns
+spec:
+  selector:
+    app: app-backend-v1
+  ports:
+  - protocol: TCP
+    port: 8080
+    targetPort: 3000
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: app-backend-v1
+  namespace: multireferencegrants-ns
+  labels:
+    app: app-backend-v1
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: app-backend-v1
+  template:
+    metadata:
+      labels:
+        app: app-backend-v1
+    spec:
+      containers:
+      - name: app-backend-v1
+        image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
+        env:
+        - name: POD_NAME
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.name
+        - name: NAMESPACE
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.namespace
+        - name: SERVICE_NAME
+          value: app-backend-v1
+        resources:
+          requests:
+            cpu: 10m
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: app-backend-v2
+  namespace: multireferencegrants-ns
+spec:
+  selector:
+    app: app-backend-v2
+  ports:
+  - protocol: TCP
+    port: 8080
+    targetPort: 3000
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: app-backend-v2
+  namespace: multireferencegrants-ns
+  labels:
+    app: app-backend-v2
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: app-backend-v2
+  template:
+    metadata:
+      labels:
+        app: app-backend-v2
+    spec:
+      containers:
+      - name: app-backend-v2
+        image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
+        env:
+        - name: POD_NAME
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.name
+        - name: NAMESPACE
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.namespace
+        - name: SERVICE_NAME
+          value: app-backend-v2
+        resources:
+          requests:
+            cpu: 10m
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: app-backend-v3
+  namespace: multireferencegrants-ns
+spec:
+  selector:
+    app: app-backend-v3
+  ports:
+  - protocol: TCP
+    port: 8080
+    targetPort: 3000
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: app-backend-v3
+  namespace: multireferencegrants-ns
+  labels:
+    app: app-backend-v3
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: app-backend-v3
+  template:
+    metadata:
+      labels:
+        app: app-backend-v3
+    spec:
+      containers:
+      - name: app-backend-v3
+        image: gcr.io/k8s-staging-gateway-api/echo-basic:v20231214-v1.0.0-140-gf544a46e
+        env:
+        - name: POD_NAME
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.name
+        - name: NAMESPACE
+          valueFrom:
+            fieldRef:
+              fieldPath: metadata.namespace
+        - name: SERVICE_NAME
+          value: app-backend-v3
+        resources:
+          requests:
+            cpu: 10m
diff --git a/test/e2e/testdata/multi-referencegrants-same-namespace.yaml b/test/e2e/testdata/multi-referencegrants-same-namespace.yaml
new file mode 100644
index 000000000..f9940185e
--- /dev/null
+++ b/test/e2e/testdata/multi-referencegrants-same-namespace.yaml
@@ -0,0 +1,92 @@
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: HTTPRoute
+metadata:
+  name: multi-referencegrant-same-namespace
+  namespace: gateway-conformance-infra
+spec:
+  hostnames:
+  - multireferencegrant.local
+  parentRefs:
+  - group: gateway.networking.k8s.io
+    kind: Gateway
+    name: same-namespace
+    namespace: gateway-conformance-infra
+  rules:
+  - backendRefs:
+    - group: ""
+      kind: Service
+      name: app-backend-v3
+      namespace: multireferencegrants-ns
+      port: 8080
+      weight: 1
+    matches:
+    - path:
+        type: PathPrefix
+        value: /v3/echo
+  - backendRefs:
+    - group: ""
+      kind: Service
+      name: app-backend-v2
+      namespace: multireferencegrants-ns
+      port: 8080
+      weight: 1
+    matches:
+    - path:
+        type: PathPrefix
+        value: /v2/echo
+  - backendRefs:
+    - group: ""
+      kind: Service
+      name: app-backend-v1
+      namespace: multireferencegrants-ns
+      port: 8080
+      weight: 1
+    matches:
+    - path:
+        type: PathPrefix
+        value: /v1/echo
+---
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: ReferenceGrant
+metadata:
+  name: app-backend-v1-rg
+  namespace: multireferencegrants-ns
+spec:
+  from:
+  - group: gateway.networking.k8s.io
+    kind: HTTPRoute
+    namespace: gateway-conformance-infra
+  to:
+  - group: ""
+    kind: Service
+    name: app-backend-v1
+---
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: ReferenceGrant
+metadata:
+  name: app-backend-v2-rg
+  namespace: multireferencegrants-ns
+spec:
+  from:
+  - group: gateway.networking.k8s.io
+    kind: HTTPRoute
+    namespace: gateway-conformance-infra
+  to:
+  - group: ""
+    kind: Service
+    name: app-backend-v2
+---
+apiVersion: gateway.networking.k8s.io/v1beta1
+kind: ReferenceGrant
+metadata:
+  name: app-backend-v3-rg
+  namespace: multireferencegrants-ns
+spec:
+  from:
+  - group: gateway.networking.k8s.io
+    kind: HTTPRoute
+    namespace: gateway-conformance-infra
+  to:
+  - group: ""
+    kind: Service
+    name: app-backend-v3
diff --git a/test/e2e/tests/referencegrants.go b/test/e2e/tests/referencegrants.go
new file mode 100644
index 000000000..903e64598
--- /dev/null
+++ b/test/e2e/tests/referencegrants.go
@@ -0,0 +1,79 @@
+// Copyright Envoy Gateway Authors
+// SPDX-License-Identifier: Apache-2.0
+// The full text of the Apache license is available in the LICENSE file at
+// the root of the repo.
+
+//go:build e2e
+// +build e2e
+
+package tests
+
+import (
+	"testing"
+
+	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/gateway-api/conformance/utils/http"
+	"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
+	"sigs.k8s.io/gateway-api/conformance/utils/suite"
+)
+
+func init() {
+	ConformanceTests = append(ConformanceTests, MultiReferenceGrantsSameNamespaceTest)
+}
+
+var MultiReferenceGrantsSameNamespaceTest = suite.ConformanceTest{
+	ShortName:   "MultiReferenceGrantsSameNamespace",
+	Description: "Test for multiple reference grants in the same namespace",
+	Manifests:   []string{"testdata/multi-referencegrants-same-namespace-services.yaml", "testdata/multi-referencegrants-same-namespace.yaml"},
+	Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
+		resourceNS := "gateway-conformance-infra"
+		routeNN := types.NamespacedName{Name: "multi-referencegrant-same-namespace", Namespace: resourceNS}
+		gwNN := types.NamespacedName{Name: "same-namespace", Namespace: resourceNS}
+		gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routeNN)
+
+		targetHost := "multireferencegrant.local"
+		targetNS := "multireferencegrants-ns"
+		testcases := []http.ExpectedResponse{
+			{
+				Request: http.Request{
+					Host: targetHost,
+					Path: "/v1/echo",
+				},
+				Response: http.Response{
+					StatusCode: 200,
+				},
+				Backend:   "app-backend-v1",
+				Namespace: targetNS,
+			},
+			{
+				Request: http.Request{
+					Host: targetHost,
+					Path: "/v2/echo",
+				},
+				Response: http.Response{
+					StatusCode: 200,
+				},
+				Backend:   "app-backend-v2",
+				Namespace: targetNS,
+			},
+			{
+				Request: http.Request{
+					Host: targetHost,
+					Path: "/v3/echo",
+				},
+				Response: http.Response{
+					StatusCode: 200,
+				},
+				Backend:   "app-backend-v3",
+				Namespace: targetNS,
+			},
+		}
+
+		for i, tc := range testcases {
+			t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
+				t.Parallel()
+				http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc)
+			})
+		}
+	},
+}
diff --git a/tools/src/setup-envtest/go.mod b/tools/src/setup-envtest/go.mod
index cef388c9c..53668dc72 100644
--- a/tools/src/setup-envtest/go.mod
+++ b/tools/src/setup-envtest/go.mod
@@ -1,6 +1,6 @@
 module local
 
-go 1.22.5
+go 1.22.7
 
 require sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20240423173400-ed81fa696dea