微服务介绍
在传统模式下,如果微服务之间要进行通信,那么程序需要自己处理各种通信的细节,这就包括服务发现、熔断机制、超时重试和 tracing 等功能。这些功能通常实现为与某种编程语言相关的 library,这也导致了这样的 library 无法在不同的编程语言之间共享。
更进一步,如果我们可以将这部分功能抽取出来,形成一个独立的进程,这样的进程称为 Sidecar。通常来说,我们会将应用程序和 Sidecar 部署在一起,那么程序的入口流量和出口流量都会由这个 Sidecar 去代理,这样就可以通过 Sidecar 去实现服务发现、熔断机制、超时重试等功能了。
Envoy Proxy 介绍
Envoy Proxy 可以用来充当 Sidecar 进程。通常来说,我们会将应用程序和 Envoy 部署在一起,形成一个微服务。另一方面,为了实现高可用,通常一个微服务会部署多份副本,这些副本加在一起,就形成了 Service Cluster。下图显示的就是服务与服务之间的通信:
除了可以充当 Sidecar 进程之外,Envoy Proxy 还可以充当反向代理,将流量转发给后端的 Service Cluster。充当反向代理的 Envoy,通常也可以称为 Edge Envoy。
构建程序镜像
在部署应用程序之前,需要先构建 Docker 镜像,下面是一个简单的 Flask 程序app.py
:
具体的 Dockerfile 以及构建镜像需要用到的命令,可以见这里。
在 K8S 部署微服务
这个微服务由两个进程组成,一个是 Envoy 进程(充当 Sidecar),另一个是 Flask 程序。Envoy 的作用其实很简单,就是监听 80 端口,并将接收到的foo.com
这个域名的全部流量都转发给 Flask 程序,下面是它的配置文件envoy.json
(稍后再解释 Envoy 配置文件的含义):
具体的 Kubernetes 配置文件放在了这里,git clone
这个项目,并执行下面的命令,部署微服务:
通常,在部署微服务时,会部署微服务的多个副本,形成 Service Cluster。例如,在部署之后,可以看到,Service Cluster 的名称为flask-app-envoy-service
:
同时也可以看到,这个 Service Cluster 中包含了 4 个相同的 Service:
动态服务发现
Envoy 自身并不支持服务发现,不过可以借助开源社区提供的插件 kubernetes-envoy-sds,实现服务发现。使用下面的命令,在 Kubernetes 中,部署这个插件(需要 Kubernetes 1.6 以上版本):
这个插件的名称为kubernetes-envoy-sds
,它部署在kube-system
这个 namespace 下面:
Envoy 充当反向代理
在部署好微服务之后,还需要部署一个 Envoy 充当反向代理(充当反向代理 Envoy,也称为 Edge Envoy),用来将foo.com
这个域名的流量转发给后端的 Flask Service Cluster。下面是 Edge Envoy 的配置文件envoy.json
:
这里解释一下 Envoy 的配置文件,可以看到,配置文件中有一个listener
,它负责监听 80 端口。注意到,listener
中包含了一个名为http_connection_manager
的filter
,这个filter
主要用来处理 HTTP 请求(包括 HTTP/1.1 and HTTP/2 协议)。filter
中最主要的配置就是virtual_hosts
,它定义了一系列的路由规则,用来指定如何将流量转发给后端的 Service Cluster。
例如,下面的配置会将foo.com
的所有流量,都转发给后端的 Flask Service Cluster:
另一个比较重要的配置就是clusters
,它定义了所有的后端 Service Cluster。一个 Service Cluster 中可以包含多个相同的 Service,Envoy 在转发流量给后端的 Service Cluster 时,允许指定负载均衡策略,例如下面的配置中,指定负载均衡策略为round_robin
:
既然在转发流量时,Envoy 可以指定负载均衡策略,那也就表示了 Envoy 必须知道 Service Cluster 中每个 Service 的 IP。即使当 Service Cluster 进行扩容或者缩容时,Envoy 也可以及时获取到每个 Service 的 IP。为了实现这一点,就需要动态的服务发现,所以type
参数需要指定为sds
。sds
其实就是我们前面说到的,用于实现动态服务发现的插件kubernetes-envoy-sds
,它的配置如下:
Kubernetes 配置文件放在了这里,git clone这个项目,并执行下面的命令,可以部署 Edge Envoy:
Edge Envoy 使用的是 NodePort 的方式暴露端口,可以看到它的端口为 32714:
假设集群内,有一个节点的 IP 为172.16.1.127
,那么可以使用下面的命令,测试 Edge Envoy 是否正常工作:
参考资料
- Envoy Proxy with Microservices
- Getting started with Lyft Envoy for microservices resilience
- Deploying Envoy with a Python Flask webapp and Kubernetes
- Deploying Envoy as an API Gateway for Microservices
- Thoughts on Envoy’s Design
- Microservices Patterns With Envoy Sidecar Proxy: Circuit breakers (Part I)
- Microservices Patterns With Envoy Sidecar Proxy: Retries / Timeouts (Part II)
- Microservices Patterns With Envoy Sidecar Proxy: Distributed Tracing (Part III)
- 在AWS上部署gRPC
- The mechanics of deploying Envoy at Lyft