Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions internal/xds/translator/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,18 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute, httpListener *ir.HTTPListener, backe
// Hash Policy
if router.GetRoute() != nil {
router.GetRoute().HashPolicy = buildHashPolicy(httpRoute)

// When a route splits traffic across multiple weighted backendRefs and uses a
// ConsistentHash load balancer, enable use_hash_policy so Envoy selects the weighted
// cluster deterministically from the request's hash policy instead of at random.
// Without this, the consistent hash only pins endpoint selection within a cluster,
// while the choice among the weighted backends stays random per request, so a client
// is not pinned to a single backend across the split.
if wc := router.GetRoute().GetWeightedClusters(); wc != nil && len(router.GetRoute().GetHashPolicy()) > 0 {
wc.RandomValueSpecifier = &routev3.WeightedCluster_UseHashPolicy{
UseHashPolicy: wrapperspb.Bool(true),
}
}
}

// Timeouts
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
http:
- name: "first-listener"
address: "::"
port: 10080
hostnames:
- "*"
path:
mergeSlashes: true
escapedSlashesAction: UnescapeAndRedirect
routes:
# A weighted split across two distinct backend clusters (cluster-per-setting is
# triggered by the per-backendRef filter) combined with a ConsistentHash load
# balancer. use_hash_policy must be set on the weighted clusters so the cluster
# selection is driven by the request hash policy instead of being random per
# request, pinning a client to a single backend across the split.
- name: "first-route"
hostname: "*"
traffic:
loadBalancer:
consistentHash:
headers:
- name: x-user-id
destination:
name: "first-route-dest"
settings:
- addressType: IP
endpoints:
- host: "1.1.1.1"
port: 50001
weight: 80
name: "first-route-dest/backend/0"
filters:
addRequestHeaders:
- name: x-backend
value:
- primary
append: false
- addressType: IP
endpoints:
- host: "2.2.2.2"
port: 50002
weight: 20
name: "first-route-dest/backend/1"
filters:
addRequestHeaders:
- name: x-backend
value:
- backup
append: false
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
- circuitBreakers:
thresholds:
- maxRetries: 1024
commonLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_PREFERRED
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: first-route-dest/backend/0
ignoreHealthOnHostRemoval: true
loadBalancingPolicy:
policies:
- typedExtensionConfig:
name: envoy.load_balancing_policies.maglev
typedConfig:
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.maglev.v3.Maglev
name: first-route-dest/backend/0
perConnectionBufferLimitBytes: 32768
type: EDS
- circuitBreakers:
thresholds:
- maxRetries: 1024
commonLbConfig: {}
connectTimeout: 10s
dnsLookupFamily: V4_PREFERRED
edsClusterConfig:
edsConfig:
ads: {}
resourceApiVersion: V3
serviceName: first-route-dest/backend/1
ignoreHealthOnHostRemoval: true
loadBalancingPolicy:
policies:
- typedExtensionConfig:
name: envoy.load_balancing_policies.maglev
typedConfig:
'@type': type.googleapis.com/envoy.extensions.load_balancing_policies.maglev.v3.Maglev
name: first-route-dest/backend/1
perConnectionBufferLimitBytes: 32768
type: EDS
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
- clusterName: first-route-dest/backend/0
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 1.1.1.1
portValue: 50001
loadBalancingWeight: 1
loadBalancingWeight: 80
locality:
region: first-route-dest/backend/0
- clusterName: first-route-dest/backend/1
endpoints:
- lbEndpoints:
- endpoint:
address:
socketAddress:
address: 2.2.2.2
portValue: 50002
loadBalancingWeight: 1
loadBalancingWeight: 20
locality:
region: first-route-dest/backend/1
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
- address:
socketAddress:
address: '::'
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-10080
useRemoteAddress: true
name: first-listener
maxConnectionsToAcceptPerSocketEvent: 1
name: first-listener
perConnectionBufferLimitBytes: 32768
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
- ignorePortInHostMatching: true
name: first-listener
virtualHosts:
- domains:
- '*'
name: first-listener/*
routes:
- match:
prefix: /
name: first-route
route:
clusterNotFoundResponseCode: INTERNAL_SERVER_ERROR
hashPolicy:
- header:
headerName: x-user-id
upgradeConfigs:
- upgradeType: websocket
weightedClusters:
clusters:
- name: first-route-dest/backend/0
requestHeadersToAdd:
- appendAction: OVERWRITE_IF_EXISTS_OR_ADD
header:
key: x-backend
value: primary
weight: 80
- name: first-route-dest/backend/1
requestHeadersToAdd:
- appendAction: OVERWRITE_IF_EXISTS_OR_ADD
header:
key: x-backend
value: backup
weight: 20
useHashPolicy: true
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
clusters:
- name: route-with-weighted-zones-maglev-dest/backend/0
weight: 1
useHashPolicy: true
- match:
prefix: /
name: route-with-weighted-zones-backend-utilization
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed ConsistentHash load balancing not pinning a client to a single backend when a route splits traffic across multiple weighted backendRefs. Envoy Gateway now sets `use_hash_policy` on the generated weighted clusters when a ConsistentHash load balancer is configured, so the request's hash policy selects the weighted cluster deterministically instead of at random per request.
Loading