- 教程
- 云原生
- 容器编排
【免费下载链接】kubernetes-handbook
Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南
导读
本文以 Kubernetes Handbook 仓库中 usecases/envoy-front-proxy.md 为核心,完整讲解如何使用 Envoy 作为前端(边缘)反向代理:通过 Docker 容器与 docker-compose 在单机环境编排front-envoy、service1、service2三个服务,从底层理解 Envoy 的路由、负载均衡与 admin 管理端点。读完本文你将掌握 Envoy 的 YAML 静态配置(listener / cluster / admin)、进程外(out-of-process)与无侵入式架构原理,并为后续将 Envoy 作为 Istio Service Mesh 数据平面(data plane)打下扎实基础。
Envoy 与前端代理的定位
Envoy 是 Lyft 开源、使用 C++ 编写的 L7 代理和通信总线,是 CNCF 旗下的毕业项目,也是 Istio 服务网格默认的数据平面。其关键特性包括:进程外架构(不侵入应用进程)、L3/L4 与 HTTP L7 filter 架构、HTTP/2 支持、L7 路由、动态配置(xDS)、最佳可观测性、front/edge proxy 支持、高级负载均衡、健康检查与服务发现等。
从 usecases/envoy.md 可知,Envoy 本身无法构成完整的 Service Mesh,但可以作为 service mesh 中应用间流量的代理,负责数据层。而"前端代理"正是 Envoy 支持的一种部署角色:Edge envoy,即流量进出 mesh 时的入口代理,相当于 Kubernetes 中的 Ingress。与之相对的是随每个服务实例一起运行的Service envoy(在 Kubernetes 中作为 Sidecar 与应用容器共存于同一 Pod),详见 usecases/envoy-terminology.md。
本文的示例正对应"边缘反向代理"这一角色:Envoy 类似于 Nginx,但与之不同的是,它还可以作为进程伴随每个服务运行在同一个容器/Pod 中(Sidecar 模式),这也是它无侵入、进程外架构的体现。
快速开始:克隆 Envoy 源码
Envoy 中的所有规则配置与 Kubernetes 一样,都是通过 YAML 文件完成的。在继续之前,先克隆 Envoy 的 GitHub 仓库:
git clone https://github.com/envoyproxy/envoy.gitEnvoy 官方提供了多个可直接使用docker-compose运行的打包用例(sandbox),代码位于 Envoy 仓库的examples目录下:
- Front Proxy(前端代理)
- Zipkin Tracing
- Jaeger Tracing
- gRPC Bridge
本文的核心示例即取自其中的Front proxy用例(envoy/examples/front-proxy)。
Front Proxy 示例的整体架构
本示例的部署结构如下图所示,此时 Envoy 作为反向代理运行在 mesh 边缘,承担边缘网关的角色。
从图中可以看到三组角色的分工:
- front-envoy:边缘(前端)Envoy,监听 80 端口接收外部流量,根据 URL 前缀将请求反向代理到后端的 service1 / service2,同时暴露 8001 端口提供 admin 管理接口;
- service1 / service2:两个后端业务服务,每个服务都与一个 service-envoy 共同运行(示例中通过
SERVICE_NAME环境变量区分实例编号),对外只暴露 80 端口; - envoymesh 网络:三个容器共享的自定义 docker 网络,
front-envoy通过 DNS 名称(service1、service2)发现后端。
这与 usecases/envoy-terminology.md 中描述的 mesh 概念一致:一组互相协调以提供一致网络拓扑的主机,其中 edge envoy 负责流量进出,service envoy 与应用进程无感知地共存。
编写 docker-compose.yml 编排文件
在此示例中一共有 3 个服务,首先为其创建容器编排的docker-compose.yml文件:
version: '2' services: front-envoy: build: context: . dockerfile: Dockerfile-frontenvoy volumes: - ./front-envoy.yaml:/etc/front-envoy.yaml networks: - envoymesh expose: - "80" - "8001" ports: - "8000:80" - "8001:8001" service1: build: context: . dockerfile: Dockerfile-service volumes: - ./service-envoy.yaml:/etc/service-envoy.yaml networks: envoymesh: aliases: - service1 environment: - SERVICE_NAME=1 expose: - "80" service2: build: context: . dockerfile: Dockerfile-service volumes: - ./service-envoy.yaml:/etc/service-envoy.yaml networks: envoymesh: aliases: - service2 environment: - SERVICE_NAME=2 expose: - "80" networks: envoymesh: {}该编排文件的关键设计点:
- 网络别名(aliases):
service1、service2在网络envoymesh中注册了 DNS 别名,这使得front-envoy的 cluster 配置可以直接用主机名service1、service2寻址后端; - 端口映射:
front-envoy将容器内 80 端口映射到宿主机的8000端口(对外流量入口),将 8001 端口直接透出(admin 管理接口);两个后端服务仅通过expose声明端口,不映射到宿主机,只能在envoymesh网络内部被访问; - 配置挂载:
./front-envoy.yaml挂载到容器内/etc/front-envoy.yaml,./service-envoy.yaml挂载到/etc/service-envoy.yaml,实现配置与镜像分离。
使用docker-compose up --build启动后,三个服务都会处于frontproxy_envoymesh这个网络中(网络名前缀为项目目录名),从而保证相互可达。
front-envoy 镜像与启动方式
front-envoy使用Dockerfile-frontenvoy文件构建镜像,内容如下:
FROM envoyproxy/envoy:latest RUN apt-get update && apt-get -q install -y \ curl CMD /usr/local/bin/envoy -c /etc/front-envoy.yaml --service-cluster front-proxy该 Dockerfile 有两个值得注意的地方:
- 基础镜像为官方
envoyproxy/envoy:latest,并额外安装了curl,方便在容器内做连通性验证; - 启动命令中
-c /etc/front-envoy.yaml指定静态配置文件(由宿主机./front-envoy.yaml挂载进来),--service-cluster front-proxy设置 Envoy 实例所属的服务集群名,该名称会出现在统计信息中,便于多实例场景下区分。
front-envoy.yaml 静态配置详解
/etc/front-envoy.yaml是本次示例的核心配置文件,完整内容如下:
static_resources: listeners: - address: socket_address: address: 0.0.0.0 port_value: 80 filter_chains: - filters: - name: envoy.http_connection_manager config: codec_type: auto stat_prefix: ingress_http route_config: name: local_route virtual_hosts: - name: backend domains: - "*" routes: - match: prefix: "/service/1" route: cluster: service1 - match: prefix: "/service/2" route: cluster: service2 http_filters: - name: envoy.router config: {} clusters: - name: service1 connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service1 port_value: 80 - name: service2 connect_timeout: 0.25s type: strict_dns lb_policy: round_robin http2_protocol_options: {} hosts: - socket_address: address: service2 port_value: 80 admin: access_log_path: "/dev/null" address: socket_address: address: 0.0.0.0 port_value: 8001配置整体包含三大顶级配置项:
- static_resources:静态资源定义,包含 listener(监听器)与 cluster(集群)两部分;
- clusters:envoymesh 中的服务注册信息(此处为静态注册,也可通过 SDS/xDS 动态发现);
- admin:管理接口,监听 8001 端口,可通过
/stats获取当前 Envoy 的统计信息,通过/server_info获取版本信息。
Listener:HTTP 连接管理器
listeners定义 Envoy 监听的网络位置与流量处理链。示例中监听0.0.0.0:80,通过filter_chains挂载一个envoy.http_connection_manager(HTTP 连接管理器)过滤器,其中:
codec_type: auto:自动协商 HTTP/1.1 与 HTTP/2 编解码;stat_prefix: ingress_http:统计信息前缀,用于区分不同 listener 的度量;route_config.virtual_hosts:虚拟主机配置,domains: ["*"]匹配所有域名,routes内通过prefix(URL 路径前缀)与cluster(目标集群)建立映射:/service/1→service1,/service/2→service2;http_filters中最后挂载envoy.router过滤器,负责真正的路由转发动作。
结合 usecases/envoy-terminology.md 中的术语说明,virtual_hosts必须包含name(服务名称)、domains(DNS 域名,必须能跟 virtual host 的 URL 匹配)、routes(路由列表);每个路由可包含prefix(URL 路径前缀)、cluster(处理请求的 envoy cluster)、timeout_ms(超时时间)。这里的内联路由配置即为静态 RDS,若采用动态配置则可由 Route Discovery Service(RDS)下发。
Cluster:服务发现与负载均衡
clusters定义了一组逻辑上相似的上游主机。示例中service1与service2两个 cluster 的关键参数:
name:cluster 名称,即服务名称,与路由中引用的 cluster 一一对应;connect_timeout: 0.25s:与上游建立连接的超时时间;type: strict_dns:服务发现类型,Envoy 持续监听 DNS,每个匹配的 A 记录都认定为有效主机(DNS 解析出的每个 IP 都会加入 cluster);lb_policy: round_robin:负载均衡策略,轮询访问各上游主机;http2_protocol_options: {}:启用 HTTP/2 上游协议支持(Envoy 对上游默认优先协商 HTTP/2);hosts:上游主机地址列表,此处通过 socket_address 指定 DNS 名称service1:80、service2:80。
关于type(服务发现方式),usecases/envoy-terminology.md 汇总了四种取值:
static:静态配置,监听 cluster 中列出的所有主机;strict_dns:Envoy 持续监听 DNS,每个匹配的 A 记录都认定为有效;logical_dns:Envoy 使用 DNS 增加主机,但即使 DNS 不再返回该主机也不会删除这些主机信息;sds:Service Discovery Service,Envoy 访问外部的 REST 接口获取 cluster 成员信息(即 usecases/envoy-mesh-in-kubernetes-tutorial.md 中讨论的 SDS 方案,用于发现服务的所有 endpoint 而非仅 ClusterIP)。
Admin:管理接口
admin块配置管理服务监听地址为0.0.0.0:8001,access_log_path设为/dev/null关闭访问日志。启动后访问http://localhost:8001即可看到管理端点列表(详见下文"admin 端点"一节)。
启动并验证环境
在envoy/examples/front-proxy目录下执行:
$ pwd envoy/examples/front-proxy $ docker-compose up --build -d $ docker-compose ps Name Command State Ports ------------------------------------------------------------------------------------------------------------- example_service1_1 /bin/sh -c /usr/local/bin/ ... Up 80/tcp example_service2_1 /bin/sh -c /usr/local/bin/ ... Up 80/tcp example_front-envoy_1 /bin/sh -c /usr/local/bin/ ... Up 0.0.0.0:8000->80/tcp, 0.0.0.0:8001->8001/tcp三个容器全部启动成功:两个后端服务仅监听 80 端口,front-envoy将宿主机的8000映射到容器 80(流量入口)、8001映射到容器 8001(admin 接口)。
路由验证
访问 service1(http://localhost:8000/service/1):
$ curl -v localhost:8000/service/1 * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8000 (#0) > GET /service/1 HTTP/1.1 > Host: localhost:8000 > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < content-type: text/html; charset=utf-8 < content-length: 89 < server: envoy < date: Fri, 20 Apr 2018 08:26:33 GMT < x-envoy-upstream-service-time: 14 < Hello from behind Envoy (service 1)! hostname: a3e4185a9a49 resolvedhostname: 172.18.0.4 * Connection #0 to host localhost left intact访问 service2(http://localhost:8000/service/2)时返回:
* Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 8000 (#0) > GET /service/2 HTTP/1.1 > Host: localhost:8000 > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < content-type: text/html; charset=utf-8 < content-length: 89 < server: envoy < date: Fri, 20 Apr 2018 08:27:27 GMT < x-envoy-upstream-service-time: 10 < Hello from behind Envoy (service 2)! hostname: f6650e1911a0 resolvedhostname: 172.18.0.3 * Connection #0 to host localhost left intact响应特征印证了 Envoy 的路由与代理行为:
- 响应头中
server: envoy表明流量确实经过 Envoy 转发; x-envoy-upstream-service-time头记录了上游服务的处理耗时(单位毫秒),这是 Envoy 可观测性的一部分;- 返回体中的
hostname与resolvedhostname是后端示例应用打印的容器 ID 与解析到的 IP,两者不同(一个指向 service1,一个指向 service2),说明请求被正确路由到了对应的后端服务。
负载均衡验证
通过docker-compose scale将 service1 扩容到 3 个实例(注意:新版 docker-compose 中 scale 命令已废弃,推荐使用up --scale参数):
$ docker-compose scale service1=3 WARNING: The scale command is deprecated. Use the up command with the --scale flag instead. Starting frontproxy_service1_1 ... done Creating frontproxy_service1_2 ... done Creating frontproxy_service1_3 ... done $ docker-compose ps Name Command State Ports --------------------------------------------------------------------------------------------------------------------------- frontproxy_front-envoy_1 /usr/bin/dumb-init -- /bin ... Up 10000/tcp, 0.0.0.0:8000->80/tcp, 0.0.0.0:8001->8001/tcp frontproxy_service1_1 /bin/sh -c /usr/local/bin/ ... Up 10000/tcp, 80/tcp frontproxy_service1_2 /bin/sh -c /usr/local/bin/ ... Up 10000/tcp, 80/tcp frontproxy_service1_3 /bin/sh -c /usr/local/bin/ ... Up 10000/tcp, 80/tcp frontproxy_service2_1 /bin/sh -c /usr/local/bin/ ... Up 10000/tcp, 80/tcp此时 service1 已有 3 个实例。循环访问 service1 观察负载均衡效果:
$ while true;do curl localhost:8000/service/1;sleep 1;done Hello from behind Envoy (service 1)! hostname: a3e4185a9a49 resolvedhostname: 172.18.0.4 Hello from behind Envoy (service 1)! hostname: fe44dba64122 resolvedhostname: 172.18.0.5 Hello from behind Envoy (service 1)! hostname: c5b9f1289e0f resolvedhostname: 172.18.0.6 Hello from behind Envoy (service 1)! hostname: a3e4185a9a49 resolvedhostname: 172.18.0.4 Hello from behind Envoy (service 1)! hostname: fe44dba64122 resolvedhostname: 172.18.0.5 Hello from behind Envoy (service 1)! hostname: c5b9f1289e0f resolvedhostname: 172.18.0.6三个不同 hostname(对应三个容器实例)循环出现,说明round_robin轮询负载均衡已生效——这一策略正是在front-envoy.yaml的cluster配置项中通过lb_policy: round_robin声明的。值得注意的是,这里的负载均衡发生在 Envoy 层:由于strict_dns会持续解析service1的 DNS 记录,Envoy 动态感知到了扩容后新增的容器地址并纳入轮询池。
admin 端点与运维能力
访问http://localhost:8001可以看到 Envoy admin 提供的管理 API 端点:
| 命令 | 描述 |
|---|---|
| / | Admin 主页 |
| /certs | 打印机器上的 certs |
| /clusters | upstream cluster 状态 |
| /config_dump | 输出当前的 Envoy 配置 |
| /cpuprofiler | 开启/关闭 CPU profiler |
| /healthcheck/fail | 导致服务失败健康检查 |
| /healthcheck/ok | 导致服务通过健康检查 |
| /help | 打印管理命令的帮助信息 |
| /hot_restart_version | 打印热重启兼容版本 |
| /listeners | 打印 listener 地址 |
| /logging | 查询/更改日志级别 |
| /quitquitquit | 退出服务 |
| /reset_counters | 将计数器重置为 1 |
| /runtime | 打印运行时值 |
| /runtime_modify | 修改运行时值 |
| /server_info | 打印服务器版本/状态信息 |
| /stats | 打印服务器状态统计信息 |
| /stats/prometheus | 打印 prometheus 格式的服务器状态统计信息 |
这些端点覆盖了日常运维的主要场景:/stats与/stats/prometheus提供监控数据(后者可直接被 Prometheus 抓取);/config_dump可用于核对线上实际生效的配置;/clusters查看上游集群健康与成员状态;/logging动态调整日志级别;/healthcheck/fail与/healthcheck/ok可人为触发健康检查失败/通过以测试故障转移逻辑。Enovy 通过这些管理 API 端点提供了运行时动态配置与观测能力。
从前端代理到数据平面:与 Istio 的衔接
本示例的意义不止于单机实验。把 Envoy 部署在应用进程之外、与应用容器同 Pod(Sidecar)正是 Istio 数据平面的基本形态:
- 在 usecases/istio.md 的架构描述中,数据平面由一组智能代理(Envoy)以 sidecar 模式部署,协调和控制所有服务之间的网络通信;控制平面负责管理和配置代理路由流量、执行策略;
- 仓库中的 manifests/istio/istio.yaml 展示了 Istio 的部署形态:istio-ingress(对应本示例中 front-envoy 的边缘入口角色)、istio-manager(负责 discovery,即控制平面的配置下发)、istio-mixer(策略与遥测);
- manifests/sofa-mesh/sofa-mesh-demo.yaml 中也可以看到
istio-proxy(envoy)容器的存在,以及envoyfilters这类用于定制 Envoy 行为的 CRD 定义。
在本示例中,Envoy 的路由与 cluster 全部来自静态 YAML;而在 Istio 中,控制平面通过 xDS(CDS/EDS/RDS/LDS 等发现服务)将配置动态下发给 Envoy,实现无重启的流量管理。理解了本示例中 listener 与 cluster 的静态配置逻辑,再理解 Istio 的动态配置注入就水到渠成。
小结
通过 docker-compose 在单机运行 Envoy Front Proxy 示例,我们可以得出以下与生产实践直接相关的结论:
- 进程外、无侵入:Envoy 以独立进程运行在应用之外(同一容器或同一 Pod),应用代码无需任何改动即可获得代理、路由、负载均衡与可观测性能力;
- YAML 驱动的声明式配置:listener(含 HTTP connection manager 与路由表)、cluster(服务发现 + 负载均衡策略)、admin 三大配置块覆盖了边缘代理的核心能力;
- 边缘入口角色:front-envoy 充当流量进出 mesh 的网关(类似 Kubernetes Ingress),支持基于 URL 前缀的路由与基于
strict_dns+round_robin的动态负载均衡; - admin 端点提供运行时运维能力:统计、配置导出、日志级别调整、健康检查开关等均可通过 8001 端口的 HTTP 端点完成;
- 为 Service Mesh 打基础:本示例的静态配置模式正是 Istio 数据平面 Envoy 代理的雏形,理解了它便能更快掌握 xDS 动态配置与 Sidecar 注入机制。
如需继续深入,建议阅读仓库中 usecases/envoy-terminology.md(Envoy 架构与基本术语、xDS 概念)、usecases/envoy-mesh-in-kubernetes-tutorial.md(Envoy 在 Kubernetes 中做 mesh 的完整实战,包括 edge envoy 与 SDS 服务发现),以及 usecases/istio.md(Istio 数据平面与控制平面架构)。
- 教程
- 云原生
- 容器编排
【免费下载链接】kubernetes-handbook
Kubernetes 架构与生态:从云原生到 AI 原生基础设施的构建指南
相关推荐
超实用!PostgREST与Nginx反向代理+负载均衡实战指南
超实用!PostgREST与Nginx反向代理+负载均衡实战指南 PostgREST作为一款轻量级RESTful API服务器,能快速将PostgreSQL数据
后端API网关BilibiliDown:3分钟学会下载B站视频,支持高清画质与批量操作
BilibiliDown:3分钟学会下载B站视频,支持高清画质与批量操作 想要轻松下载B站视频,保存喜欢的UP主内容,或者批量获取收藏夹里的视频吗?Bilibi
音视频桌面应用Kubernetes 集群中的 Envoy Mesh 实战:从 edge envoy 反向代理到 SDS 服务发现与负载均衡
Kubernetes 集群中的 Envoy Mesh 实战:从 edge envoy 反向代理到 SDS 服务发现与负载均衡 本文以 kubernetes ha
教程云原生容器编排
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考