写点什么

服务网格数据平面的关键:层层剖析 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:071089

评论

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

前端基础五之jQuery基础

ベ布小禅

8月日更

坚持“一城市一矿山” 拾起卖争当循环产业领跑者

InfoQ 天津

排查指南 | 两个案例学会从埋点排查 iOS 离线包

蚂蚁集团移动开发平台 mPaaS

mPaaS

fil挖矿必看!fil挖矿步骤有哪些?fil挖矿的效率如何?

分布式存储 IPFS fil fil挖矿

【回帖赢大奖】AI+开发者=?

百度大脑

腾讯「小借条」引发的思考:区块链+的商业模式让各企业争先恐后的奥秘

CECBC

netty系列之:netty中的懒人编码解码器

程序那些事

Java Netty nio 程序那些事

markdown不支持代码块和表格,离开这里了

DBKernel

基于一万小时定律去规划职业

非著名程序员

生涯规划 职场 职业规划 8月日更

「古老」茶产业碰上「年轻」区块链,能否擦出新火花?

CECBC

租房市场是流动的么?

escray

生活记录 8月日更 搜房记 租房

图计算之开局女朋友跑了2

Zhuan

图计算 GraphScope 图分析

地府鬼神图关系构建

6979阿强

图算法 图计算 GraphScope

极光开发者周刊【No.0820】

极光JIGUANG

百度智能云最新成绩单亮相百度世界大会2021,“云智一体”再升级!

百度大脑

人工智能 百度

CRLF、CSRF、SSRF攻击与利用

网络安全学海

黑客 网络安全 信息安全 WEB安全 漏洞挖掘

腾讯、阿里纷纷看好的NFT,能否成为拯救区块链的良药?

CECBC

DevOps 调查第十年,如何借助工具实现落地?

飞算JavaAI开发助手

DevOps 基础软件 自动化平台

Go- 基本类型和运算符

HelloBug

Go 语言 布尔类型 基本类型和运算符 数字类型

fil挖矿难度大不大?fil挖矿1T收益是多少?

fil挖矿难度大不大 fil挖矿1T收益是多少

上游思维:用小行动获取反馈

石云升

读书笔记 8月日更 上游思维

3天倒计时!百度机器学习训练营正式开播啦!(加QQ群941354305)

有只小耳朵

人工智能 深度学习 学习 AI AI Studio

时序数据到底是什么,为什么我们需要时序数据库?

数据库 大数据 时序数据库 tsdb 数据智能

Springboot 结合 Netty 实战聊天系统

声网

音视频

10 个超棒的 JavaScript 简写技巧

前端依依

程序员 大前端 js 代码规范

Apache APISIX 在 Airwallex 的应用 | 专访 Airwallex 技术平台负责人李杨

API7.ai 技术团队

Apache 开源 案例分享 api 网关 APISIX

【六顶思考帽】学习心得

LeifChen

8月日更 六顶思考帽 创新思维

云计算成为趋势,北鲲云超算平台布局云计算市场?

北鲲云

【得物技术】浅谈Redis集群下mget的性能问题

得物技术

redis 性能优化 性能 redis集群 mget

如何利用 SEI 实现音画同步?

ZEGO即构

音视频 音画同步 数据流录制 flv

Fil火爆的原因是什么?fil未来价格会多少钱一枚?

分布式存储 IPFS fil fil价格 fil行情

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