37

用Envoy配置Service Mesh

 5 years ago
source link: http://dockone.io/article/8681?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【编者的话】

在这篇文章中,我们会简明扼要的介绍一下什么是"Service Mesh",以及如何使用"Envoy"构建一个"Service Mesh"。

那什么是Service Mesh呢?

Service Mesh在微服务架构体系中属于通信层。所有从微服务发出和收到的请求都会经过mesh。每个微服务都有一个自己的代理服务,所有的这些代理服务一起构成"Service mesh"

所以,如果微服务直间想进行相互调用,他们不是直接发生通信的,而是先将请求路由到本地的代理服务,然后代理服务将其路由到目标的微服务。实际上,微服务根本不了解外部世界,只和本地代理打交道。

IBJbEf6.png!web

当我们讨论ServiceMesh的时候,一定听说过一个词叫"sidecar", 它是一个在服务之间的代理程序,它负责为每一个服务实例服务

rqyiuaR.jpg!web

What does a Service Mesh provide?

1、ServiceService Discovery

2、Observability (metrics)

3、Rate Limiting

4、Circuit Breaking

5、Traffic Shifting

6、Load Balancing

7、Authentication and Authorisation

8、Distributed Tracing

Envoy

Envoy是一个用c++语言编写的高性能代理程序。不是一定要使用Envoy来构建ServiceMesh,其他的代理程序比如nginx、traefix也可以,但是在文本中,我们使用Envoy。

现在,我们来构建一个3个节点的service mesh,下面是我们的部署图:

IZRBRvQ.png!web

Front Envoy

"Front Envoy"是一个环境中的边缘代理,通常在这里执行TLS termination, authentication生成请求headers等操作…

下面是Front Envoy的配置信息:

主要由4部分组成:1、Listener 2、Routes 3、Clusters 4、Endpoints

1、Listeners

我们可以为一个Envoy配置1个或者多个listener,从配置文件的第9-36行,可以看到当前侦听器的地址和端口,并且每个listener可以有一个或多个network filter。通过这些过 filter,可以实现大多数功能,如routing, tls termination, traffic shifting等。"envoy.http_connection_manager"是我们在这里使用的内置filter之一,除了这个envoy还有其他几个filter。

2、Routes

第22-34行是route的相关配置,包括domain(应该接受request的域),以及与每个request匹配后发送到其适当集群中。

3、Clusters

Clusters段说明了Envoy将流量转发到哪个upstream Services

第41-50行定义了"service_a",这是"front envoy"将要与之通信的唯一的upstream service。

"connect_timeout"是指如果连接upstream服务器的时间超过了connect_timeout的制定,就会返回503错误。

通常会有多个"front envoy"实例,envoy支持多个负载平衡算法来路由请求。这里我们使用的是round robin。

Endpoints

"hosts"指定了我们会将流量转发到哪里,在本例中,我们只有一个Service_A。

在第48行,你可以发现,我们并不是把请求直接发送到service_A,而是发给了Service_A的Envoy代理service_a_envoy,然后将其路由到本地Service_a实例。

还可以注意到一个service的名字代表了所有的对应的实例,就类似Kubernetes里的面的headless service

我们在这里做一个客户端的负载均衡。Envoy缓存了所有ServiceA的实例,并且每5秒刷新一次。

Envoy支持主动和被动两种方式的健康检查。如果想使用主动方式,那就在cluster的配置信息里设置。

Others

第2-7行是关于管理方面的,比如日志级别,状态查看等。

第8行是"static_resources",意思是手动加载所有的配置选项,稍后的内容中我们会做详细介绍。

其实配置的选项还有很多,我们的目的不是介绍所有的选项及其含义,我们主要是想用一个最小的配置范例做一个入门介绍。

Service A

下面是一个Service A在Envoy的配置

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"

codec_type: "AUTO"

generate_request_id: true

route_config:

name: "local_route"

virtual_hosts:

-

name: "http-route"

domains:

- "*"

routes:

-

match:

prefix: "/"

route:

cluster: "service_a"

http_filters:

-

