起不来的配置会在部署途中暴露
一句话总结
Envoy 读取一份配置文件后成为一个进程。这份文件由管理端口、身份、静态资源、动态资源四个部分构成,其余的一切都是这四部分内部的层次。如果能逐层指出这个结构,即使第一次见到的配置也不会迷路。
为什么需要它
代理配置出错,通常会出现两种情况之一:一种是进程根本启动不起来,另一种是能启动,但请求被送到了错误的地方。在生产环境中,更可怕的是第一种。因为重启通常发生在部署过程中,而那时旧进程已经被停掉了。@type 少一个字母、缩进差一格,都会直接变成故障。
Envoy 了解这个问题,所以专门提供了只检查配置的模式。
envoy --mode validate -c boot.yaml
这条命令会把配置完整读取一遍并检查到 schema,然后不占用任何端口,只留下退出码就结束。因此在已经运行着 Envoy 的机器上也可以执行,还可以放进构建容器镜像的 CI 步骤中。如果改了配置却没有运行这条命令,就没有人知道这份配置能不能启动。
工作原理
bootstrap 的顶层键只需要记住四个。
| 键 | 含义 | 缺少时 |
|---|---|---|
admin |
管理端口。用于统计、配置转储、修改日志级别 | 没有可以观察内部的窗口 |
node |
这个代理的标识(id、cluster) |
只使用静态配置时没有问题;接入 xDS 后则必须提供 |
static_resources |
写在文件里的监听器和集群 | 不监听任何东西 |
dynamic_resources |
从外部获取的配置(xDS) | 配置被固定 |
static_resources 内部又分为五层:listener → filter_chain → http_connection_manager → route_config → cluster。这与请求进入的顺序完全一致:从地址和端口开始,选出由哪条过滤器链接收,按 HTTP 解析,再从路由表中得到目标集群名称,最后由该名称的集群把请求发往实际的端点。读配置时遵循这个顺序,就能很快看出是哪一层为空。
写在 bootstrap 中的内容是否真的原样生效,不靠肉眼确认。管理端口 /config_dump 的第一节是 BootstrapConfigDump,Envoy 实际读取到的值就原样放在其中。养成把文件和转储并排查看的习惯,就能消除“我明明改了,为什么没变”的困惑。
在现场相遇的样子
在一台机器上启动第二个 Envoy 的时候。端口都已经错开,第二个进程却因 unable to bind domain socket with base_id=0 而退出。Envoy 启动时会申请一块共享内存区域(热重启时用来传递统计数据),它的名称由 base id 决定,而默认值是 0。用 --base-id 区分开,两个就都能启动。在同一节点上部署两个代理的架构(一个做入口,一个做出口)中,一定会遇到这个问题。
管理端口暴露在外的事故。有人为了方便,把 admin.address 设成 0.0.0.0。但这个端口没有认证,/quitquitquit 会结束进程,/drain_listeners 会切断流量。为了抓统计数据而开的口子,立刻就成了让服务下线的按钮。应把管理端口绑定在回环地址上,需要时在它前面另设代理,只暴露读取路径。
不了解 --concurrency 就做实验。默认值是 CPU 核心数。由于每个工作线程的负载均衡状态各自独立,发送八个请求并统计是否均匀分配到三个端点,每次得到的数字都会不同。统计分配情况的实验,必须使用 --concurrency 1 才具有确定性。
“改了但没有变化。”写在 static_resources 中的内容只会在进程启动时读取一次。改了文件,在重新启动之前什么都不会发生。所以在生产环境中,把文件和 /config_dump 并排对照的习惯很重要——转储里没有,就是还没有生效;转储里有而行为不同,那就该怀疑别的层,而不是配置。从外部获取配置、无需重启就能更改的方式就是 dynamic_resources(xDS),这会在本课程的最后一个模块中讲解。
官方文档:Bootstrap configuration · Command line options · Administration interface
下一项实验要做什么
亲手编写 bootstrap,用 --mode validate 让它通过,再故意写错一个字母,观察它被拒绝。然后启动第二个 Envoy,亲身遇到需要 --base-id 的时刻,最后通过管理端口结束进程再重新启动。