Repository: envoyproxy/gateway
Pull request #3974 (2024-07-30 14:50:02)

feat: Support DNS resolution settings
### DNS resolution settings
The purpose is to allow control over DNS resolution settings for non static cluster endpoints. 
With this PR, it will be possible to define custom DNS resolution settings through a BTP policy.

Fixes # https://github.com/envoyproxy/gateway/issues/3690


codecov[bot]: ## [Codecov](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?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 `73.33333%` with `8 lines` in your changes missing coverage. Please review.
> Project coverage is 67.58%. Comparing base [(`ddf2178`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/ddf21783285d3632bfe0bc8acafc2a0273c6e930?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) to head [(`a6888e6`)](https://app.codecov.io/gh/envoyproxy/gateway/commit/a6888e64f4ce475e8ee812b5fd3191e23e673fb5?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy).

| [Files](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?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/xds/translator/cluster.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?src=pr&el=tree&filepath=internal%2Fxds%2Ftranslator%2Fcluster.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwveGRzL3RyYW5zbGF0b3IvY2x1c3Rlci5nbw==) | 0.00% | [5 Missing and 1 partial :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy) |
| [internal/xds/translator/translator.go](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?src=pr&el=tree&filepath=internal%2Fxds%2Ftranslator%2Ftranslator.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=envoyproxy#diff-aW50ZXJuYWwveGRzL3RyYW5zbGF0b3IvdHJhbnNsYXRvci5nbw==) | 0.00% | [1 Missing and 1 partial :warning: ](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?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             @@
##             main    #3974      +/-   ##
==========================================
+ Coverage   67.57%   67.58%   +0.01%     
==========================================
  Files         183      183              
  Lines       22406    22436      +30     
==========================================
+ Hits        15140    15163      +23     
- Misses       6188     6193       +5     
- Partials     1078     1080       +2     
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/envoyproxy/gateway/pull/3974?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).

alexwo: /retest
guydc: /retest
alexwo: /retest
alexwo: /retest
alexwo: /retest

Patch:
diff --git a/api/v1alpha1/backendtrafficpolicy_types.go b/api/v1alpha1/backendtrafficpolicy_types.go
index f484f44b4..a8c39e9df 100644
--- a/api/v1alpha1/backendtrafficpolicy_types.go
+++ b/api/v1alpha1/backendtrafficpolicy_types.go
@@ -110,6 +110,10 @@ type BackendTrafficPolicySpec struct {
 	//
 	// +optional
 	Connection *BackendConnection `json:"connection,omitempty"`
+	// DNS includes dns resolution settings.
+	//
+	// +optional
+	DNS *DNS `json:"dns,omitempty"`
 }
 
 // +kubebuilder:object:root=true
diff --git a/api/v1alpha1/dns_types.go b/api/v1alpha1/dns_types.go
new file mode 100644
index 000000000..62108a934
--- /dev/null
+++ b/api/v1alpha1/dns_types.go
@@ -0,0 +1,18 @@
+// 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.
+
+package v1alpha1
+
+import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+type DNS struct {
+	// DNSRefreshRate specifies the rate at which DNS records should be refreshed.
+	// Defaults to 30 seconds.
+	DNSRefreshRate *metav1.Duration `json:"dnsRefreshRate,omitempty"`
+	// RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.
+	// If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL.
+	// Defaults to true.
+	RespectDNSTTL *bool `json:"respectDnsTtl,omitempty"`
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 3ea39b669..e6c4da29a 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -569,6 +569,11 @@ func (in *BackendTrafficPolicySpec) DeepCopyInto(out *BackendTrafficPolicySpec)
 		*out = new(BackendConnection)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.DNS != nil {
+		in, out := &in.DNS, &out.DNS
+		*out = new(DNS)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new BackendTrafficPolicySpec.
@@ -1097,6 +1102,31 @@ func (in *CustomTag) DeepCopy() *CustomTag {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DNS) DeepCopyInto(out *DNS) {
+	*out = *in
+	if in.DNSRefreshRate != nil {
+		in, out := &in.DNSRefreshRate, &out.DNSRefreshRate
+		*out = new(v1.Duration)
+		**out = **in
+	}
+	if in.RespectDNSTTL != nil {
+		in, out := &in.RespectDNSTTL, &out.RespectDNSTTL
+		*out = new(bool)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
+func (in *DNS) DeepCopy() *DNS {
+	if in == nil {
+		return nil
+	}
+	out := new(DNS)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *EnvironmentCustomTag) DeepCopyInto(out *EnvironmentCustomTag) {
 	*out = *in
diff --git a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
index 20ffe8339..2ddf8c841 100644
--- a/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
+++ b/charts/gateway-helm/crds/generated/gateway.envoyproxy.io_backendtrafficpolicies.yaml
@@ -138,6 +138,21 @@ spec:
                       rule: 'type(self) == string ? self.matches(r"^[1-9]+[0-9]*([EPTGMK]i|[EPTGMk])?$")
                         : type(self) == int'
                 type: object
+              dns:
+                description: DNS includes dns resolution settings.
+                properties:
+                  dnsRefreshRate:
+                    description: |-
+                      DNSRefreshRate specifies the rate at which DNS records should be refreshed.
+                      Defaults to 30 seconds.
+                    type: string
+                  respectDnsTtl:
+                    description: |-
+                      RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.
+                      If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL.
+                      Defaults to true.
+                    type: boolean
+                type: object
               faultInjection:
                 description: |-
                   FaultInjection defines the fault injection policy to be applied. This configuration can be used to
diff --git a/internal/gatewayapi/backendtrafficpolicy.go b/internal/gatewayapi/backendtrafficpolicy.go
index 26d4a2a9b..65d4404df 100644
--- a/internal/gatewayapi/backendtrafficpolicy.go
+++ b/internal/gatewayapi/backendtrafficpolicy.go
@@ -295,6 +295,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 		ka        *ir.TCPKeepalive
 		rt        *ir.Retry
 		bc        *ir.BackendConnection
+		ds        *ir.DNS
 		err, errs error
 	)
 
@@ -349,6 +350,10 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 		}
 	}
 
+	if policy.Spec.DNS != nil {
+		ds = t.translateDNS(policy)
+	}
+
 	// Early return if got any errors
 	if errs != nil {
 		return errs
@@ -368,6 +373,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 					r.TCPKeepalive = ka
 					r.Timeout = to
 					r.BackendConnection = bc
+					r.DNS = ds
 				}
 			}
 		}
@@ -380,6 +386,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 					r.LoadBalancer = lb
 					r.Timeout = to
 					r.BackendConnection = bc
+					r.DNS = ds
 				}
 			}
 		}
