istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/networking/core/cluster_traffic_policy.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package core 16 17 import ( 18 "math" 19 20 cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" 21 core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" 22 proxyprotocol "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/proxy_protocol/v3" 23 http "github.com/envoyproxy/go-control-plane/envoy/extensions/upstreams/http/v3" 24 xdstype "github.com/envoyproxy/go-control-plane/envoy/type/v3" 25 "google.golang.org/protobuf/proto" 26 "google.golang.org/protobuf/types/known/durationpb" 27 "google.golang.org/protobuf/types/known/wrapperspb" 28 29 meshconfig "istio.io/api/mesh/v1alpha1" 30 networking "istio.io/api/networking/v1alpha3" 31 "istio.io/istio/pilot/pkg/features" 32 "istio.io/istio/pilot/pkg/model" 33 "istio.io/istio/pilot/pkg/networking/core/loadbalancer" 34 "istio.io/istio/pilot/pkg/util/protoconv" 35 "istio.io/istio/pkg/config/protocol" 36 "istio.io/istio/pkg/log" 37 ) 38 39 // applyTrafficPolicy applies the trafficPolicy defined within destinationRule, 40 // which can be called for both outbound and inbound cluster, but only connection pool will be applied to inbound cluster. 41 func (cb *ClusterBuilder) applyTrafficPolicy(opts buildClusterOpts) { 42 connectionPool, outlierDetection, loadBalancer, tls, proxyProtocol := selectTrafficPolicyComponents(opts.policy) 43 // Connection pool settings are applicable for both inbound and outbound clusters. 44 if connectionPool == nil { 45 connectionPool = &networking.ConnectionPoolSettings{} 46 } 47 cb.applyConnectionPool(opts.mesh, opts.mutable, connectionPool) 48 if opts.direction != model.TrafficDirectionInbound { 49 cb.applyH2Upgrade(opts.mutable, opts.port, opts.mesh, connectionPool) 50 applyOutlierDetection(opts.mutable.cluster, outlierDetection) 51 applyLoadBalancer(opts.mutable.cluster, loadBalancer, opts.port, cb.locality, cb.proxyLabels, opts.mesh) 52 if opts.clusterMode != SniDnatClusterMode { 53 autoMTLSEnabled := opts.mesh.GetEnableAutoMtls().Value 54 tls, mtlsCtxType := cb.buildUpstreamTLSSettings(tls, opts.serviceAccounts, opts.istioMtlsSni, 55 autoMTLSEnabled, opts.meshExternal, opts.serviceMTLSMode) 56 cb.applyUpstreamTLSSettings(&opts, tls, mtlsCtxType) 57 cb.applyUpstreamProxyProtocol(&opts, proxyProtocol) 58 } 59 } 60 61 if opts.mutable.cluster.GetType() == cluster.Cluster_ORIGINAL_DST { 62 opts.mutable.cluster.LbPolicy = cluster.Cluster_CLUSTER_PROVIDED 63 } 64 } 65 66 // selectTrafficPolicyComponents returns the components of TrafficPolicy that should be used for given port. 67 func selectTrafficPolicyComponents(policy *networking.TrafficPolicy) ( 68 *networking.ConnectionPoolSettings, 69 *networking.OutlierDetection, 70 *networking.LoadBalancerSettings, 71 *networking.ClientTLSSettings, 72 *networking.TrafficPolicy_ProxyProtocol, 73 ) { 74 if policy == nil { 75 return nil, nil, nil, nil, nil 76 } 77 connectionPool := policy.ConnectionPool 78 outlierDetection := policy.OutlierDetection 79 loadBalancer := policy.LoadBalancer 80 tls := policy.Tls 81 proxyProtocol := policy.ProxyProtocol 82 83 // Check if CA Certificate should be System CA Certificate 84 if features.VerifyCertAtClient && tls != nil && tls.CaCertificates == "" { 85 tls.CaCertificates = "system" 86 } 87 88 return connectionPool, outlierDetection, loadBalancer, tls, proxyProtocol 89 } 90 91 // FIXME: there isn't a way to distinguish between unset values and zero values 92 func (cb *ClusterBuilder) applyConnectionPool(mesh *meshconfig.MeshConfig, 93 mc *clusterWrapper, settings *networking.ConnectionPoolSettings, 94 ) { 95 if settings == nil { 96 return 97 } 98 99 threshold := getDefaultCircuitBreakerThresholds() 100 var idleTimeout *durationpb.Duration 101 var maxRequestsPerConnection uint32 102 var maxConcurrentStreams uint32 103 var maxConnectionDuration *durationpb.Duration 104 105 if settings.Http != nil { 106 if settings.Http.Http2MaxRequests > 0 { 107 // Envoy only applies MaxRequests in HTTP/2 clusters 108 threshold.MaxRequests = &wrapperspb.UInt32Value{Value: uint32(settings.Http.Http2MaxRequests)} 109 } 110 if settings.Http.Http1MaxPendingRequests > 0 { 111 // Envoy only applies MaxPendingRequests in HTTP/1.1 clusters 112 threshold.MaxPendingRequests = &wrapperspb.UInt32Value{Value: uint32(settings.Http.Http1MaxPendingRequests)} 113 } 114 115 // FIXME: zero is a valid value if explicitly set, otherwise we want to use the default 116 if settings.Http.MaxRetries > 0 { 117 threshold.MaxRetries = &wrapperspb.UInt32Value{Value: uint32(settings.Http.MaxRetries)} 118 } 119 120 idleTimeout = settings.Http.IdleTimeout 121 maxRequestsPerConnection = uint32(settings.Http.MaxRequestsPerConnection) 122 maxConcurrentStreams = uint32(settings.Http.MaxConcurrentStreams) 123 } 124 125 cb.applyDefaultConnectionPool(mc.cluster) 126 if settings.Tcp != nil { 127 if settings.Tcp.ConnectTimeout != nil { 128 mc.cluster.ConnectTimeout = settings.Tcp.ConnectTimeout 129 } 130 131 if settings.Tcp.MaxConnections > 0 { 132 threshold.MaxConnections = &wrapperspb.UInt32Value{Value: uint32(settings.Tcp.MaxConnections)} 133 } 134 if settings.Tcp.MaxConnectionDuration != nil { 135 maxConnectionDuration = settings.Tcp.MaxConnectionDuration 136 } 137 if idleTimeout == nil { 138 idleTimeout = settings.Tcp.IdleTimeout 139 } 140 } 141 applyTCPKeepalive(mesh, mc.cluster, settings.Tcp) 142 143 mc.cluster.CircuitBreakers = &cluster.CircuitBreakers{ 144 Thresholds: []*cluster.CircuitBreakers_Thresholds{threshold}, 145 } 146 147 if maxConnectionDuration != nil || idleTimeout != nil || maxRequestsPerConnection > 0 || maxConcurrentStreams > 0 { 148 if mc.httpProtocolOptions == nil { 149 mc.httpProtocolOptions = &http.HttpProtocolOptions{} 150 } 151 options := mc.httpProtocolOptions 152 if options.CommonHttpProtocolOptions == nil { 153 options.CommonHttpProtocolOptions = &core.HttpProtocolOptions{} 154 } 155 if idleTimeout != nil { 156 idleTimeoutDuration := idleTimeout 157 options.CommonHttpProtocolOptions.IdleTimeout = idleTimeoutDuration 158 } 159 if maxRequestsPerConnection > 0 { 160 options.CommonHttpProtocolOptions.MaxRequestsPerConnection = &wrapperspb.UInt32Value{Value: maxRequestsPerConnection} 161 } 162 if maxConnectionDuration != nil { 163 options.CommonHttpProtocolOptions.MaxConnectionDuration = maxConnectionDuration 164 } 165 // Check if cluster is HTTP2 166 http2ProtocolOptions := options.GetExplicitHttpConfig().GetHttp2ProtocolOptions() 167 if http2ProtocolOptions != nil && maxConcurrentStreams > 0 { 168 http2ProtocolOptions.MaxConcurrentStreams = &wrapperspb.UInt32Value{Value: maxConcurrentStreams} 169 } 170 } 171 if settings.Http != nil && settings.Http.UseClientProtocol { 172 // Use downstream protocol. If the incoming traffic use HTTP 1.1, the 173 // upstream cluster will use HTTP 1.1, if incoming traffic use HTTP2, 174 // the upstream cluster will use HTTP2. 175 cb.setUseDownstreamProtocol(mc) 176 } 177 } 178 179 // applyH2Upgrade function will upgrade cluster to http2 if specified by configuration. 180 // applyH2Upgrade can only be called for outbound cluster 181 func (cb *ClusterBuilder) applyH2Upgrade(mc *clusterWrapper, port *model.Port, 182 mesh *meshconfig.MeshConfig, connectionPool *networking.ConnectionPoolSettings, 183 ) { 184 if shouldH2Upgrade(mc.cluster.Name, port, mesh, connectionPool) { 185 setH2Options(mc) 186 } 187 } 188 189 // shouldH2Upgrade function returns true if the cluster should be upgraded to http2. 190 // shouldH2Upgrade can only be called for outbound cluster 191 func shouldH2Upgrade(clusterName string, port *model.Port, mesh *meshconfig.MeshConfig, 192 connectionPool *networking.ConnectionPoolSettings, 193 ) bool { 194 // TODO (mjog) 195 // Upgrade if tls.GetMode() == networking.TLSSettings_ISTIO_MUTUAL 196 if connectionPool != nil && connectionPool.Http != nil { 197 override := connectionPool.Http.H2UpgradePolicy 198 // If user wants an upgrade at destination rule/port level that means he is sure that 199 // it is a Http port - upgrade in such case. This is useful incase protocol sniffing is 200 // enabled and user wants to upgrade/preserve http protocol from client. 201 if override == networking.ConnectionPoolSettings_HTTPSettings_UPGRADE { 202 log.Debugf("Upgrading cluster: %v (%v %v)", clusterName, mesh.H2UpgradePolicy, override) 203 return true 204 } 205 if override == networking.ConnectionPoolSettings_HTTPSettings_DO_NOT_UPGRADE { 206 log.Debugf("Not upgrading cluster: %v (%v %v)", clusterName, mesh.H2UpgradePolicy, override) 207 return false 208 } 209 } 210 211 // Do not upgrade non-http ports. This also ensures that we are only upgrading 212 // named ports so that protocol sniffing does not interfere. Protocol sniffing 213 // uses downstream protocol. Therefore if the client upgrades connection to http2, 214 // the server will send h2 stream to the application,even though the application only 215 // supports http 1.1. 216 if port != nil && !port.Protocol.IsHTTP() { 217 return false 218 } 219 220 return mesh.H2UpgradePolicy == meshconfig.MeshConfig_UPGRADE 221 } 222 223 func (cb *ClusterBuilder) applyDefaultConnectionPool(cluster *cluster.Cluster) { 224 cluster.ConnectTimeout = proto.Clone(cb.req.Push.Mesh.ConnectTimeout).(*durationpb.Duration) 225 } 226 227 func applyLoadBalancer(c *cluster.Cluster, lb *networking.LoadBalancerSettings, port *model.Port, 228 locality *core.Locality, proxyLabels map[string]string, meshConfig *meshconfig.MeshConfig, 229 ) { 230 // Disable panic threshold when SendUnhealthyEndpoints is enabled as enabling it "may" send traffic to unready 231 // end points when load balancer is in panic mode. 232 if features.SendUnhealthyEndpoints.Load() { 233 c.CommonLbConfig.HealthyPanicThreshold = &xdstype.Percent{Value: 0} 234 } 235 localityLbSetting := loadbalancer.GetLocalityLbSetting(meshConfig.GetLocalityLbSetting(), lb.GetLocalityLbSetting()) 236 if localityLbSetting != nil { 237 c.CommonLbConfig.LocalityConfigSpecifier = &cluster.Cluster_CommonLbConfig_LocalityWeightedLbConfig_{ 238 LocalityWeightedLbConfig: &cluster.Cluster_CommonLbConfig_LocalityWeightedLbConfig{}, 239 } 240 } 241 // Use locality lb settings from load balancer settings if present, else use mesh wide locality lb settings 242 applyLocalityLoadBalancer(locality, proxyLabels, c, localityLbSetting) 243 244 if c.GetType() == cluster.Cluster_ORIGINAL_DST { 245 c.LbPolicy = cluster.Cluster_CLUSTER_PROVIDED 246 return 247 } 248 249 // Redis protocol must be defaulted with MAGLEV to benefit from client side sharding. 250 if features.EnableRedisFilter && port != nil && port.Protocol == protocol.Redis { 251 c.LbPolicy = cluster.Cluster_MAGLEV 252 return 253 } 254 255 // DO not do if else here. since lb.GetSimple returns a enum value (not pointer). 256 switch lb.GetSimple() { 257 // nolint: staticcheck 258 case networking.LoadBalancerSettings_LEAST_CONN, networking.LoadBalancerSettings_LEAST_REQUEST: 259 applyLeastRequestLoadBalancer(c, lb) 260 case networking.LoadBalancerSettings_RANDOM: 261 c.LbPolicy = cluster.Cluster_RANDOM 262 case networking.LoadBalancerSettings_ROUND_ROBIN: 263 applyRoundRobinLoadBalancer(c, lb) 264 case networking.LoadBalancerSettings_PASSTHROUGH: 265 c.LbPolicy = cluster.Cluster_CLUSTER_PROVIDED 266 c.ClusterDiscoveryType = &cluster.Cluster_Type{Type: cluster.Cluster_ORIGINAL_DST} 267 // Wipe out any LoadAssignment, if set. This can occur when we have a STATIC Service but PASSTHROUGH traffic policy 268 c.LoadAssignment = nil 269 default: 270 applySimpleDefaultLoadBalancer(c, lb) 271 } 272 273 ApplyRingHashLoadBalancer(c, lb) 274 } 275 276 func applyLocalityLoadBalancer(locality *core.Locality, proxyLabels map[string]string, cluster *cluster.Cluster, 277 localityLB *networking.LocalityLoadBalancerSetting, 278 ) { 279 // Failover should only be applied with outlier detection, or traffic will never failover. 280 enableFailover := cluster.OutlierDetection != nil 281 if cluster.LoadAssignment != nil { 282 // TODO: enable failoverPriority for `STRICT_DNS` cluster type 283 loadbalancer.ApplyLocalityLoadBalancer(cluster.LoadAssignment, nil, locality, proxyLabels, localityLB, enableFailover) 284 } 285 } 286 287 // applySimpleDefaultLoadBalancer will set the DefaultLBPolicy and create an LbConfig if used in LoadBalancerSettings 288 func applySimpleDefaultLoadBalancer(c *cluster.Cluster, loadbalancer *networking.LoadBalancerSettings) { 289 c.LbPolicy = defaultLBAlgorithm() 290 switch c.LbPolicy { 291 case cluster.Cluster_ROUND_ROBIN: 292 applyRoundRobinLoadBalancer(c, loadbalancer) 293 case cluster.Cluster_LEAST_REQUEST: 294 applyLeastRequestLoadBalancer(c, loadbalancer) 295 } 296 } 297 298 func defaultLBAlgorithm() cluster.Cluster_LbPolicy { 299 return cluster.Cluster_LEAST_REQUEST 300 } 301 302 // applyRoundRobinLoadBalancer will set the LbPolicy and create an LbConfig for ROUND_ROBIN if used in LoadBalancerSettings 303 func applyRoundRobinLoadBalancer(c *cluster.Cluster, loadbalancer *networking.LoadBalancerSettings) { 304 c.LbPolicy = cluster.Cluster_ROUND_ROBIN 305 306 if loadbalancer.GetWarmupDurationSecs() != nil { 307 c.LbConfig = &cluster.Cluster_RoundRobinLbConfig_{ 308 RoundRobinLbConfig: &cluster.Cluster_RoundRobinLbConfig{ 309 SlowStartConfig: setSlowStartConfig(loadbalancer.GetWarmupDurationSecs()), 310 }, 311 } 312 } 313 } 314 315 // applyLeastRequestLoadBalancer will set the LbPolicy and create an LbConfig for LEAST_REQUEST if used in LoadBalancerSettings 316 func applyLeastRequestLoadBalancer(c *cluster.Cluster, loadbalancer *networking.LoadBalancerSettings) { 317 c.LbPolicy = cluster.Cluster_LEAST_REQUEST 318 319 if loadbalancer.GetWarmupDurationSecs() != nil { 320 c.LbConfig = &cluster.Cluster_LeastRequestLbConfig_{ 321 LeastRequestLbConfig: &cluster.Cluster_LeastRequestLbConfig{ 322 SlowStartConfig: setSlowStartConfig(loadbalancer.GetWarmupDurationSecs()), 323 }, 324 } 325 } 326 } 327 328 // setSlowStartConfig will set the warmupDurationSecs for LEAST_REQUEST and ROUND_ROBIN if provided in DestinationRule 329 func setSlowStartConfig(dur *durationpb.Duration) *cluster.Cluster_SlowStartConfig { 330 return &cluster.Cluster_SlowStartConfig{ 331 SlowStartWindow: dur, 332 } 333 } 334 335 // getDefaultCircuitBreakerThresholds returns a copy of the default circuit breaker thresholds for the given traffic direction. 336 func getDefaultCircuitBreakerThresholds() *cluster.CircuitBreakers_Thresholds { 337 return &cluster.CircuitBreakers_Thresholds{ 338 // DefaultMaxRetries specifies the default for the Envoy circuit breaker parameter max_retries. This 339 // defines the maximum number of parallel retries a given Envoy will allow to the upstream cluster. Envoy defaults 340 // this value to 3, however that has shown to be insufficient during periods of pod churn (e.g. rolling updates), 341 // where multiple endpoints in a cluster are terminated. In these scenarios the circuit breaker can kick 342 // in before Pilot is able to deliver an updated endpoint list to Envoy, leading to client-facing 503s. 343 MaxRetries: &wrapperspb.UInt32Value{Value: math.MaxUint32}, 344 MaxRequests: &wrapperspb.UInt32Value{Value: math.MaxUint32}, 345 MaxConnections: &wrapperspb.UInt32Value{Value: math.MaxUint32}, 346 MaxPendingRequests: &wrapperspb.UInt32Value{Value: math.MaxUint32}, 347 TrackRemaining: true, 348 } 349 } 350 351 // FIXME: there isn't a way to distinguish between unset values and zero values 352 func applyOutlierDetection(c *cluster.Cluster, outlier *networking.OutlierDetection) { 353 if outlier == nil { 354 return 355 } 356 357 out := &cluster.OutlierDetection{} 358 359 // SuccessRate based outlier detection should be disabled. 360 out.EnforcingSuccessRate = &wrapperspb.UInt32Value{Value: 0} 361 362 if e := outlier.Consecutive_5XxErrors; e != nil { 363 v := e.GetValue() 364 365 out.Consecutive_5Xx = &wrapperspb.UInt32Value{Value: v} 366 367 if v > 0 { 368 v = 100 369 } 370 out.EnforcingConsecutive_5Xx = &wrapperspb.UInt32Value{Value: v} 371 } 372 if e := outlier.ConsecutiveGatewayErrors; e != nil { 373 v := e.GetValue() 374 375 out.ConsecutiveGatewayFailure = &wrapperspb.UInt32Value{Value: v} 376 377 if v > 0 { 378 v = 100 379 } 380 out.EnforcingConsecutiveGatewayFailure = &wrapperspb.UInt32Value{Value: v} 381 } 382 383 if outlier.Interval != nil { 384 out.Interval = outlier.Interval 385 } 386 if outlier.BaseEjectionTime != nil { 387 out.BaseEjectionTime = outlier.BaseEjectionTime 388 } 389 if outlier.MaxEjectionPercent > 0 { 390 out.MaxEjectionPercent = &wrapperspb.UInt32Value{Value: uint32(outlier.MaxEjectionPercent)} 391 } 392 393 if outlier.SplitExternalLocalOriginErrors { 394 out.SplitExternalLocalOriginErrors = true 395 if outlier.ConsecutiveLocalOriginFailures.GetValue() > 0 { 396 out.ConsecutiveLocalOriginFailure = &wrapperspb.UInt32Value{Value: outlier.ConsecutiveLocalOriginFailures.Value} 397 out.EnforcingConsecutiveLocalOriginFailure = &wrapperspb.UInt32Value{Value: 100} 398 } 399 // SuccessRate based outlier detection should be disabled. 400 out.EnforcingLocalOriginSuccessRate = &wrapperspb.UInt32Value{Value: 0} 401 } 402 403 c.OutlierDetection = out 404 405 // Disable panic threshold by default as its not typically applicable in k8s environments 406 // with few pods per service. 407 // To do so, set the healthy_panic_threshold field even if its value is 0 (defaults to 50 in Envoy). 408 // FIXME: we can't distinguish between it being unset or being explicitly set to 0 409 minHealthPercent := outlier.MinHealthPercent 410 if minHealthPercent >= 0 { 411 // When we are sending unhealthy endpoints, we should disable Panic Threshold. Otherwise 412 // Envoy will send traffic to "Unready" pods when the percentage of healthy hosts fall 413 // below minimum health percentage. 414 if features.SendUnhealthyEndpoints.Load() { 415 minHealthPercent = 0 416 } 417 c.CommonLbConfig.HealthyPanicThreshold = &xdstype.Percent{Value: float64(minHealthPercent)} 418 } 419 } 420 421 // ApplyRingHashLoadBalancer will set the LbPolicy and create an LbConfig for RING_HASH if used in LoadBalancerSettings 422 func ApplyRingHashLoadBalancer(c *cluster.Cluster, lb *networking.LoadBalancerSettings) { 423 consistentHash := lb.GetConsistentHash() 424 if consistentHash == nil { 425 return 426 } 427 428 switch { 429 case consistentHash.GetMaglev() != nil: 430 c.LbPolicy = cluster.Cluster_MAGLEV 431 if consistentHash.GetMaglev().TableSize != 0 { 432 c.LbConfig = &cluster.Cluster_MaglevLbConfig_{ 433 MaglevLbConfig: &cluster.Cluster_MaglevLbConfig{ 434 TableSize: &wrapperspb.UInt64Value{Value: consistentHash.GetMaglev().TableSize}, 435 }, 436 } 437 } 438 case consistentHash.GetRingHash() != nil: 439 c.LbPolicy = cluster.Cluster_RING_HASH 440 if consistentHash.GetRingHash().MinimumRingSize != 0 { 441 c.LbConfig = &cluster.Cluster_RingHashLbConfig_{ 442 RingHashLbConfig: &cluster.Cluster_RingHashLbConfig{ 443 MinimumRingSize: &wrapperspb.UInt64Value{Value: consistentHash.GetRingHash().MinimumRingSize}, 444 }, 445 } 446 } 447 default: 448 // Check the deprecated MinimumRingSize. 449 // TODO: MinimumRingSize is an int, and zero could potentially 450 // be a valid value unable to distinguish between set and unset 451 // case currently. 452 // 1024 is the default value for envoy. 453 minRingSize := &wrapperspb.UInt64Value{Value: 1024} 454 455 if consistentHash.MinimumRingSize != 0 { // nolint: staticcheck 456 minRingSize = &wrapperspb.UInt64Value{Value: consistentHash.GetMinimumRingSize()} // nolint: staticcheck 457 } 458 c.LbPolicy = cluster.Cluster_RING_HASH 459 c.LbConfig = &cluster.Cluster_RingHashLbConfig_{ 460 RingHashLbConfig: &cluster.Cluster_RingHashLbConfig{ 461 MinimumRingSize: minRingSize, 462 }, 463 } 464 } 465 } 466 467 func (cb *ClusterBuilder) applyUpstreamProxyProtocol( 468 opts *buildClusterOpts, 469 proxyProtocol *networking.TrafficPolicy_ProxyProtocol, 470 ) { 471 if proxyProtocol == nil { 472 return 473 } 474 c := opts.mutable 475 if c.cluster.TransportSocket != nil { 476 // add an upstream proxy protocol wrapper for transportSocket 477 c.cluster.TransportSocket = &core.TransportSocket{ 478 Name: "envoy.transport_sockets.upstream_proxy_protocol", 479 ConfigType: &core.TransportSocket_TypedConfig{TypedConfig: protoconv.MessageToAny(&proxyprotocol.ProxyProtocolUpstreamTransport{ 480 Config: &core.ProxyProtocolConfig{Version: core.ProxyProtocolConfig_Version(proxyProtocol.Version)}, 481 TransportSocket: c.cluster.TransportSocket, 482 })}, 483 } 484 } 485 486 // add an upstream proxy protocol wrapper for each transportSocket 487 for _, tsm := range c.cluster.TransportSocketMatches { 488 tsm.TransportSocket = &core.TransportSocket{ 489 Name: "envoy.transport_sockets.upstream_proxy_protocol", 490 ConfigType: &core.TransportSocket_TypedConfig{TypedConfig: protoconv.MessageToAny(&proxyprotocol.ProxyProtocolUpstreamTransport{ 491 Config: &core.ProxyProtocolConfig{Version: core.ProxyProtocolConfig_Version(proxyProtocol.Version)}, 492 TransportSocket: tsm.TransportSocket, 493 })}, 494 } 495 } 496 }