NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

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

评论

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

全新升级!腾讯云大数据ES Serverless服务开启日志分析新体验

腾讯云大数据

elastic

在 React 中渲染大型数据集的 3 种方法

高端章鱼哥

Web windows React

AI+游戏,内容生产力的又一次变革

澳鹏Appen

人工智能 AR vr 生成式AI 游戏AI

saas堡垒机定义以及优势简单说明-行云管家

行云管家

SaaS 堡垒机 saas堡垒机

第二期开源答题挑战,看看你是什么级别吧!

开放原子开源基金会

开源 挑战 答题

软件测试 | mysqlhotcopy(MyISAM表热备份工具)

测吧(北京)科技有限公司

测试

首期"源规律"开源公益课程正式上线

开放原子开源基金会

开源 合规 法律法规

平台工程社区:与全球 2w+ 早期实践者同行

杨振涛

DevOps 云原生 社区 平台工程 平台工程师

让数据管理由繁至简的低代码开发平台

力软低代码开发平台

代码随想录Day36 - 贪心算法(五)

jjn0703

作为CTO,我真正想要的可观测性平台

JainChen

开发者 监控 可观测性

20 个编写清晰高效的 TypeScript 代码的技巧

这我可不懂

typescript 前端 代码

定档!WAVE SUMMIT 2023@全球开发者,8月16日北京见!

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨 百度飞桨

校源行 | 2023年开放原子校源行开源大使培训圆满结束,考试时间正式公布

开放原子开源基金会

开源

MIAOYUN获评“2023年度一云多芯稳定安全运行优秀案例”

MIAOYUN

解决方案 信创 中国信通院 信创云 可信云大会

软件测试 | mysqlshow(数据库对象查看工具)

测吧(北京)科技有限公司

测试

铜锁 SM2 算法性能优化实践(二)|快速模约减算法实现

铜锁开源密码库

开源 开发者 算法 同态加密 密码学

直击运维痛点,大数据计算引擎 EasyMR 的监控告警设计优化之路

袋鼠云数栈

监控 监控告警

安全文件传输的重要性及其对企业的影响

镭速

文件传输

校源行|开放原子开源社团(山东大学)授牌仪式隆重举行

开放原子开源基金会

开源 山东大学

如何通过Python线程池实现异步编程?

互联网工科生

Python 线程池

如何解决大量小文件传输慢的问题

镭速

小文件传输

【十万个等保小知识】等保测评报告是在等保整改之后发吗?

行云管家

等保 等级保护 等保测评 等保整改

如何为物联网设备注入“华为云+鸿蒙DNA”?

华为云开发者联盟

云计算 后端 华为云 华为云开发者联盟 企业号 8 月 PK 榜

站在营销的角度浅谈直播行业

山东布谷网络科技

直播 直播app 直播APP源码

LeetCode题解:剑指 Offer 56 - I. 数组中数字出现的次数,哈希表,JavaScript,详细注释

Lee Chen

JavaScript LeetCode

使用低代码平台提高生产力

树上有只程序猿

低代码 生产力 全栈开发 JNPF

软件测试 | 日志的删除

测吧(北京)科技有限公司

测试

利用文心千帆打造一个属于自己的小师爷

为自己带盐

大语言模型 文心千帆

基于低代码平台快速搭建应用

互联网工科生

低代码 低代码开发 JNPF java低代码开发平台

GPTCache 悬赏令!寻找最佳捉虫猎手,豪华赏格等你来拿!

Zilliz

Zilliz AIGC ChatGPT LLM gptcache

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