@@ -400,6 +407,7 @@ func (t *Translator) translateBackendTrafficPolicyForRoute(policy *egv1a1.Backen
 						BackendConnection: bc,
 					}
 
+					r.DNS = ds
 					// Update the Host field in HealthCheck, now that we have access to the Route Hostname.
 					r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname)
 
@@ -432,6 +440,7 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 		ct        *ir.Timeout
 		ka        *ir.TCPKeepalive
 		rt        *ir.Retry
+		ds        *ir.DNS
 		err, errs error
 	)
 
@@ -479,6 +488,10 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 		}
 	}
 
+	if policy.Spec.DNS != nil {
+		ds = t.translateDNS(policy)
+	}
+
 	// Early return if got any errors
 	if errs != nil {
 		return errs
@@ -516,6 +529,10 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 			if r.Timeout == nil {
 				r.Timeout = ct
 			}
+
+			if r.DNS == nil {
+				r.DNS = ds
+			}
 		}
 	}
 
@@ -540,6 +557,10 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 		if route.Timeout == nil {
 			route.Timeout = ct
 		}
+
+		if route.DNS == nil {
+			route.DNS = ds
+		}
 	}
 
 	for _, http := range x.HTTP {
@@ -568,6 +589,10 @@ func (t *Translator) translateBackendTrafficPolicyForGateway(policy *egv1a1.Back
 				Retry:          rt,
 			}
 
+			if r.DNS == nil {
+				r.DNS = ds
+			}
+
 			// Update the Host field in HealthCheck, now that we have access to the Route Hostname.
 			r.Traffic.HealthCheck.SetHTTPHostIfAbsent(r.Hostname)
 
@@ -847,6 +872,17 @@ func (t *Translator) buildConsistentHashLoadBalancer(policy *egv1a1.BackendTraff
 	return consistentHash, nil
 }
 
+func (t *Translator) translateDNS(policy *egv1a1.BackendTrafficPolicy) *ir.DNS {
+	ds := &ir.DNS{}
+	if policy.Spec.DNS.RespectDNSTTL != nil {
+		ds.RespectDNSTTL = policy.Spec.DNS.RespectDNSTTL
+	}
+	if policy.Spec.DNS.DNSRefreshRate != nil {
+		ds.DNSRefreshRate = policy.Spec.DNS.DNSRefreshRate
+	}
+	return ds
+}
+
 func (t *Translator) buildProxyProtocol(policy *egv1a1.BackendTrafficPolicy) *ir.ProxyProtocol {
 	var pp *ir.ProxyProtocol
 	switch policy.Spec.ProxyProtocol.Version {
diff --git a/internal/ir/xds.go b/internal/ir/xds.go
index 3d300f1a5..f4f059a2a 100644
--- a/internal/ir/xds.go
+++ b/internal/ir/xds.go
@@ -563,6 +563,17 @@ type HTTPRoute struct {
 	UseClientProtocol *bool `json:"useClientProtocol,omitempty" yaml:"useClientProtocol,omitempty"`
 	// Metadata is used to enrich envoy route metadata with user and provider-specific information
 	Metadata *ResourceMetadata `json:"metadata,omitempty" yaml:"metadata,omitempty"`
+	// DNS is used to configure how DNS resolution is handled for the route
+	DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"`
+}
+
+// DNS contains configuration options for DNS resolution.
+// +k8s:deepcopy-gen=true
+type DNS struct {
+	// DNSRefreshRate specifies the rate at which DNS records should be refreshed.
+	DNSRefreshRate *metav1.Duration `json:"dnsRefreshRate,omitempty"`
+	// RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.
+	RespectDNSTTL *bool `json:"respectDnsTtl,omitempty"`
 }
 
 // TrafficFeatures holds the information associated with the Backend Traffic Policy.
@@ -1386,6 +1397,8 @@ type TCPRoute struct {
 	ProxyProtocol *ProxyProtocol `json:"proxyProtocol,omitempty" yaml:"proxyProtocol,omitempty"`
 	// settings of upstream connection
 	BackendConnection *BackendConnection `json:"backendConnection,omitempty" yaml:"backendConnection,omitempty"`
+	// DNS is used to configure how DNS resolution is handled for the route
+	DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"`
 }
 
 // TLS holds information for configuring TLS on a listener
@@ -1496,6 +1509,7 @@ type UDPRoute struct {
 	Timeout *Timeout `json:"timeout,omitempty" yaml:"timeout,omitempty"`
 	// settings of upstream connection
 	BackendConnection *BackendConnection `json:"backendConnection,omitempty" yaml:"backendConnection,omitempty"`
+	DNS               *DNS               `json:"dns,omitempty" yaml:"dns,omitempty"`
 }
 
 // Validate the fields within the UDPListener structure
diff --git a/internal/ir/zz_generated.deepcopy.go b/internal/ir/zz_generated.deepcopy.go
index 273eeb1c3..e0a7b4557 100644
--- a/internal/ir/zz_generated.deepcopy.go
+++ b/internal/ir/zz_generated.deepcopy.go
@@ -562,6 +562,31 @@ func (in *CoreListenerDetails) DeepCopy() *CoreListenerDetails {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *DNS) DeepCopyInto(out *DNS) {
+	*out = *in
+	if in.DNSRefreshRate != nil {
+		in, out := &in.DNSRefreshRate, &out.DNSRefreshRate
+		*out = new(v1.Duration)
+		**out = **in
+	}
+	if in.RespectDNSTTL != nil {
+		in, out := &in.RespectDNSTTL, &out.RespectDNSTTL
+		*out = new(bool)
+		**out = **in
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
+func (in *DNS) DeepCopy() *DNS {
+	if in == nil {
+		return nil
+	}
+	out := new(DNS)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *DestinationEndpoint) DeepCopyInto(out *DestinationEndpoint) {
 	*out = *in
@@ -1318,6 +1343,11 @@ func (in *HTTPRoute) DeepCopyInto(out *HTTPRoute) {
 		*out = new(ResourceMetadata)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.DNS != nil {
+		in, out := &in.DNS, &out.DNS
+		*out = new(DNS)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HTTPRoute.
@@ -2524,6 +2554,11 @@ func (in *TCPRoute) DeepCopyInto(out *TCPRoute) {
 		*out = new(BackendConnection)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.DNS != nil {
+		in, out := &in.DNS, &out.DNS
+		*out = new(DNS)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TCPRoute.
@@ -2914,6 +2949,11 @@ func (in *UDPRoute) DeepCopyInto(out *UDPRoute) {
 		*out = new(BackendConnection)
 		(*in).DeepCopyInto(*out)
 	}
+	if in.DNS != nil {
+		in, out := &in.DNS, &out.DNS
+		*out = new(DNS)
+		(*in).DeepCopyInto(*out)
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UDPRoute.
diff --git a/internal/xds/translator/cluster.go b/internal/xds/translator/cluster.go
index e646f4109..9a7819a59 100644
--- a/internal/xds/translator/cluster.go
+++ b/internal/xds/translator/cluster.go
@@ -52,6 +52,7 @@ type xdsClusterArgs struct {
 	tcpkeepalive      *ir.TCPKeepalive
 	metrics           *ir.Metrics
 	backendConnection *ir.BackendConnection
+	dns               *ir.DNS
 	useClientProtocol bool
 }
 
@@ -144,6 +145,16 @@ func buildXdsCluster(args *xdsClusterArgs) *clusterv3.Cluster {
 		cluster.ClusterDiscoveryType = &clusterv3.Cluster_Type{Type: clusterv3.Cluster_STRICT_DNS}
 		cluster.DnsRefreshRate = durationpb.New(30 * time.Second)
 		cluster.RespectDnsTtl = true
+		if args.dns != nil {
+			if args.dns.DNSRefreshRate != nil {
+				if args.dns.DNSRefreshRate.Duration > 0 {
+					cluster.DnsRefreshRate = durationpb.New(args.dns.DNSRefreshRate.Duration)
+				}
+			}
+			if args.dns.RespectDNSTTL != nil {
+				cluster.RespectDnsTtl = ptr.Deref(args.dns.RespectDNSTTL, true)
+			}
+		}
 	}
 
 	// build common, HTTP/1 and HTTP/2  protocol options for cluster
@@ -649,3 +660,85 @@ func buildBackandConnectionBufferLimitBytes(bc *ir.BackendConnection) *wrappers.
 
 	return wrapperspb.UInt32(tcpClusterPerConnectionBufferLimitBytes)
 }
+
+type ExtraArgs struct {
+	metrics       *ir.Metrics
+	http1Settings *ir.HTTP1Settings
+}
+
+type clusterArgs interface {
+	asClusterArgs(extras *ExtraArgs) *xdsClusterArgs
+}
+
+type UDPRouteTranslator struct {
+	*ir.UDPRoute
+}
+
+func (route *UDPRouteTranslator) asClusterArgs(extra *ExtraArgs) *xdsClusterArgs {
+	return &xdsClusterArgs{
+		name:              route.Destination.Name,
+		settings:          route.Destination.Settings,
+		loadBalancer:      route.LoadBalancer,
+		timeout:           route.Timeout,
+		tSocket:           nil,
+		endpointType:      buildEndpointType(route.Destination.Settings),
+		metrics:           extra.metrics,
+		backendConnection: route.BackendConnection,
+		dns:               route.DNS,
+	}
+}
+
+type TCPRouteTranslator struct {
+	*ir.TCPRoute
+}
+
+func (route *TCPRouteTranslator) asClusterArgs(extra *ExtraArgs) *xdsClusterArgs {
+	return &xdsClusterArgs{
+		name:              route.Destination.Name,
+		settings:          route.Destination.Settings,
+		loadBalancer:      route.LoadBalancer,
+		proxyProtocol:     route.ProxyProtocol,
+		circuitBreaker:    route.CircuitBreaker,
+		tcpkeepalive:      route.TCPKeepalive,
+		healthCheck:       route.HealthCheck,
+		timeout:           route.Timeout,
+		endpointType:      buildEndpointType(route.Destination.Settings),
+		metrics:           extra.metrics,
+		backendConnection: route.BackendConnection,
+		dns:               route.DNS,
+	}
+}
+
+type HTTPRouteTranslator struct {
+	*ir.HTTPRoute
+}
+
+func (httpRoute *HTTPRouteTranslator) asClusterArgs(extra *ExtraArgs) *xdsClusterArgs {
+	clusterArgs := &xdsClusterArgs{
+		name:              httpRoute.Destination.Name,
+		settings:          httpRoute.Destination.Settings,
+		tSocket:           nil,
+		endpointType:      buildEndpointType(httpRoute.Destination.Settings),
+		metrics:           extra.metrics,
+		http1Settings:     extra.http1Settings,
+		useClientProtocol: ptr.Deref(httpRoute.UseClientProtocol, false),
+	}
+
+	// Populate traffic features.
+	bt := httpRoute.Traffic
+	if bt != nil {
+		clusterArgs.loadBalancer = bt.LoadBalancer
+		clusterArgs.proxyProtocol = bt.ProxyProtocol
+		clusterArgs.circuitBreaker = bt.CircuitBreaker
+		clusterArgs.healthCheck = bt.HealthCheck
+		clusterArgs.timeout = bt.Timeout
+		clusterArgs.tcpkeepalive = bt.TCPKeepalive
+		clusterArgs.backendConnection = bt.BackendConnection
+	}
+
+	if httpRoute.DNS != nil {
+		clusterArgs.dns = httpRoute.DNS
+	}
+
+	return clusterArgs
+}
diff --git a/internal/xds/translator/translator.go b/internal/xds/translator/translator.go
index a58903e88..861e36ca8 100644
--- a/internal/xds/translator/translator.go
+++ b/internal/xds/translator/translator.go
@@ -24,7 +24,6 @@ import (
 	"google.golang.org/protobuf/proto"
 	"google.golang.org/protobuf/types/known/anypb"
 	"google.golang.org/protobuf/types/known/wrapperspb"
-	"k8s.io/utils/ptr"
 
 	egv1a1 "github.com/envoyproxy/gateway/api/v1alpha1"
 	extensionTypes "github.com/envoyproxy/gateway/internal/extension/types"
@@ -453,9 +452,11 @@ func (t *Translator) addRouteToRouteConfig(
 		if httpRoute.Destination != nil {
 			if err = processXdsCluster(
 				tCtx,
-				httpRoute,
-				httpListener.HTTP1,
-				metrics,
+				&HTTPRouteTranslator{httpRoute},
+				&ExtraArgs{
+					metrics:       metrics,
+					http1Settings: httpListener.HTTP1,
+				},
 			); err != nil {
 				errs = errors.Join(errs, err)
 			}
@@ -573,19 +574,7 @@ func (t *Translator) processTCPListenerXdsTranslation(
 		patchProxyProtocolFilter(xdsListener, tcpListener.EnableProxyProtocol)
 
 		for _, route := range tcpListener.Routes {
-			if err := addXdsCluster(tCtx, &xdsClusterArgs{
-				name:              route.Destination.Name,
-				settings:          route.Destination.Settings,
-				loadBalancer:      route.LoadBalancer,
-				proxyProtocol:     route.ProxyProtocol,
-				circuitBreaker:    route.CircuitBreaker,
-				tcpkeepalive:      route.TCPKeepalive,
-				healthCheck:       route.HealthCheck,
-				timeout:           route.Timeout,
-				endpointType:      buildEndpointType(route.Destination.Settings),
-				metrics:           metrics,
-				backendConnection: route.BackendConnection,
-			}); err != nil && !errors.Is(err, ErrXdsClusterExists) {
+			if err := processXdsCluster(tCtx, &TCPRouteTranslator{route}, &ExtraArgs{metrics: metrics}); err != nil && !errors.Is(err, ErrXdsClusterExists) {
 				errs = errors.Join(errs, err)
 			}
 			if route.TLS != nil && route.TLS.Terminate != nil {
@@ -647,16 +636,7 @@ func processUDPListenerXdsTranslation(
 			}
 
 			// 1:1 between IR UDPRoute and xDS Cluster
-			if err := addXdsCluster(tCtx, &xdsClusterArgs{
-				name:              route.Destination.Name,
-				settings:          route.Destination.Settings,
-				loadBalancer:      route.LoadBalancer,
-				timeout:           route.Timeout,
-				tSocket:           nil,
-				endpointType:      buildEndpointType(route.Destination.Settings),
-				metrics:           metrics,
-				backendConnection: route.BackendConnection,
-			}); err != nil && !errors.Is(err, ErrXdsClusterExists) {
+			if err := processXdsCluster(tCtx, &UDPRouteTranslator{route}, &ExtraArgs{metrics: metrics}); err != nil && !errors.Is(err, ErrXdsClusterExists) {
 				errs = errors.Join(errs, err)
 			}
 		}
@@ -748,34 +728,11 @@ func findXdsEndpoint(tCtx *types.ResourceVersionTable, name string) *endpointv3.
 	return nil
 }
 
-// processXdsCluster processes a xds cluster by its endpoint address type.
-func processXdsCluster(tCtx *types.ResourceVersionTable, httpRoute *ir.HTTPRoute, http1Settings *ir.HTTP1Settings, metrics *ir.Metrics) error {
-	clusterArgs := &xdsClusterArgs{
-		name:              httpRoute.Destination.Name,
-		settings:          httpRoute.Destination.Settings,
-		tSocket:           nil,
-		endpointType:      buildEndpointType(httpRoute.Destination.Settings),
-		http1Settings:     http1Settings,
-		metrics:           metrics,
-		useClientProtocol: ptr.Deref(httpRoute.UseClientProtocol, false),
-	}
-
-	// Populate traffic features.
-	bt := httpRoute.Traffic
-	if bt != nil {
-		clusterArgs.loadBalancer = bt.LoadBalancer
-		clusterArgs.proxyProtocol = bt.ProxyProtocol
-		clusterArgs.circuitBreaker = bt.CircuitBreaker
-		clusterArgs.healthCheck = bt.HealthCheck
-		clusterArgs.timeout = bt.Timeout
-		clusterArgs.tcpkeepalive = bt.TCPKeepalive
-		clusterArgs.backendConnection = bt.BackendConnection
-	}
-
-	if err := addXdsCluster(tCtx, clusterArgs); err != nil && !errors.Is(err, ErrXdsClusterExists) {
+// processXdsCluster processes xds cluster with args per route.
+func processXdsCluster(tCtx *types.ResourceVersionTable, route clusterArgs, extras *ExtraArgs) error {
+	if err := addXdsCluster(tCtx, route.asClusterArgs(extras)); err != nil && !errors.Is(err, ErrXdsClusterExists) {
 		return err
 	}
-
 	return nil
 }
 
diff --git a/site/content/en/news/releases/_index.md b/site/content/en/news/releases/_index.md
index cff552837..e8282654b 100644
--- a/site/content/en/news/releases/_index.md
+++ b/site/content/en/news/releases/_index.md
@@ -36,6 +36,7 @@ communications with the Envoy Gateway community, and the mechanics of the releas
 | 2023 Q3 |    Arko Dasgupta ([arkodg](https://github.com/arkodg))         |
 | 2023 Q4 |    Arko Dasgupta ([arkodg](https://github.com/arkodg))         |
 | 2024 Q1 |    Xunzhuo Liu ([Xunzhuo](https://github.com/Xunzhuo))         |
+| 2024 Q2 |    Guy Daich ([guydc](https://github.com/guydc))               |
 
 ## Release Schedule
 
@@ -49,6 +50,8 @@ In order to align with the Envoy Proxy [release schedule][], Envoy Gateway relea
 |  0.4.0  | 2023/04/22  | 2023/04/24  |   +2 days   |  2023/10/24 |
 |  0.5.0  | 2023/07/22  | 2023/08/02  |   +10 days  |  2024/01/02 |
 |  0.6.0  | 2023/10/22  | 2023/11/02  |   +10 days  |  2024/05/02 |
+|  1.0.0  | 2024/03/06  | 2023/03/13  |   +7 days   |  2024/09/13 |
+|  1.1.0  | 2024/07/16	| 2024/07/22  |   +6 days   |  2024/01/22 |
 
 [v2.0.0 spec]: https://semver.org/spec/v2.0.0.html
 [release guide]: ../../contributions/releasing


Test patch:
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.in.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.in.yaml
new file mode 100644
index 000000000..f1d48c4d3
--- /dev/null
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.in.yaml
@@ -0,0 +1,127 @@
+gateways:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    namespace: envoy-gateway
+    name: gateway-1
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - name: http
+      protocol: HTTP
+      port: 80
+      allowedRoutes:
+        namespaces:
+          from: All
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    namespace: envoy-gateway
+    name: gateway-2
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - name: http
+      protocol: HTTP
+      port: 80
+      allowedRoutes:
+        namespaces:
+          from: All
+httpRoutes:
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-1
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-2
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/"
+      backendRefs:
+      - name: service-1
+        port: 8080
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-2
+  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
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    namespace: default
+    name: httproute-3
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - namespace: envoy-gateway
+      name: gateway-1
+      sectionName: http
+    rules:
+    - matches:
+      - path:
+          value: "/v3"
+      backendRefs:
+      - name: service-3
+        port: 8080
+backendTrafficPolicies:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route-1
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-1
+    dns:
+      dnsRefreshRate: "1s"
+      respectDnsTtl: true
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    namespace: default
+    name: policy-for-route-2
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-2
+    dns:
+      dnsRefreshRate: "5s"
+      respectDnsTtl: false
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    namespace: envoy-gateway
+    name: policy-for-all-routes-in-gateway-1
+  spec:
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: Gateway
+      name: gateway-1
+    dns:
+      dnsRefreshRate: "10s"
+      respectDnsTtl: true
diff --git a/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml b/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml
new file mode 100644
index 000000000..89d990232
--- /dev/null
+++ b/internal/gatewayapi/testdata/backendtrafficpolicy-with-dns-settings.out.yaml
@@ -0,0 +1,427 @@
+backendTrafficPolicies:
+- apiVersion: gateway.envoyproxy.io/v1alpha1
+  kind: BackendTrafficPolicy
+  metadata:
+    creationTimestamp: null
+    name: policy-for-route-1
+    namespace: default
+  spec:
+    dns:
+      dnsRefreshRate: 1s
+      respectDnsTtl: true
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-1
+  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:
+    creationTimestamp: null
+    name: policy-for-route-2
+    namespace: default
+  spec:
+    dns:
+      dnsRefreshRate: 5s
+      respectDnsTtl: false
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: HTTPRoute
+      name: httproute-2
+  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:
+    creationTimestamp: null
+    name: policy-for-all-routes-in-gateway-1
+    namespace: envoy-gateway
+  spec:
+    dns:
+      dnsRefreshRate: 10s
+      respectDnsTtl: true
+    targetRef:
+      group: gateway.networking.k8s.io
+      kind: Gateway
+      name: gateway-1
+  status:
+    ancestors:
+    - ancestorRef:
+        group: gateway.networking.k8s.io
+        kind: Gateway
+        name: gateway-1
+        namespace: envoy-gateway
+      conditions:
+      - lastTransitionTime: null
+        message: Policy has been accepted.
+        reason: Accepted
+        status: "True"
+        type: Accepted
+      controllerName: gateway.envoyproxy.io/gatewayclass-controller
+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: http
+      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: http
+      supportedKinds:
+      - group: gateway.networking.k8s.io
+        kind: HTTPRoute
+      - group: gateway.networking.k8s.io
+        kind: GRPCRoute
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: Gateway
+  metadata:
+    creationTimestamp: null
+    name: gateway-2
+    namespace: envoy-gateway
+  spec:
+    gatewayClassName: envoy-gateway-class
+    listeners:
+    - allowedRoutes:
+        namespaces:
+          from: All
+      name: http
+      port: 80
+      protocol: HTTP
+  status:
+    listeners:
+    - attachedRoutes: 2
+      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: http
+      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: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-2
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-1
+        port: 8080
+      matches:
+      - path:
+          value: /
+  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
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-2
+    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
+- apiVersion: gateway.networking.k8s.io/v1
+  kind: HTTPRoute
+  metadata:
+    creationTimestamp: null
+    name: httproute-3
+    namespace: default
+  spec:
+    hostnames:
+    - gateway.envoyproxy.io
+    parentRefs:
+    - name: gateway-1
+      namespace: envoy-gateway
+      sectionName: http
+    rules:
+    - backendRefs:
+      - name: service-3
+        port: 8080
+      matches:
+      - path:
+          value: /v3
+  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-1
+        namespace: envoy-gateway
+        sectionName: http
+infraIR:
+  envoy-gateway/gateway-1:
+    proxy:
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-1/http
+        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
+  envoy-gateway/gateway-2:
+    proxy:
+      listeners:
+      - address: null
+        name: envoy-gateway/gateway-2/http
+        ports:
+        - containerPort: 10080
+          name: http-80
+          protocol: HTTP
+          servicePort: 80
+      metadata:
+        labels:
+          gateway.envoyproxy.io/owning-gateway-name: gateway-2
+          gateway.envoyproxy.io/owning-gateway-namespace: envoy-gateway
+      name: envoy-gateway/gateway-2
+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: http
+      name: envoy-gateway/gateway-1/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          name: httproute/default/httproute-3/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        dns:
+          dnsRefreshRate: 10s
+          respectDnsTtl: true
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-3
+          namespace: default
+        name: httproute/default/httproute-3/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /v3
+        traffic: {}
+  envoy-gateway/gateway-2:
+    accessLog:
+      text:
+      - path: /dev/stdout
+    http:
+    - address: 0.0.0.0
+      hostnames:
+      - '*'
+      isHTTP2: false
+      metadata:
+        kind: Gateway
+        name: gateway-2
+        namespace: envoy-gateway
+        sectionName: http
+      name: envoy-gateway/gateway-2/http
+      path:
+        escapedSlashesAction: UnescapeAndRedirect
+        mergeSlashes: true
+      port: 10080
+      routes:
+      - destination:
+          name: httproute/default/httproute-2/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        dns:
+          dnsRefreshRate: 5s
+          respectDnsTtl: false
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-2
+          namespace: default
+        name: httproute/default/httproute-2/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /v2
+        traffic: {}
+      - destination:
+          name: httproute/default/httproute-1/rule/0
+          settings:
+          - addressType: IP
+            endpoints:
+            - host: 7.7.7.7
+              port: 8080
+            protocol: HTTP
+            weight: 1
+        dns:
+          dnsRefreshRate: 1s
+          respectDnsTtl: true
+        hostname: gateway.envoyproxy.io
+        isHTTP2: false
+        metadata:
+          kind: HTTPRoute
+          name: httproute-1
+          namespace: default
+        name: httproute/default/httproute-1/rule/0/match/0/gateway_envoyproxy_io
+        pathMatch:
+          distinct: false
+          name: ""
+          prefix: /
+        traffic: {}
diff --git a/site/content/en/latest/api/extension_types.md b/site/content/en/latest/api/extension_types.md
index 9a2cd961a..b0e858331 100644
--- a/site/content/en/latest/api/extension_types.md
+++ b/site/content/en/latest/api/extension_types.md
@@ -460,6 +460,7 @@ _Appears in:_
 | `useClientProtocol` | _boolean_ |  false  | UseClientProtocol configures Envoy to prefer sending requests to backends using<br />the same HTTP protocol that the incoming request used. Defaults to false, which means<br />that Envoy will use the protocol indicated by the attached BackendRef. |
 | `timeout` | _[Timeout](#timeout)_ |  false  | Timeout settings for the backend connections. |
 | `connection` | _[BackendConnection](#backendconnection)_ |  false  | Connection includes backend connection settings. |
+| `dns` | _[DNS](#dns)_ |  false  | DNS includes dns resolution settings. |
 
 
 #### BasicAuth
@@ -845,6 +846,21 @@ _Appears in:_
 | `RequestHeader` | CustomTagTypeRequestHeader adds value from request header to each span.<br /> | 
 
 
+#### DNS
+
+
+
+
+
+_Appears in:_
+- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
+
+| Field | Type | Required | Description |
+| ---   | ---  | ---      | ---         |
+| `dnsRefreshRate` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  true  | DNSRefreshRate specifies the rate at which DNS records should be refreshed.<br />Defaults to 30 seconds. |
+| `respectDnsTtl` | _boolean_ |  true  | RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.<br />If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL.<br />Defaults to true. |
+
+
 #### EnvironmentCustomTag
 
 
diff --git a/site/content/zh/latest/api/extension_types.md b/site/content/zh/latest/api/extension_types.md
index 9a2cd961a..b0e858331 100644
--- a/site/content/zh/latest/api/extension_types.md
+++ b/site/content/zh/latest/api/extension_types.md
@@ -460,6 +460,7 @@ _Appears in:_
 | `useClientProtocol` | _boolean_ |  false  | UseClientProtocol configures Envoy to prefer sending requests to backends using<br />the same HTTP protocol that the incoming request used. Defaults to false, which means<br />that Envoy will use the protocol indicated by the attached BackendRef. |
 | `timeout` | _[Timeout](#timeout)_ |  false  | Timeout settings for the backend connections. |
 | `connection` | _[BackendConnection](#backendconnection)_ |  false  | Connection includes backend connection settings. |
+| `dns` | _[DNS](#dns)_ |  false  | DNS includes dns resolution settings. |
 
 
 #### BasicAuth
@@ -845,6 +846,21 @@ _Appears in:_
 | `RequestHeader` | CustomTagTypeRequestHeader adds value from request header to each span.<br /> | 
 
 
+#### DNS
+
+
+
+
+
+_Appears in:_
+- [BackendTrafficPolicySpec](#backendtrafficpolicyspec)
+
+| Field | Type | Required | Description |
+| ---   | ---  | ---      | ---         |
+| `dnsRefreshRate` | _[Duration](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.29/#duration-v1-meta)_ |  true  | DNSRefreshRate specifies the rate at which DNS records should be refreshed.<br />Defaults to 30 seconds. |
+| `respectDnsTtl` | _boolean_ |  true  | RespectDNSTTL indicates whether the DNS Time-To-Live (TTL) should be respected.<br />If the value is set to true, the DNS refresh rate will be set to the resource record’s TTL.<br />Defaults to true. |
+
+
 #### EnvironmentCustomTag