Skip to content

Commit 1e5bbb5

Browse files
authored
Dynamic forwarding load balancing policy (envoyproxy#38757)
Commit Message: Additional Description: Risk Level: Low, new extension Testing: Unit Tests Docs Changes: Yes Release Notes: Yes Platform Specific Features: N/A --------- Signed-off-by: Yan Avlasov <[email protected]>
1 parent b701b03 commit 1e5bbb5

File tree

21 files changed

+2352
-0
lines changed

21 files changed

+2352
-0
lines changed

CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ extensions/upstreams/tcp @ggreenway @mattklein123
338338
/*/extensions/load_balancing_policies/subset @wbpcode @zuercher @nezdolik
339339
/*/extensions/load_balancing_policies/cluster_provided @wbpcode @zuercher
340340
/*/extensions/load_balancing_policies/client_side_weighted_round_robin @wbpcode @adisuissa @efimki
341+
/*/extensions/load_balancing_policies/override_host @yanavlasov @tonya11en
341342
# Early header mutation
342343
/*/extensions/http/early_header_mutation/header_mutation @wbpcode @tyxia
343344
# Network matching extensions

api/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ proto_library(
293293
"//envoy/extensions/load_balancing_policies/common/v3:pkg",
294294
"//envoy/extensions/load_balancing_policies/least_request/v3:pkg",
295295
"//envoy/extensions/load_balancing_policies/maglev/v3:pkg",
296+
"//envoy/extensions/load_balancing_policies/override_host/v3:pkg",
296297
"//envoy/extensions/load_balancing_policies/pick_first/v3:pkg",
297298
"//envoy/extensions/load_balancing_policies/random/v3:pkg",
298299
"//envoy/extensions/load_balancing_policies/ring_hash/v3:pkg",
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# DO NOT EDIT. This file is generated by tools/proto_format/proto_sync.py.
2+
3+
load("@envoy_api//bazel:api_build_system.bzl", "api_proto_package")
4+
5+
licenses(["notice"]) # Apache 2
6+
7+
api_proto_package(
8+
deps = [
9+
"//envoy/config/cluster/v3:pkg",
10+
"//envoy/type/metadata/v3:pkg",
11+
"@com_github_cncf_xds//udpa/annotations:pkg",
12+
],
13+
)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
syntax = "proto3";
2+
3+
package envoy.extensions.load_balancing_policies.override_host.v3;
4+
5+
import "envoy/config/cluster/v3/cluster.proto";
6+
import "envoy/type/metadata/v3/metadata.proto";
7+
8+
import "udpa/annotations/status.proto";
9+
import "validate/validate.proto";
10+
11+
option java_package = "io.envoyproxy.envoy.extensions.load_balancing_policies.override_host.v3";
12+
option java_outer_classname = "OverrideHostProto";
13+
option java_multiple_files = true;
14+
option go_package = "github.com/envoyproxy/go-control-plane/envoy/extensions/load_balancing_policies/override_host/v3;override_hostv3";
15+
option (udpa.annotations.file_status).package_version_status = ACTIVE;
16+
17+
// [#protodoc-title: Override Host Load Balancing Policy]
18+
// [#extension: envoy.load_balancing_policies.override_host]
19+
20+
// Configuration for the Override Host Load Balancing policy.
21+
//
22+
// This policy allows endpoint picking to be implemented in an external to Envoy
23+
// component. For example an ext_proc RPC to a service that implements k8s proposal for AI gateway inferences extensions
24+
// https://github.com/kubernetes-sigs/gateway-api-inference-extension/tree/main/docs/proposals/004-endpoint-picker-protocol
25+
// can provide hosts for serving a request using Override Host load balancing policy.
26+
//
27+
// This policy uses selected endpoints from either request headers or request metadata.
28+
//
29+
// The primary host override source must specify a single ``IP:port`` value in either the header or the
30+
// metadata. For example ``10.0.0.5:8080`` or ``[2600:4040:5204::1574:24ae]:80``. The IPv6 address is enclosed in square brackets.
31+
//
32+
// For example, to support k8s gateway inference extensions, which uses the ``x-gateway-destination-endpoint`` header or metadata
33+
// value under the "envoy.lb" key for the primary endpoint, the Override Host load balancing policy should be configured in the
34+
// following way:
35+
//
36+
// .. code-block:: yaml
37+
//
38+
// override_host_sources:
39+
// - header: "x-gateway-destination-endpoint"
40+
// - metadata:
41+
// key: "envoy.lb"
42+
// path:
43+
// - key: "x-gateway-destination-endpoint"
44+
// - header: "x-gateway-fallback-endpoints"
45+
//
46+
// If neither header nor metadata is present, then the specified fallback load balancing policy is used. This allows load
47+
// balancing to degrade to a a built in policy (i.e. Round Robin) in case external endpoint picker fails.
48+
//
49+
// See the :ref:`load balancing architecture
50+
// overview<arch_overview_load_balancing_types>` for more information.
51+
//
52+
message OverrideHost {
53+
message OverrideHostSource {
54+
// The header to get the override host addresses. Only one of the header or metadata field must be set.
55+
string header = 1
56+
[(validate.rules).string = {well_known_regex: HTTP_HEADER_VALUE strict: false}];
57+
58+
// The metadata key to get the override host addresses from the request dynamic metadata. If
59+
// set this field then it will take precedence over the header field.
60+
// Only one of the header or metadata field must be set.
61+
type.metadata.v3.MetadataKey metadata = 2;
62+
}
63+
64+
// A list of sources to get host addresses from. The host sources are searched in the order
65+
// specified. The request is forwarded to the first address and subsequent addresses are used
66+
// for request retries or hedging.
67+
// Note that if an overridden host address is not present in the current endpoint set, it is
68+
// skipped and the next found address is used. If there are not enough overridden addresses to
69+
// satisfy all retry attempts the fallback load balancing policy is used to pick a host.
70+
repeated OverrideHostSource override_host_sources = 1
71+
[(validate.rules).repeated = {min_items: 1}];
72+
73+
// The child LB policy to use in case neither header nor metadata with selected
74+
// hosts is present.
75+
config.cluster.v3.LoadBalancingPolicy fallback_policy = 3
76+
[(validate.rules).message = {required: true}];
77+
}

api/versioning/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ proto_library(
231231
"//envoy/extensions/load_balancing_policies/common/v3:pkg",
232232
"//envoy/extensions/load_balancing_policies/least_request/v3:pkg",
233233
"//envoy/extensions/load_balancing_policies/maglev/v3:pkg",
234+
"//envoy/extensions/load_balancing_policies/override_host/v3:pkg",
234235
"//envoy/extensions/load_balancing_policies/pick_first/v3:pkg",
235236
"//envoy/extensions/load_balancing_policies/random/v3:pkg",
236237
"//envoy/extensions/load_balancing_policies/ring_hash/v3:pkg",

changelogs/current.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ removed_config_or_runtime:
9797
Removed runtime guard ``envoy.reloadable_features.lua_flow_control_while_http_call`` and legacy code paths.
9898
9999
new_features:
100+
- area: load_balancing
101+
change: |
102+
Added Override Host Load Balancing policy. See
103+
:ref:`load balancing policies overview <arch_overview_load_balancing_policies>` for more details.
100104
- area: lua
101105
change: |
102106
Added support for accessing filter context.

source/extensions/extensions_build_config.bzl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ EXTENSIONS = {
515515
"envoy.load_balancing_policies.subset": "//source/extensions/load_balancing_policies/subset:config",
516516
"envoy.load_balancing_policies.cluster_provided": "//source/extensions/load_balancing_policies/cluster_provided:config",
517517
"envoy.load_balancing_policies.client_side_weighted_round_robin": "//source/extensions/load_balancing_policies/client_side_weighted_round_robin:config",
518+
"envoy.load_balancing_policies.override_host": "//source/extensions/load_balancing_policies/override_host:config",
518519

519520
#
520521
# HTTP Early Header Mutation

source/extensions/extensions_metadata.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,6 +1743,13 @@ envoy.load_balancing_policies.client_side_weighted_round_robin:
17431743
status: alpha
17441744
type_urls:
17451745
- envoy.extensions.load_balancing_policies.client_side_weighted_round_robin.v3.ClientSideWeightedRoundRobin
1746+
envoy.load_balancing_policies.override_host:
1747+
categories:
1748+
- envoy.load_balancing_policies
1749+
security_posture: unknown
1750+
status: alpha
1751+
type_urls:
1752+
- envoy.extensions.load_balancing_policies.override_host.v3.OverrideHost
17461753
envoy.http.early_header_mutation.header_mutation:
17471754
categories:
17481755
- envoy.http.early_header_mutation
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
load(
2+
"//bazel:envoy_build_system.bzl",
3+
"envoy_cc_extension",
4+
"envoy_cc_library",
5+
"envoy_extension_package",
6+
)
7+
8+
licenses(["notice"]) # Apache 2
9+
10+
envoy_extension_package()
11+
12+
envoy_cc_extension(
13+
name = "config",
14+
srcs = ["config.cc"],
15+
hdrs = ["config.h"],
16+
deps = [
17+
":load_balancer",
18+
"//envoy/common:exception_lib",
19+
"//envoy/common:optref_lib",
20+
"//envoy/common:random_generator_interface",
21+
"//envoy/common:time_interface",
22+
"//envoy/registry",
23+
"//envoy/runtime:runtime_interface",
24+
"//envoy/server:factory_context_interface",
25+
"//envoy/upstream:load_balancer_interface",
26+
"//envoy/upstream:upstream_interface",
27+
"//source/common/protobuf",
28+
"//source/common/protobuf:utility_lib_header",
29+
"//source/common/upstream:load_balancer_factory_base_lib",
30+
"@com_google_absl//absl/log:check",
31+
"@com_google_absl//absl/status:statusor",
32+
"@envoy_api//envoy/extensions/load_balancing_policies/override_host/v3:pkg_cc_proto",
33+
],
34+
)
35+
36+
envoy_cc_library(
37+
name = "load_balancer",
38+
srcs = ["load_balancer.cc"],
39+
hdrs = ["load_balancer.h"],
40+
deps = [
41+
":override_host_filter_state",
42+
"//envoy/common:exception_lib",
43+
"//envoy/common:optref_lib",
44+
"//envoy/common:random_generator_interface",
45+
"//envoy/common:time_interface",
46+
"//envoy/http:header_map_interface",
47+
"//envoy/runtime:runtime_interface",
48+
"//envoy/upstream:load_balancer_interface",
49+
"//envoy/upstream:upstream_interface",
50+
"//source/common/common:assert_lib",
51+
"//source/common/common:minimal_logger_lib",
52+
"//source/common/common:thread_lib",
53+
"//source/common/config:metadata_lib",
54+
"//source/common/config:utility_lib",
55+
"//source/common/protobuf",
56+
"@com_google_absl//absl/container:inlined_vector",
57+
"@com_google_absl//absl/log:check",
58+
"@com_google_absl//absl/status",
59+
"@com_google_absl//absl/status:statusor",
60+
"@com_google_absl//absl/strings",
61+
"@com_google_absl//absl/types:optional",
62+
"@envoy_api//envoy/config/core/v3:pkg_cc_proto",
63+
"@envoy_api//envoy/extensions/load_balancing_policies/override_host/v3:pkg_cc_proto",
64+
],
65+
)
66+
67+
envoy_cc_library(
68+
name = "least_request_lb_lib",
69+
srcs = ["least_request_lb.cc"],
70+
hdrs = ["least_request_lb.h"],
71+
deps = ["//source/extensions/load_balancing_policies/common:load_balancer_lib"],
72+
)
73+
74+
envoy_cc_library(
75+
name = "override_host_filter_state",
76+
hdrs = ["override_host_filter_state.h"],
77+
deps = [
78+
"//envoy/stream_info:filter_state_interface",
79+
],
80+
)
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#include "source/extensions/load_balancing_policies/override_host/config.h"
2+
3+
#include <memory>
4+
#include <utility>
5+
6+
#include "envoy/common/exception.h"
7+
#include "envoy/common/optref.h"
8+
#include "envoy/extensions/load_balancing_policies/override_host/v3/override_host.pb.h"
9+
#include "envoy/extensions/load_balancing_policies/override_host/v3/override_host.pb.validate.h"
10+
#include "envoy/registry/registry.h"
11+
#include "envoy/server/factory_context.h"
12+
#include "envoy/upstream/load_balancer.h"
13+
14+
#include "source/common/protobuf/protobuf.h"
15+
#include "source/common/protobuf/utility.h"
16+
#include "source/extensions/load_balancing_policies/override_host/load_balancer.h"
17+
18+
namespace Envoy {
19+
namespace Extensions {
20+
namespace LoadBalancingPolices {
21+
namespace OverrideHost {
22+
23+
using ::envoy::extensions::load_balancing_policies::override_host::v3::OverrideHost;
24+
25+
absl::StatusOr<Upstream::LoadBalancerConfigPtr>
26+
OverrideHostLoadBalancerFactory::loadConfig(Server::Configuration::ServerFactoryContext& context,
27+
const Protobuf::Message& config) {
28+
const OverrideHost& override_host_config = MessageUtil::downcastAndValidate<const OverrideHost&>(
29+
config, context.messageValidationVisitor());
30+
// Enforced in config validation.
31+
ASSERT(override_host_config.has_fallback_policy());
32+
return OverrideHostLbConfig::make(override_host_config, context);
33+
}
34+
35+
Upstream::ThreadAwareLoadBalancerPtr
36+
OverrideHostLoadBalancerFactory::create(OptRef<const Upstream::LoadBalancerConfig> lb_config,
37+
const ClusterInfo& cluster_info,
38+
const PrioritySet& priority_set, Loader& runtime,
39+
RandomGenerator& random, TimeSource& time_source) {
40+
ASSERT(lb_config.has_value()); // Factory can not work without config.
41+
const auto& override_host_lb_config = dynamic_cast<const OverrideHostLbConfig&>(lb_config.ref());
42+
Upstream::ThreadAwareLoadBalancerPtr locality_picker_lb =
43+
override_host_lb_config.create(cluster_info, priority_set, runtime, random, time_source);
44+
ASSERT(locality_picker_lb != nullptr); // Factory can not create null LB.
45+
return std::make_unique<OverrideHostLoadBalancer>(override_host_lb_config,
46+
std::move(locality_picker_lb));
47+
}
48+
49+
REGISTER_FACTORY(OverrideHostLoadBalancerFactory, Upstream::TypedLoadBalancerFactory);
50+
51+
} // namespace OverrideHost
52+
} // namespace LoadBalancingPolices
53+
} // namespace Extensions
54+
} // namespace Envoy

0 commit comments

Comments
 (0)