Envoy Bootstrap 配置完全指南:静态与动态资源、xDS 接入与实战示例
【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy
导读
Envoy 的 Bootstrap(引导)配置是整个数据面的"启动配置文件",它既是 Envoy 进程启动时的唯一入口参数,也是接入 xDS 控制面的必经之路。本文基于 docs/root/configuration/overview/bootstrap.rst 展开,系统讲解 Bootstrap 配置的作用、-c命令行加载方式、Bootstrap消息中静态资源(static_resources)与动态资源(dynamic_resources)的核心区分,并结合仓库中的完整示例与源码实现,带你掌握从"全静态配置"到"全动态 xDS 配置"的完整演进路径,以及 ADS、Delta xDS、xDS TTL 等高级机制的使用方法。读完本文,你将能够独立编写可运行的 Envoy bootstrap 配置,并理解其底层加载与校验原理。
一、为什么需要 Bootstrap 配置
要使用 xDS API 动态下发配置,Envoy 必须首先通过一份 bootstrap 配置文件完成"自举"。这份文件承担两项职责(见 bootstrap.rst):
- 提供静态的服务器配置(管理接口、节点身份、静态资源等);
- 配置 Envoy 按需访问 xDS 管理服务器(即 动态配置架构 中描述的 dynamic configuration)。
这份配置通过命令行-c参数提供给 Envoy,扩展名决定了底层配置表示形式:
./envoy -c <path to config>.{json,yaml,pb,pb_text}json/yaml:文本格式,由 Envoy 通过 proto3 的 JSON/YAML 映射机械地转换为 protobuf 消息;pb:二进制 protobuf;pb_text:protobuf 文本格式。
在源码中,这个加载过程位于 source/server/server.cc 的InstanceUtil::loadBootstrapConfig()。它依次检查--config-path、--config-yaml与--config-proto三个来源,至少提供一个非空值,否则返回错误At least one of --config-path or --config-yaml or Options::configProto() should be non-empty。命令行参数本身定义在 source/server/options_impl.cc,其中-c/--config-path指向配置文件路径,--config-yaml允许以内联 YAML 的方式提供配置,并与--config-path的内容进行合并(bootstrap.MergeFrom(bootstrap_override))。
二、Bootstrap 消息:配置树的根
:ref:Bootstrap <envoy_v3_api_msg_config.bootstrap.v3.Bootstrap>消息是整个配置的根节点,其 proto 定义位于 api/envoy/config/bootstrap/v3/bootstrap.proto。理解这份消息的关键,在于静态资源与动态资源的区分:
Listener(监听器)和Cluster(集群)既可以静态地写在static_resources字段中;- 也可以通过 xDS 服务(如 LDS 或 CDS)在
dynamic_resources字段中配置动态发现。
2.1 StaticResources 静态资源
StaticResources子消息(bootstrap.proto)包含三个字段:
| 字段 | 类型 | 说明 |
|---|---|---|
listeners | repeated Listener | 静态监听器,无论 LDS 是否配置都始终可用 |
clusters | repeated Cluster | 静态集群;当cds_config使用基于网络的配置源时,必须在此提供初始集群,让 Envoy 知道如何与管理服务器通信 |
secrets | repeated Secret | 静态 TLS 密钥,可被SdsSecretConfig引用 |
其中clusters的注释点明了一个重要实践:即使采用全动态配置,也需要一个静态的xds_cluster指向管理服务器,这个集群是 Envoy 启动后与管理服务器建立连接的"引导通道"。
2.2 DynamicResources 动态资源
DynamicResources子消息(bootstrap.proto)包含:
| 字段 | 类型 | 说明 |
|---|---|---|
lds_config | ConfigSource | 所有 Listener 由单个 LDS 配置源提供 |
cds_config | ConfigSource | 所有启动后的 Cluster 由单个 CDS 配置源提供 |
ads_config | ApiConfigSource | 可选,单个 ADS 源;api_type必须为GRPC,只有设置了ads字段的 ConfigSource 才会在 ADS 通道上传输 |
此外还有lds_resources_locator/cds_resources_locator(xdstp://资源定位符,当前标注为[#not-implemented-hide:],属于预留能力)。
2.3 Bootstrap 的其它重要顶层字段
从 bootstrap.proto 可以看到 Bootstrap 消息还承载了大量服务器级配置:
node:节点身份,用于向管理服务器标识自身及实例识别(如生成头部中的标识);cluster_manager:集群管理器配置(4 号字段),拥有所有上游集群;hds_config:健康发现服务(HDS)配置;flags_path:启动标志文件的搜索路径;stats_sinks/stats_config:统计输出与内部统计处理配置;layered_runtime:分层运行时配置提供者,未指定时使用 "null" provider,即全部采用默认值;admin:本地管理 HTTP 服务器配置;overload_manager:过载管理器配置;enable_dispatcher_stats:是否启用事件分发器统计(默认false,启用后若使用 statsd 协议会产生大量数据);header_prefix:替换x-envoy头前缀的字符串(如设置为X-Foo,则x-envoy-retry-on变为x-foo-retry-on),核心代码与核心扩展生效,改动需极其谨慎;typed_dns_resolver_config:DNS 解析器类型扩展配置;bootstrap_extensions、fatal_actions、default_config_source、default_socket_interface、certificate_provider_instances、inline_headers、default_regex_engine、listener_manager等,构成可扩展的引导能力矩阵。
三、三种典型的 Bootstrap 配置形态
仓库在 docs/root/configuration/overview/examples.rst 中给出了从静态到动态的完整演进示例,统一以"代理 127.0.0.1:10000 到 127.0.0.1:1234 的 HTTP 服务"为运行场景。下面逐一展开(三个 YAML 示例均通过:type-name: envoy.config.bootstrap.v3.Bootstrap的校验,可直接复制使用)。
3.1 形态一:全静态配置(Static)
最小化的全静态 bootstrap 配置如下:
admin: address: socket_address: { address: 127.0.0.1, port_value: 9901 } static_resources: listeners: - name: listener_0 address: socket_address: { address: 127.0.0.1, port_value: 10000 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: some_service } http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: some_service connect_timeout: 0.25s type: STATIC lb_policy: ROUND_ROBIN load_assignment: cluster_name: some_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 1234要点拆解:
admin配置管理端口 9901,可通过curl http://127.0.0.1:9901/访问管理接口;- 监听器
listener_0绑定 10000 端口,网络过滤器链中注册了http_connection_manager(HCM); - HCM 通过
route_config内联定义了路由:域名["*"]匹配所有 Host,prefix: "/"匹配所有路径,转发到集群some_service; http_filters中必须包含envoy.filters.http.router过滤器,负责真正的请求转发,否则配置无效;- 集群
some_service为STATIC类型,connect_timeout: 0.25s设置连接超时,lb_policy: ROUND_ROBIN使用轮询负载均衡,load_assignment静态指定端点 127.0.0.1:1234。
这种形态下一切资源都在文件内定义,不涉及任何动态发现,适合单机演示与最小部署。
3.2 形态二:大部分静态 + 动态 EDS
继续上面的配置,将集群端点改为通过 EDS gRPC 管理服务器(监听 127.0.0.1:5678)动态发现:
admin: address: socket_address: { address: 127.0.0.1, port_value: 9901 } static_resources: listeners: - name: listener_0 address: socket_address: { address: 127.0.0.1, port_value: 10000 } filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: some_service } http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: some_service connect_timeout: 0.25s lb_policy: ROUND_ROBIN type: EDS eds_cluster_config: eds_config: api_config_source: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: xds_cluster - name: xds_cluster connect_timeout: 0.25s type: STATIC lb_policy: ROUND_ROBIN typed_extension_protocol_options: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: http2_protocol_options: connection_keepalive: interval: 30s timeout: 5s upstream_connection_options: # configure a TCP keep-alive to detect and reconnect to the admin # server in the event of a TCP socket half open connection tcp_keepalive: {} load_assignment: cluster_name: xds_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 5678这个例子揭示了两个关键实践:
- 引导集群必不可少:
xds_cluster是静态定义的,将 Envoy 指向管理服务器。即使配置完全动态化,也总需要一些静态资源来指向 xDS 管理服务器; - 连接健康保障:文档强调必须在
tcp_keepalive块中设置合适的 TCP Keep-Alive 选项,用于检测到管理服务器的 TCP 半开连接并重建完整连接;同时通过typed_extension_protocol_options配置 HTTP/2 的connection_keepalive(间隔 30s、超时 5s),在连接不再响应时及时重连。
此时 EDS 管理服务器可以返回如下DiscoveryResponse(version_info与@typetype URL 的版本化方案在 流式 gRPC 订阅协议 中有更详细说明):
version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment cluster_name: some_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 12343.3 形态三:全动态配置(Dynamic)
完全动态的 bootstrap 配置,除了管理服务器本身所属资源外,所有资源都通过 xDS 发现:
admin: address: socket_address: { address: 127.0.0.1, port_value: 9901 } dynamic_resources: lds_config: api_config_source: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: xds_cluster cds_config: api_config_source: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: xds_cluster static_resources: clusters: - name: xds_cluster connect_timeout: 0.25s type: STATIC lb_policy: ROUND_ROBIN typed_extension_protocol_options: envoy.extensions.upstreams.http.v3.HttpProtocolOptions: "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions explicit_http_config: http2_protocol_options: # Configure an HTTP/2 keep-alive to detect connection issues and reconnect # to the admin server if the connection is no longer responsive. connection_keepalive: interval: 30s timeout: 5s load_assignment: cluster_name: xds_cluster endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 5678管理服务器需要响应四类请求。LDS 请求可返回:
version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.listener.v3.Listener name: listener_0 address: socket_address: address: 127.0.0.1 port_value: 10000 filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO rds: route_config_name: local_route config_source: api_config_source: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: xds_cluster http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router注意这里 HCM 不再使用内联route_config,而是改用rds字段,将路由配置交给 RDS 动态发现。RDS 请求可返回:
version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: { prefix: "/" } route: { cluster: some_service }CDS 请求可返回:
version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster name: some_service connect_timeout: 0.25s lb_policy: ROUND_ROBIN type: EDS eds_cluster_config: eds_config: api_config_source: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: xds_clusterEDS 请求可返回(与前文相同):
version_info: "0" resources: - "@type": type.googleapis.com/envoy.config.endpoint.v3.ClusterLoadAssignment cluster_name: some_service endpoints: - lb_endpoints: - endpoint: address: socket_address: address: 127.0.0.1 port_value: 1234这就是一条完整的 xDS 链路:LDS → RDS → CDS → EDS,监听器、路由、集群、端点全部由管理服务器动态下发。
四、xDS API 端点与订阅形态
管理服务器需要实现 xds_api.rst 中描述的各端点。无论是流式 gRPC 还是 REST-JSON,都是客户端发送DiscoveryRequest、管理服务器返回DiscoveryResponse,遵循 xDS 协议。
4.1 gRPC 流式端点(v3 传输 API)
| 端点(POST) | 对应 proto | 触发配置位置 |
|---|---|---|
/envoy.service.cluster.v3.ClusterDiscoveryService/StreamClusters | api/envoy/service/cluster/v3/cds.proto | dynamic_resources.cds_config |
/envoy.service.endpoint.v3.EndpointDiscoveryService/StreamEndpoints | api/envoy/service/endpoint/v3/eds.proto | Cluster.eds_cluster_config.eds_config |
/envoy.service.listener.v3.ListenerDiscoveryService/StreamListeners | api/envoy/service/listener/v3/lds.proto | dynamic_resources.lds_config |
/envoy.service.route.v3.RouteDiscoveryService/StreamRoutes | api/envoy/service/route/v3/rds.proto | HttpConnectionManager.rds |
/envoy.service.route.v3.ScopedRoutesDiscoveryService/StreamScopedRoutes | api/envoy/service/route/v3/srds.proto | HttpConnectionManager.scoped_routes |
/envoy.service.secret.v3.SecretDiscoveryService/StreamSecrets | api/envoy/service/secret/v3/sds.proto | SdsSecretConfig(如CommonTlsContext中的引用) |
/envoy.service.runtime.v3.RuntimeDiscoveryService/StreamRuntime | api/envoy/service/runtime/v3/rtds.proto | Bootstrap.layered_runtime中的rtds_layer |
以 EDS 为例,在Cluster配置中设置如下内容即可触发 StreamEndpoints 调用:
eds_config: api_config_source: api_type: GRPC grpc_services: - envoy_grpc: cluster_name: some_xds_cluster仓库还提供了一个完整的动态资源示例 docs/root/configuration/overview/_include/xds_api/dynamic-resources.yaml,其中ads_config、cds_config、lds_config三块分别对应 ADS/CDS/LDS 的 gRPC 订阅配置,xds_cluster以STRICT_DNS类型指向控制面域名my-control-plane:18000。
4.2 REST 端点
REST-JSON 形态下端点统一为/v3/discovery:clusters、/v3/discovery:endpoints、/v3/discovery:listeners、/v3/discovery:routes,配置上使用api_type: REST与cluster_names列表。例如:
cds_config: api_config_source: api_type: REST cluster_names: [some_xds_cluster]注意:管理服务器响应这些端点时必须返回DiscoveryResponse且 HTTP 状态码为 200;若 Envoy 客户端携带的版本号表明配置未变化,管理服务器可以返回空 body 并附带 HTTP 304。
4.3 ADS:聚合发现服务
ADS 解决的是多流协调问题。Envoy 本质上采用最终一致性模型,而 ADS 提供了一次性排序 API 更新推送、并保证一个 Envoy 节点对单一管理服务器的亲和性。没有 ADS 时,CDS/EDS/RDS 流可能指向不同的管理服务器,或同一服务器上的不同 gRPC 流/连接,EDS 资源请求甚至会被拆到两个不同的流上;ADS 将它们合并到单一管理服务器的单一双向 gRPC 流上,无需分布式同步即可正确排序更新。
例如,要将foo.com从集群X改到集群Y,ADS 会在同一流上依次下发 CDS、EDS(先包含X和Y两个集群)、再下发 RDS,从而支持无中断(hitless)更新。
ADS 仅支持 gRPC 流式(不支持 REST),端点为:
/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources对应服务定义见 api/envoy/service/discovery/v3/discovery.proto。在dynamic_resources中设置ads_config(示例见 dynamic-resources.yaml 第 6-11 行)后,任何上述配置源都可以改用 ADS 通道,例如将 LDS 配置从:
lds_config: api_config_source: api_type: REST cluster_names: [some_xds_cluster]改为:
lds_config: {ads: {}}即可让 LDS 流经由共享的 ADS 通道指向some_ads_cluster。
4.4 Delta xDS:增量发现
REST、文件系统和原始 gRPC xDS 实现都采用"世界状态"(state-of-the-world,SotW)更新:每次 CDS 更新必须包含所有集群,某集群缺席即代表其已被删除。对于资源量巨大、且持续有小幅变动的部署,SotW 更新会非常笨重。
自 Envoy 1.12.0 起支持 xDS(包括 ADS)的delta(增量)变体,更新只包含新增/变更/删除的资源。要点:
- delta 是仅 gRPC的协议;
- 使用与 SotW 不同的请求/响应 proto(
DeltaDiscovery{Request,Response},见 discovery.proto); - 概念上 delta 是一种新的 xDS 传输类型:现有 static、filesystem、REST、gRPC-SotW,再加上 gRPC-delta;
- Envoy 的 gRPC-SotW/delta 客户端实现共享了大部分代码,但两者是互不兼容的协议。
使用方式非常简单:将ApiConfigSource的api_type字段设为DELTA_GRPC即可。对 xDS 和 ADS 都适用;对 ADS 而言,设置的是DynamicResources.ads_config中的api_type字段。
4.5 xDS TTL:资源临时生效与自动过期
当需要临时更新某些 xDS 资源时,xDS TTL 可以保证:如果控制面不可用且无法撤销该 xDS 变更,Envoy 会在服务器指定的 TTL 到期后删除该资源。需要注意:
- 当前 TTL 到期后的行为是移除(而非回滚到上一版本),因此该特性主要适用于"资源缺失优于临时版本"的场景,例如用 RTDS 下发临时运行时覆盖;
- TTL 在 Resource proto 上指定:Delta xDS 直接在响应内指定;SotW xDS 服务器可以将响应中的个别资源包装在
Resource中以指定 TTL; - 服务器可以通过为同一版本再次下发响应来刷新或修改 TTL,此时不必包含资源本身。
五、特殊 YAML 用法:!ignore标签
加载 YAML 配置时,Envoy 加载器会特殊处理带有!ignore标签的 map 键,将其从原生配置树中完全省略(examples.rst 的 "Special YAML usage" 一节)。这是因为 YAML 流通常必须严格遵循 Envoy 配置的 proto 模式,而!ignore允许声明"显式不作为已表示类型处理"的内容。
这让你可以把文件拆成两部分:一部分是不按模式解析的 YAML 内容,另一部分是被解析的内容;第一部分中的 YAML 锚点可以被第二部分的别名引用,从而简化需要复用或动态生成配置片段(如共享的 socket 地址)的场景。完整示例见 docs/root/configuration/overview/_include/tagged.yaml:
!ignore dynamic_sockets: - &admin_address {address: 127.0.0.1, port_value: 9901} - &listener_address {address: 127.0.0.1, port_value: 10000} - &lb_address {address: 127.0.0.1, port_value: 1234} admin: address: socket_address: *admin_address static_resources: listeners: - name: listener_0 address: socket_address: *listener_address filter_chains: - filters: - name: envoy.filters.network.http_connection_manager typed_config: "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager stat_prefix: ingress_http codec_type: AUTO route_config: name: local_route virtual_hosts: - name: local_service domains: ["*"] routes: - match: {prefix: "/"} route: {cluster: some_service} http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router clusters: - name: some_service connect_timeout: 0.25s type: STATIC lb_policy: ROUND_ROBIN load_assignment: cluster_name: some_service endpoints: - lb_endpoints: - endpoint: address: socket_address: *lb_address这里!ignore dynamic_sockets块定义了三个可复用的 socket 地址锚点,admin和static_resources通过别名(*admin_address等)引用它们。底层实现位于 source/common/protobuf/yaml_utility.cc:在parseYamlNode解析 Map 节点时,凡it.first.Tag() != "!ignore"的键才被写入结构体字段,!ignore键被直接丢弃。
兼容性警告:如果使用外部 YAML 加载器解析 Envoy 配置,需要告知加载器如何处理!ignore自定义标签。文档给出了 PyYAML 的处理方式:
yaml.SafeLoader.add_constructor('!ignore', yaml.loader.SafeConstructor.construct_scalar)(仓库中 Envoy 自身在配置校验时注册!ignore标签的方式与此类似。)
六、结合源码理解 Bootstrap 的加载与校验
将整条链路串起来看:
- 命令行解析(source/server/options_impl.cc):
-c/--config-path指定配置文件路径,--config-yaml支持内联 YAML 并与前者合并; - 文件加载(source/server/server.cc):
loadBootstrapConfig()依据扩展名选择解析方式——pb走二进制、pb_text走文本、yaml/yml走 YAML(见 source/common/protobuf/utility.cc),最终通过MessageUtil::loadFromFile/loadFromYaml填充envoy.config.bootstrap.v3.Bootstrap消息,并调用MessageUtil::validate进行模式校验; - 配置生效:Bootstrap 消息被
InstanceBase::initialize用于构建DrainManager、日志系统、集群管理器、监听器管理器等服务器组件,其中的dynamic_resources则驱动 xDS 客户端与管理服务器建立订阅。
因此,Bootstrap 既是 Envoy 的"启动开关",也是"控制面接入契约"——它决定了 Envoy 以何种身份(node)、通过什么通道(静态集群 + gRPC/REST/ADS)、以何种订阅形态(SotW 或 delta)接入 xDS。
七、实践建议与常见误区
- 引导集群永远静态:即使全动态部署,
xds_cluster也必须在static_resources.clusters中静态定义,否则 Envoy 无法与管理服务器建立首次连接; - 务必配置 keep-alive:为
xds_cluster配置tcp_keepalive与 HTTP/2connection_keepalive,以检测 TCP 半开连接并自动重连; - router 过滤器不可省略:任何 HCM 的
http_filters链都必须包含envoy.filters.http.router,否则请求无法被转发; - SotW 与 delta 互斥:二者是互不兼容的协议,选择后需在控制面与服务端保持一致;
- ADS 依赖单一流:ADS 仅 gRPC,且要求所有走 ADS 的 ConfigSource 都设置
ads: {}字段; - REST 响应语义:REST 端点必须返回 200 +
DiscoveryResponse,配置未变化时可用 304 + 空 body 应答; - TTL 是"删除"而非"回滚":使用 RTDS 做临时运行时覆盖时,注意 TTL 到期后资源是被移除,而不是恢复到旧版本。
八、进一步阅读
- 完整示例文件:examples.rst、dynamic-resources.yaml、oauth-sds-example.yaml(含 SDS 动态下发 OAuth 密钥的完整监听器/集群配置)
- xDS API 端点与 ADS/Delta/TTL 细节:xds_api.rst
- Bootstrap proto 字段全集:api/envoy/config/bootstrap/v3/bootstrap.proto
- 管理服务器实现参考:mgmt_server.rst
- 加载与校验实现:source/server/server.cc、source/common/protobuf/yaml_utility.cc
【免费下载链接】envoyCloud-native high-performance edge/middle/service proxy项目地址: https://gitcode.com/GitHub_Trending/en/envoy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考