Agentic AI、具身智能、强化学习框架、端侧大模型……来QCon上海站,感受AI的未来! 了解详情
写点什么

服务网格数据平面的关键:层层剖析 Envoy 配置

  • 2020-05-18
  • 本文字数:6613 字

    阅读完需:约 22 分钟

服务网格数据平面的关键:层层剖析Envoy配置

服务网格是微服务设置中的通信层,也就是说往返于每个服务的所有请求都通过网格。服务网格在微服务设置中也成为基础架构层,它能够让服务之间的通信变得安全可靠。关于 Service Mesh 的基础内容,我们已经在这篇文章中详细介绍过。


每一个服务都有自己的代理服务(sidecars),然后所有代理服务一起形成服务网格。Sidecars 处理服务之间的通信,也就是说所有的流量都会通过网格并且该透明层可以控制服务之间如何交互。


服务网格通过由 API 控制的组件提供可观察性、服务发现以及负载均衡等。


实际上,如果一个服务要调用另一个服务,它不会直接调用目标服务。而是先将请求路由到本地代理,然后代理再将该请求路由到目标服务。这一过程意味着服务实例不会和其他服务直接接触,仅与本地代理进行通信。



本地代理服务


根据 ThoughtWorks Technology Radar(这是一份半年度的文档,用于评估现有技术和新生技术的风险和收益)指出,“服务网格提供一致的发现、安全性、跟踪(tracing)、监控以及故障处理,而无需共享资源(如 API 网关或 ESB)。一个十分典型的用例是轻量的反向代理进程会与每个服务进程或单独的容器一起部署。”


当谈到服务网格时,不可避免谈到的是“sidecar”——可用于每个服务实例的代理。每个 sidecar 负责管理一个服务的一个实例。我们将在本文中进一步详细讨论 sidecar。

服务网格可以交付什么?


服务网格可以交付的功能


当前,越来越多的企业和组织开始转向微服务架构。这样的企业需要服务网格所提供的上述功能。解耦库的使用或自定义代码的方法无疑是赢家。

为什么使用 Envoy?

Envoy 不是构建一个服务网格的唯一选择,市面上还有其他的代理如 Nginx、Traefik 等。我之所以选择 Envoy,这个用 C++编写的高性能代理,是因为我更喜欢 Envoy 的轻量、强大的路由,及其提供的可观察性和可扩展性。


让我们首先构建 1 个包含 3 个服务的服务网格设置,这是我们正在尝试构建的架构:



sidecar 代理的服务设置

Front Envoy

在我们的设置中 Front Envoy 是一个边缘代理,我们通常在其中执行 TLS 终止、身份验证、生成请求头等操作。


我们来看看 Front Envoy 配置:


---admin:  access_log_path: "/tmp/admin_access.log"  address:     socket_address:       address: "127.0.0.1"      port_value: 9901static_resources:   listeners:    -       name: "http_listener"      address:         socket_address:           address: "0.0.0.0"          port_value: 80      filter_chains:          filters:             -               name: "envoy.http_connection_manager"              config:                stat_prefix: "ingress"                route_config:                   name: "local_route"                  virtual_hosts:                     -                       name: "http-route"                      domains:                         - "*"                      routes:                         -                           match:                             prefix: "/"                          route:                            cluster: "service_a"                http_filters:                  -                     name: "envoy.router"  clusters:    -       name: "service_a"      connect_timeout: "0.25s"      type: "strict_dns"      lb_policy: "ROUND_ROBIN"      hosts:        -           socket_address:             address: "service_a_envoy"            port_value: 8786
复制代码


Envoy 配置主要由以下部分组成:


1、 监听器(Listener)


2、 路由


3、 集群


4、 端点

监听器

一个或多个监听器可以在单个 Envoy 实例中运行。在以上 9 到 36 行的代码提到了当前监听器的地址和端口。每个监听器也可以有一个或多个网络过滤器。这些过滤器可以启用路由、tls 终止、流量转移等活动。除了 envoy.http_connection_manager 使用的是内置过滤器之外,Envoy 还有其他几个过滤器。

路由