name: "envoy.router"

上面定义了一个listener,用于将流量路由到实际的"Service A"的实例,您可以在103–111上找到ServiceA实例的相应cluster定义。

"Service A"与"Service B"和"Service C"通信,因此分别创建两个listener和cluster。在这里,我们为每个upstream(localhost、service b和service c)都有单独的listener,另一种方法是创建一个listener,然后根据url或headers路由到upstream。

Service B & Service C

service B和service C是最下层的服务,除了和本地服务实例通信外,没有其他的upsteam,所以他们的配置信息比较简单,如下:

Service B

admin:

access_log_path: "/tmp/admin_access.log"

address:

socket_address:

address: "127.0.0.1"

port_value: 9901

static_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

Service C

admin:

access_log_path: "/tmp/admin_access.log"

address:

socket_address:

address: "127.0.0.1"

port_value: 9901

static_resources:

listeners:

-

name: "service-c-svc-http-listener"

address:

socket_address:

address: "0.0.0.0"

port_value: 8790

filter_chains:

-

filters:

-

name: "envoy.http_connection_manager"

config:

stat_prefix: "ingress"

codec_type: "AUTO"

route_config:

name: "service-c-svc-http-route"

virtual_hosts:

-

name: "service-c-svc-http-route"

domains:

- "*"

routes:

-

match:

prefix: "/"

route:

cluster: "service_c"

http_filters:

-

name: "envoy.router"

clusters:

-

name: "service_c"

connect_timeout: "0.25s"

type: "strict_dns"

lb_policy: "ROUND_ROBIN"

hosts:

-

socket_address:

address: "service_c"

port_value: 8083

可以看出Service B和Service C的配置没什么特别的,仅仅一个listener和一个cluster

至此,我们完成了所有的配置文件,现在可以把他们部署到kubernetes集群或者docker-compose里面了。运行"docker-compose build and docker-compose up" 并且访问"localhost:8080"端口。如果一切都没问题,那么http的访问请求会穿过所有的service和Envoy的proxy,并且在logs里可以看到这些记录。

Envoy xDS

我们完成了对sidecar的配置,设置了不同的service。如果我们仅仅有2到3个Sidecar和service的时候,手工配置还算ok,但是当服务的数量变得越来越多,手动配置几乎就是不太可能的了。并且一旦sidecar的配置改动后,还需要手动进行重启那就更麻烦了。

在刚开始我们提到过为了避免手工修改配置和加载组件,Clusters(CDS), Endpoints(EDS), Listeners(LDS) & Routes(RDS) 使用了api server。所以sidecar会从api server读取配置信息,并且会动态更新到sidecar里,而不是重启sidecar程序。

更多的关于动态配置可以点击这里查看,点击这里可以看到关于xDS的。

https://www.envoyproxy.io/docs ... namic

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

Kubernetes

这个小结中我们可以看到,如何在kubernetes集群中配置service mesh:

ZnErau2.png!web

所以我们需要做如下工作:

1、Pod

2、Service

Pod

通常情况下,一个pod里面之运行一个container,但其实在一个pod里可以运行多个container,因为我们想为每个service都运行一个sidecar的proxy,所以我们在每个Pod里都运行一个Envoy的container。所以为了和外界进行通信,service的container会通过本地网络(pod内部的local host)和Envoy Container进行通信。

在container配置段,我们可以看到关于sidecar的配置信息,我们在33到39行通过configmap mount了Envoy的配置。

(缺图)

Service

Kubernetes的service负责代理pod的路由转发信息。用kube-proxy作为负载均衡(译者注:现在早已经不是kube-proxy负载了) 。但是在我们的例子中,我们采用客户端负载均衡,所以我们不适用kuber-proxy,我们要得到所有运行sideproxy的pod的list,然后用"headless service"去负载。

(缺图)

第六行标注了service headless,你可以发现我们并没有mapping kubernetes的service 端口到应用的服务端口,而是mapping了Envoy的监听端口,所以流量会转发到Envoy。

通过以上的配置,service mesh应该可以运行在kubernetes里面了


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK