资讯动态

Envoy Local Address Selectors 本地地址选择器实战:从默认 IPv4/IPv6 绑定到 Linux 网络命名空间覆盖

发布时间:2026/9/12 19:22:58 来源:尧图企业网站定制
Envoy Local Address Selectors 本地地址选择器实战从默认 IPv4/IPv6 绑定到 Linux 网络命名空间覆盖【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy导读本文围绕 Envoy 的 Local Address Selectors本地地址选择器机制展开系统讲解上游连接绑定源地址的选择逻辑默认情况下如何根据目标主机 IP 版本在多个候选源地址间做选择以及如何通过 filter_state_override 扩展基于下游共享的 Filter State 覆盖上游连接的 Linux 网络命名空间。读完本文你将掌握BindConfig.local_address_selector的配置方式、envoy.upstream.local_address_selector.default_local_address_selector与envoy.upstream.local_address_selector.filter_state_override两个扩展的工作原理并能独立编写出可在真实集群中运行的配置示例。一、什么是 Local Address Selectors在 Envoy 中当集群向上游发起连接时除了目标地址之外还需要确定从哪个本地源地址发出连接。这一决策由 Cluster 的 upstream bind config绑定配置驱动BindConfig可以声明source_address主源地址和extra_source_addresses额外源地址列表而具体选择哪一个地址、何时选择则由Local Address Selector本地地址选择器决定。Local Address Selectors 是一个可扩展点extension categoryenvoy.upstream.local_address_selector它通过BindConfig.local_address_selector字段以 TypedExtensionConfig 的方式注入。如果不配置该字段Envoy 使用内置的默认实现DefaultLocalAddressSelector如果需要更复杂的绑定逻辑例如基于 Filter State 动态覆盖网络命名空间则可以替换为其他实现例如本文重点讲解的filter_state_override。二、默认本地地址选择器DefaultLocalAddressSelector2.1 定义与语义默认实现定义在 default_local_address_selector.proto扩展名nameenvoy.upstream.local_address_selector.default_local_address_selector消息类型envoy.config.upstream.local_address_selector.v3.DefaultLocalAddressSelector空消息无需任何配置字段生效条件当BindConfig未指定local_address_selector字段时自动使用2.2 地址选择规则按照 proto 注释与源码实现默认选择器的规则如下extra_source_addresses中只能指定一个额外地址该地址会被追加到source_address之后共同构成候选源地址列表额外地址的 IP 版本必须与source_address的 IP 版本不同典型用法是同时提供 IPv4 与 IPv6 两个绑定地址建立连接时选择器比较目标主机地址的 IP 版本返回与目标 IP 版本相同的候选地址作为绑定地址如果找不到同 IP 版本的候选地址则回退返回source_address中的地址。对应的核心实现在 default_local_address_selector.ccUpstreamLocalAddress DefaultUpstreamLocalAddressSelector::getUpstreamLocalAddressImpl( const Network::Address::InstanceConstSharedPtr endpoint_address, OptRefconst Network::TransportSocketOptions) const { for (auto local_address : upstream_local_addresses_) { if (local_address.address_ nullptr) { continue; } ASSERT(local_address.address_-ip() ! nullptr); if (endpoint_address-ip() ! nullptr local_address.address_-ip()-version() endpoint_address-ip()-version()) { return local_address; } } return upstream_local_addresses_[0]; }从源码可以看到选择器逐个遍历候选地址跳过空地址命中 IP 版本匹配即返回全部未命中时回退到列表第一个地址即source_address。这正是按 IP 版本就近选择语义的实现证据。2.3 工厂注册默认选择器通过标准工厂机制注册见 default_local_address_selector_factory.cc工厂的name()返回envoy.upstream.local_address_selector.default_local_address_selectorcreateLocalAddressSelector接收解析后的候选地址列表并构造DefaultUpstreamLocalAddressSelector实例。三、Filter State Override按下游状态覆盖网络命名空间3.1 扩展总览filter_state_override是local_address_selector类别下的第二个扩展定义在 config.proto扩展名nameenvoy.upstream.local_address_selector.filter_state_override消息类型envoy.extensions.local_address_selectors.filter_state_override.v3.Config同样为空消息能力通过下游传递的 Filter State 对象覆盖上游连接绑定的 Linux 网络命名空间作用方式该扩展不是替代默认选择器而是对默认选择器结果的叠加覆盖——它在内部委托给默认选择器仅在满足条件时改写地址3.2 底层实现剖析核心实现在 filter_state_override/config.cc。实现类NamespaceLocalAddressSelector包装decorate了一个内部选择器inner关键逻辑如下Upstream::UpstreamLocalAddress getUpstreamLocalAddress( const Network::Address::InstanceConstSharedPtr endpoint_address, const Network::ConnectionSocket::OptionsSharedPtr socket_options, OptRefconst Network::TransportSocketOptions transport_socket_options) const override { const auto upstream_address inner_-getUpstreamLocalAddress(endpoint_address, socket_options, transport_socket_options); if (transport_socket_options upstream_address.address_) { const auto data getObjectAsString(transport_socket_options-downstreamSharedFilterStateObjects(), envoy.network.upstream_bind_override.network_namespace); if (data.has_value()) { const auto new_address upstream_address.address_-withNetworkNamespace(*data); if (new_address) { return {.address_ new_address, .socket_options_ upstream_address.socket_options_}; } } else { ENVOY_LOG(trace, Failed to serialize filter state as string); } } return upstream_address; }从源码可以提炼出完整的工作流程先调用内部选择器默认为default_local_address_selector获得基础绑定地址检查连接是否存在 Transport Socket Options并尝试从下游共享的 Filter State 对象中按 keyenvoy.network.upstream_bind_override.network_namespace读取字符串数据若读到该 key则调用withNetworkNamespace将基础绑定地址的网络命名空间替换为 Filter State 中指定的命名空间文件路径若 Filter State 缺失或改写失败则回退使用基础地址不改变原有行为。工厂NamespaceLocalAddressSelectorFactory::createLocalAddressSelector在 config.cc 中通过注册表显式获取默认选择器工厂先构建默认选择器再用NamespaceLocalAddressSelector将其包装后返回最后通过REGISTER_FACTORY注册为envoy.upstream.local_address_selector类别下的工厂。3.3 涉及的 Filter State 键根据 well_known_filter_state.rst本扩展涉及两个 Filter State 键envoy.network.network_namespace保存下游连接所处的 Linux 网络命名空间当与默认命名空间不同时才有值envoy.network.upstream_bind_override.network_namespace用于覆盖上游连接的网络命名空间。其序列化值为网络命名空间文件路径空字符串表示清除网络命名空间该对象需要由下游过滤器共享给上游连接使用。值得注意的是Filter State 对象需要具备可序列化能力serializeAsString命名空间文件路径正是通过字符串序列化传递的见 config.cc 中的getObjectAsString辅助函数。四、BindConfig 中的挂载点与校验4.1 local_address_selector 字段BindConfig.local_address_selector定义在 address.proto类型为TypedExtensionConfig标注了扩展类别envoy.upstream.local_address_selector。同一个 proto 中还定义了与本主题强相关的字段字段作用source_address主源地址必选语义由配置校验保证freebind是否启用IP_FREEBIND允许绑定系统上不存在的 IPextra_source_addresses额外源地址列表供 local address selector 选择local_address_selector自定义本地地址选择器扩展配置validate_network_namespaces加载配置时是否立即校验网络命名空间文件路径是否存在4.2 配置校验逻辑在 upstream_impl.cc 的createUpstreamLocalAddressSelector中Cluster 会先确定生效的 BindConfig优先使用 cluster 自身的upstream_bind_config否则回退到 bootstrap 级别的 bind config随后执行一系列校验additional_source_addresses已废弃字段与extra_source_addresses不能同时指定指定了 extra/additional 源地址但未设置source_address时会报错非 Linux 平台上若绑定配置包含带网络命名空间文件路径的地址会直接报错网络命名空间仅 Linux 可用。从 address.proto 可知validate_network_namespaces的语义默认不校验允许配置加载时尚不存在、后续才创建的命名空间连接时若命名空间不可用则优雅失败而 Listener 的地址会在配置加载时立即绑定因此无等价选项。需要特别注意的是网络命名空间特性仅 Linux 生效。4.3 选择器在连接建立阶段的调用位置连接建立时HostImplBase::createConnection会通过cluster.getUpstreamLocalAddressSelector()获取集群级选择器并在创建客户端连接前调用getUpstreamLocalAddress确定绑定地址见 upstream_impl.cc。对于多地址场景sorted_address_list数量大于 1选择器还会被传入HappyEyeballsConnectionImpl供 Happy Eyeballs 逐地址尝试时复用。此外createClientConnection可能因绑定网络命名空间失败例如命名空间运行时被删除返回空指针调用方连接池会将其视为连接失败而非崩溃——这与上文优雅失败的设计相互印证。五、端到端配置示例5.1 场景一IPv4/IPv6 双栈源地址选择利用默认选择器按 IP 版本匹配的特性配置一个同时具备 IPv4、IPv6 源地址的集群绑定static_resources: clusters: - name: dual_stack_upstream connect_timeout: 1s type: STRICT_DNS lb_policy: ROUND_ROBIN load_assignment: cluster_name: dual_stack_upstream endpoints: - lb_endpoints: - endpoint: address: socket_address: address: backend.example.com port_value: 443 upstream_bind_config: source_address: address: 192.0.2.10 port_value: 0 extra_source_addresses: - address: socket_address: address: 2001:db8::10 port_value: 0 # local_address_selector 不配置时默认使用 # envoy.upstream.local_address_selector.default_local_address_selector上述配置中Envoy 访问 IPv4 目标时绑定192.0.2.10访问 IPv6 目标时绑定2001:db8::10若目标解析出的地址与两个候选版本都不匹配则回退到source_address。该行为由默认选择器源码逐版本匹配的逻辑保证。5.2 场景二显式声明默认选择器若希望配置意图更加明确可以显式挂载默认选择器upstream_bind_config: source_address: address: 192.0.2.10 port_value: 0 local_address_selector: name: envoy.upstream.local_address_selector.default_local_address_selector typed_config: type: type.googleapis.com/envoy.config.upstream.local_address_selector.v3.DefaultLocalAddressSelectorDefaultLocalAddressSelector是空消息因此typed_config只需指定类型即可无需任何业务字段。5.3 场景三按 Filter State 动态覆盖网络命名空间将集群的本地地址选择器替换为filter_state_override扩展使上游连接可以跟随下游共享的网络命名空间static_resources: clusters: - name: ns_aware_upstream connect_timeout: 1s type: STRICT_DNS load_assignment: cluster_name: ns_aware_upstream endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 10.0.0.1 port_value: 443 upstream_bind_config: source_address: address: 172.16.0.10 port_value: 0 local_address_selector: name: envoy.upstream.local_address_selector.filter_state_override typed_config: type: type.googleapis.com/envoy.extensions.local_address_selectors.filter_state_override.v3.Config配合该配置下游过滤器filter需要在处理请求时创建并共享如下 Filter State 对象keyenvoy.network.upstream_bind_override.network_namespace值序列化为目标网络命名空间的文件路径例如/var/run/netns/custom空字符串表示清除覆盖回到默认绑定。实现上该对象须通过TransportSocketOptions::downstreamSharedFilterStateObjects传递到上游连接的建立路径中扩展的NamespaceLocalAddressSelector会读取它并对默认选择器计算出的地址调用withNetworkNamespace完成改写参见 config.cc。若读取或改写失败连接按原有默认地址继续保证扩展失败不影响可用性。六、在 Envoy 源码中的完整足迹便于继续深入以下是本主题在仓库中的主要落点扩展 proto 定义config.proto默认选择器 proto 定义default_local_address_selector.proto挂载点与校验字段address.proto默认选择器实现default_local_address_selector.cc、default_local_address_selector_factory.ccfilter_state_override 扩展实现config.cc集群侧选择器创建与连接调用upstream_impl.cc、upstream_impl.cc扩展注册信息extensions_build_config.bzl、extensions_metadata.yaml相关 Filter State 键说明well_known_filter_state.rst七、使用注意事项平台限制网络命名空间覆盖仅 Linux 有效其他平台配置了带命名空间文件路径的绑定地址会被直接拒绝见 upstream_impl.cc扩展顺序filter_state_override内部强制依赖默认选择器工厂两者应视为组合使用关系而非互斥替代校验开关生产环境如需尽早暴露命名空间路径错误可开启validate_network_namespaces默认关闭以便支持先配置、后创建的命名空间Filter State 可序列化只有可序列化的 Filter State 对象才能被扩展读取无法序列化时扩展仅记录 trace 日志并回退默认地址回退语义无论 Filter State 缺失、序列化失败还是命名空间绑定失败扩展与连接层都保证优雅回退不导致进程崩溃。【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价