22 行到 34 行代码为过滤器配置了路由规范,同时它也指定了我们所接受请求的域以及路由匹配器。路由匹配器可以根据配置的规则匹配每个请求,并将请求转发到适当的集群。

集群

集群是 Envoy 将流量路由到的上游服务规范。41 行到 48 行代码定义了“Service A”,这是 Front Envoy 要通信的唯一上游。“connect_timeout”是在返回 503 之前建立与上游服务的连接的时间限制。


通常情况下,有多个“Serivce A”实例,并且 Envoy 支持多种负载均衡算法来路由流量。在本例中,我们使用了一个简单的循环算法。

端点

“host”指定我们要将流量路由到的 Service A 的实例。在本例中,我们只有 1 个实例。


第 47 行代码没有直接与 Service A 进行通信,而是与 Service A 的 Envoy 代理实例进行通信,该代理将路由到本地 Service A 实例。


我们还可以利用返回 Service A 的所有实例的服务名称(如 Kubernetes 中的 headless 服务),来执行客户端负载均衡。Envoy 缓存 Service A 的所有 host,并每 5 秒刷新一次 host 列表。


此外,Envoy 还支持主动和被动的健康检查。因此,如果我们要进行主动健康检查,我们需要在集群配置部分对其进行配置。

其他

第 2 行到第 7 行配置了管理服务器,它能够帮助查看配置、更改日志级别、查看统计信息等。


第 8 行的“static_resources”可以手动加载所有配置。我们将在下文讨论如何动态地执行此操作。


虽然这里描述了许多其他配置,但是我们的目标不是全面介绍所有配置,而是以最少的配置开始。

Service A

这是 Service A 的 Envoy 配置:


admin:  access_log_path: "/tmp/admin_access.log"  address:     socket_address:       address: "127.0.0.1"      port_value: 9901static_resources:  listeners:
- name: "service-a-svc-http-listener" address: socket_address: address: "0.0.0.0" port_value: 8786 filter_chains: - filters: - name: "envoy.http_connection_manager" config: stat_prefix: "ingress" codec_type: "AUTO" route_config: name: "service-a-svc-http-route" virtual_hosts: - name: "service-a-svc-http-route" domains: - "*" routes: - match: prefix: "/" route: cluster: "service_a" http_filters: - name: "envoy.router" - name: "service-b-svc-http-listener" address: socket_address: address: "0.0.0.0" port_value: 8788 filter_chains: - filters: - name: "envoy.http_connection_manager" config: stat_prefix: "egress" codec_type: "AUTO" route_config: name: "service-b-svc-http-route" virtual_hosts: - name: "service-b-svc-http-route" domains: - "*" routes: - match: prefix: "/" route: cluster: "service_b" http_filters: - name: "envoy.router"
- name: "service-c-svc-http-listener" address: socket_address: address: "0.0.0.0" port_value: 8791 filter_chains: - filters: - name: "envoy.http_connection_manager" config: stat_prefix: "egress" codec_type: "AUTO" route_config: name: "service-b-svc-http-route" virtual_hosts: - name: "service-b-svc-http-route" domains: - "*" routes: - match: prefix: "/" route: cluster: "service_c" http_filters: - name: "envoy.router" clusters: - name: "service_a" connect_timeout: "0.25s" type: "strict_dns" lb_policy: "ROUND_ROBIN" hosts: - socket_address: address: "service_a" port_value: 8081 - name: "service_b" connect_timeout: "0.25s" type: "strict_dns" lb_policy: "ROUND_ROBIN" hosts: - socket_address: address: "service_b_envoy" port_value: 8789
- name: "service_c" connect_timeout: "0.25s" type: "strict_dns" lb_policy: "ROUND_ROBIN" hosts: - socket_address: address: "service_c_envoy" port_value: 8790
复制代码


11 行到 39 行定义了一个监听器来路由流量到实际的 Service A 实例。在 103 行到 111 行中找到 service_a 实例的相应集群定义。


Service A 与 Service B 和 Service C 进行通信,它指向了两个以上的监听器以及集群。在本例中,我们为每个上游(localhost、Service B 和 Service C)分离了监听器。另一种方法是使用单个监听器,并根据 URL 或请求头路由到任意上游。

Service B 和 Service C

Service B 和 Service C 处于叶级,除了本地主机服务实例外,不与任何其他上游通信。因此其配置十分简单。


而让事情变得复杂的是上述配置中的单个监听器和单个集群。


配置完成后,我们将此设置部署到 Kubernetes 或使用 docker-compose 对其进行测试。你可以运行 docker-compose build 和 docker-compose up 并点击 localhost:8080,以查看请求是否成功通过所有服务和 Envoy 代理。我们可以使用日志对其进行验证。

Envoy xDS

我们为每个 sidecar 提供了配置,并且根据不同的服务,服务之间的配置也有所不同。虽然我们可以手动制作和管理 sidecar 配置,但最初至少要提供 2 或 3 个服务,并且随着服务数量的增加,配置会变得十分复杂。此外,每次 sidecar 配置更改时,你都必须重新启动 Envoy 实例,以使更改生效。


正如上文所讨论的,我们可以通过使用 API server 来避免手动配置并加载所有组件:集群(CDS)、端点(EDS)、监听器(LDS)以及路由(RDS)。所以每个 sidecar 将与 API server 通信并接收配置。当新配置更新到 API server 时,它将自动反映在 Envoy 实例中,从而避免了重新启动。


你可以在以下链接中了解关于动态配置的信息:


https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/v2_overview#dynamic


这有一个简单的 xDS server:


https://github.com/tak2siva/Envoy-Pilot

如何在 Kubernetes 中实现

本部分将讨论如果我们要在 Kubernetes 中实现所讨论的设置该怎么办。以下是架构图:


因此,将需要更改:


  • Pod

  • 服务

部署 Pod

尽管 Pod 规范中仅定义了一个容器——按照定义,一个 Pod 可以容纳一个或多个容器。为了对每个服务实例运行 sidecar 代理,我们将 Envoy 容器添加到每个 Pod 中。为了与外界通信,服务容器将通过 localhost 与 Envoy 容器进行对话。


部署文件如下所示:


admin:  access_log_path: "/tmp/admin_access.log"  address:     socket_address:       address: "127.0.0.1"      port_value: 9901static_resources:  listeners:
- name: "service-b-svc-http-listener" address: socket_address: address: "0.0.0.0" port_value: 8789 filter_chains: - filters: - name: "envoy.http_connection_manager" config: stat_prefix: "ingress" codec_type: "AUTO" route_config: name: "service-b-svc-http-route" virtual_hosts: - name: "service-b-svc-http-route" domains: - "*" routes: - match: prefix: "/" route: cluster: "service_b" http_filters: - name: "envoy.router" clusters: - name: "service_b" connect_timeout: "0.25s" type: "strict_dns" lb_policy: "ROUND_ROBIN" hosts: - socket_address: address: "service_b" port_value: 8082
复制代码


在容器部分添加了 Envoy sidecar,并且在 33 到 39 行的 configmap 中我们挂载了我们的 Envoy 配置文件。

更改服务

Kubernetes 服务负责维护 Pod 端点列表,该列表可以路由流量。尽管 kube-proxy 通常处理 Pod 端点之间的负载均衡,但在本例中,我们将执行客户端负载均衡,并且我们不希望 kube-proxy 进行负载均衡。此外,我们想要提取 Pod 端点列表并对其进行负载均衡。为此,我们需要使用“headless 服务“来返回端点列表。


如下所示:


kind: Deploymentmetadata:  name: serviceaspec:  replicas: 2  template:    metadata:      labels:        app: servicea    spec:      containers:      - name: servicea        image: dnivra26/servicea:0.6        ports:        - containerPort: 8081          name: svc-port          protocol: TCP      - name: envoy        image: envoyproxy/envoy:latest        ports:          - containerPort: 9901            protocol: TCP            name: envoy-admin          - containerPort: 8786            protocol: TCP            name: envoy-web        volumeMounts:          - name: envoy-config-volume            mountPath: /etc/envoy-config/        command: ["/usr/local/bin/envoy"]        args: ["-c", "/etc/envoy-config/config.yaml", "--v2-config-only", "-l", "info","--service-cluster","servicea","--service-node","servicea", "--log-format", "[METADATA][%Y-%m-%d %T.%e][%t][%l][%n] %v"]      volumes:        - name: envoy-config-volume          configMap:            name: sidecar-config            items:              - key: envoy-config                path: config.yaml
复制代码


有两件事需要注意。一是第 6 行使服务变成 headless,二是我们不是将 Kubernetes 服务端口映射到应用程序的服务端口,而是映射到 Envoy 监听器端口。这意味着,流量首先通向 Envoy。即便如此,Kubernetes 也可以完美运行。


在本文中,我们看到了如何使用 Envoy 代理构建服务网格。其中,我们设置了所有通信都将通过网格。因此,现在网格不仅有大量有关流量的数据,而且还具有控制权。


以下链接中你可以获取我们所讨论的配置和代码:


https://github.com/dnivra26/envoy_servicemesh


原文链接:

https://www.thoughtworks.com/insights/blog/building-service-mesh-envoy-0


2020-05-18 18:071339

评论

发布
暂无评论
发现更多内容

架构学习模块一作业

架构实战营

工作中的设计模式 —— 原型模式

程序员小航

Java 设计模式

锁仓挖矿系统开发|锁仓挖矿APP软件开发

系统开发

全网最全人工智能专业术语表(中英文对照)

澳鹏Appen

人工智能 大数据 数据 科技互联网 专业术语

查漏补缺!驱动核心源码详解和Binder超系统学习资源,挥泪整理面经

欢喜学安卓

android 程序员 面试 移动开发

两面翻转盒子案例(3d效果)

赫鲁小夫

4月日更

IDEA 文档插件 DocView 版本更新:支持编辑文档注释

程序员小航

IDEA idea插件 文档生成 Doc View

北京天源迪科上线迪科商旅App

DT极客

2021最新分享阿里P6面经及心得

比伯

Java 架构 面试 程序人生 计算机

量化策略交易系统,马丁策略平台搭建

我能斩获自己跳动offer,全靠在一周内肝完这426页阿里面试通关手册,

钟奕礼

Java 编程 程序员 架构 面试

四面字节斩获offer,二十不惑的年纪我的人生就这样第一次的走上了正轨,看到了前途希望与光明

钟奕礼

Java 编程 程序员 架构 面试

二十八分钟,带你用gitlab向企业微信发出灵魂拷问

📿

Java gitlab gitlab ci

秒合约交易系统开发|秒合约交易APP软件开发

系统开发

新纪元·新生态!聚焦前沿科技,拥抱万物智联——2021开源科技节重磅来袭!

HDFS的block块和副本机制

大数据技术指南

hadoop hdfs 4月日更

匪夷所思?双非本末的我是如何六面阿里 --最终斩获Java岗P7offer

钟奕礼

Java 编程 程序员 架构 面试

史上最全的Java面试题库宝典,Github上标星200k,太香了!

Java架构之路

Java 程序员 架构 面试 编程语言

项目优化-代码拆分

Darren

android 组件化 代码优化

架构实战营 模块一 作业

PB

架构实战营

音频应用类开源 Demo 大盘点

anyRTC开发者

ios android 音视频 WebRTC RTC

Fluid — 云原生环境下的高效“数据物流系统”

阿里巴巴云原生

人工智能 云计算 容器 云原生 存储

辽宁重点人员管控系统搭建,指挥调度系统搭建

涨薪15K,从小公司成功逆袭,拿到美团P2-3级offer(面经+心得)

Java架构师迁哥

解决了这5大障碍,才能用好混合云!

混合云

架构实战营模块一作业

冷大大

作业 架构实战营 模块一

数字货币期权交易系统开发|数字货币期权交易APP软件开发

系统开发

阿里团队教科书:SpringBoot全优笔记,面面俱到太全了

Java架构师迁哥

跟单交易系统开发|跟单交易APP软件开发

系统开发

Linux ln 命令

一个大红包

4月日更

apk优化,Android高级工程师必看系列,在线面试指南

欢喜学安卓

android 程序员 面试 移动开发

服务网格数据平面的关键:层层剖析Envoy配置_文化 & 方法_Rancher_InfoQ精选文章