Envoy基础与快速入门-Day 02
本章主要讲envoy的基本理论和基本用法。
1. Envoy介绍
1.1 什么是Envoy
官方文档:https://www.envoyproxy.io/docs/envoy/latest/intro/what_is_envoy
Envoy本身是一种L7 层(HTTP、HTTPS)的反向代理,但同时它也支持L4层的模拟代理(tcp\UDP)。
所以说Envoy本身其实就是一个类似于nginx的反向代理应用。
# 官网介绍
Envoy 是一种 L7 代理和通信总线,专为大型现代面向服务的体系结构而设计。
为什么会有Envoy?主要是诞生于以下信念:
(1)网络应该对应用程序透明。
(2)当确实发生网络和应用程序问题时,应该很容易确定问题的根源。
1.2 高级功能
实际上,实现上述目标非常困难。Envoy 尝试通过提供以下高级功能来做到这一点。
(1)进程外架构
(2)L3/L4 过滤器架构
(3)HTTP L7 过滤器架构
(4)原生支持HTTP2
(5)支持HTTP/3 (目前为 alpha)
(6)HTTP L7 路由 # 服务网格中大部分的流量治理,指的就是这个
(7)原生支持gRPC
(8)服务发现和动态配置
(9)运行状况检查(健康检查) # Envoy支持主动健康检查和被动健康检查
(10)高级负载均衡
(11)前端/边缘(代理支持)
(12)一流的可观测性(内嵌的很多监控机制)
1.3 Envoy Data Path(Envoy工作特性)
首先,其实Envoy就是一个类似于nginx的反向代理,那么对于nginx来说,是有3种方式实现对请求的处理的:
# 虚拟主机
(1)基于端口:监听多个套接字,因为是同一个IP,但是端口不同。
(2)基于IP:监听多个套接字,但是IP不同
(3)基于域名(FQDN):在同一个套接字上,基于请求头报文中的主机头(HOST:)来判定目标虚拟主机。
对于Envoy而言,也是实现类似的方式,上面nginx支持的3种方式,Envoy也支持,只是叫法不同:
(1)Listeners
- 基于端口
- 基于IP
(2)VirtualService
- 基于域名(FQDN)
如下图:
# listeners
通过Listeners,也就是通过监听不同的套接字,来接入不同服务的请求。
# filter chains
随后,在Envoy内部,类似于nginx一样,通过串连多个不同的模块,来决定这个代理能实现什么功能,允许用户在配置文件中,指明使用的Envoy的哪些模块,为该类流量提供什么样的代理服务(流量处理机制)。这些模块,称之为filter(过滤器)。
因此,我们可以在任何一个套接字上,按我们的需要去拼接多个过滤器,来实现对流量的、不同功能的处理。
# cluster defintios
流量处理完了后,还需要指明把这些流量代理给上游的哪些服务(端点),所以这里还需要指明cluster。这里的cluster其实就是nginx中的upstream servers。
cluster这层除了可以配置什么样的流量去什么样的端点外,还可以配置如何对上游端点做健康检查(主动、被动)、连接池等相关配置。
# 总结部分
所以,前面的listeners和filter chains,可以被称之为路由部分,也就是流量治理的部分。
而cluster defintios,可以被称之为集群管理部分,集群管理有专门的集群管理器。
如何配置上面的listeners、filter chains和cluster defintios呢?
(1)直接修改Envoy的配置文件,然后重启Envoy,使得配置被加载。
(2)通过API接口来接收外部传递过来的配置信息(这就是之前说到的控制平面)。
有2种方式接收配置:
第一种:轮询。就是每隔一段时间主动询问控制平面是否有新的配置需要被加载。
第二种:建立一个双向的、始终在线的GRPC连接,一但控制平台有了新的配置,会立即推送给Envoy,然后由Envoy动态加载(立即生效)这些配置。
1.4 Envoy的几个显著特性
1.4.1 性能、可扩展性及动态配置性
(1)性能
除了大量的功能外,Envoy还提供极高的吞度量和低尾延迟差异,同时消耗相对较少的CPU和内存(用相对较少的资源消耗,来提供高性能的代理)。
(2)可扩展性
Envoy在L4和L7上提供丰富的可拔插过滤器功能,允许用户轻松添加新功能。
(3)动态配置(API可配置)
Envoy提供了一组可以由控制平面服务实现管理的API,也称为xDS API。
- 若控制平面实现了这所有的API,则可以使用通用引导配置在整个基础架构中运行Envoy。
- 所有进一步的配置更改都可以通过管理服务器无缝的进行动态传递,使得Envoy永远不需要重启。
- 于是,这使得Envoy成为一个通用数据平面,当与足够复杂的控制平面相结合时,可大大降低整体操作复杂性。
1.4.2 Envoy xDS API存在V1、 V2、V3等三个版本
(1)V1 API:仅使用JSON和REST,本质上就是轮询(性能差、配置可能存在延迟)
(2)V2 API:在V1版本上新增了一些特性,新的API模式使用proto3指定,并同时以gRPChe REST + JSON和YAML端点实现(2021年第一季度结束支持)
(3)V3 API:当前支持的版本,支持start_tls、拒绝传入的TCP连接、4096位tls秘钥、SkyWallking和WASM等。
1.4.3 小结
Envoy已成为现代 “服务网格” 和 “边缘网关” 的 “通用数据平面API”,ISTIO和Ambassador即Gloo等项目均是为此数据平面代理提供的控制平面。
2. Envoy组件拓扑与xDS API介绍
2.1 从单一的的Envoy实例来看
如下图这几个核心组件,实现下游到上游的连接。
下游:Downstream,通常指客户端。
上游:Upstream,通常指被代理的服务端。
为了能够接收客户端的流量,我们需要一个Listener(侦听器),同时,Listener支持额外的功能增强和配置,所以下图在Listener中还增加了一个用于实现过滤的过滤器Filters(专用与Listener功能扩展)。
当流量进来以后,可以交给我们串联起来的各类Filter,来实现流量的预处理,一旦处理完毕,就可以把这些流量路由(route)给上游端点(envoy中,上游服务都被称为端点endpoint)。
上游的每一个endpoint可以按照我们指定的方式被发现,并定义成不同的集群(如下图的2个cluster)。
不同的cluster可以有重复的endpoint和交叉的endpoint。
不管是由什么类型的Filter串联起来的Filter链,最终都应该由某一种叫route的过滤器,将流量路由给选定的cluster(会有很多种功能不同的路由器)。
Envoy的核心设计,主要就是面向http协议的,所以其内部的功能当中,特性最为丰富的,就是http协议的路由器(route)。
2.2 单一Envoy的详细说明
如下图:
在整个Envoy中,它支持基于xDS API,从各种各样的配置服务器上,接收不同类型的配置信息(就下面途中的那些discovery),反过来说就是Envoy允许这些配置服务通过xDS API发送配置过来。
但是为了便于管理,Envoy将可配置的配置信息,分成了多种不同类型的子类,每一个子类分别使用不同的配置服务器来配置。
而且为了区别它们是不同的配置信息,每一个类别的配置,会有一个专门的api。
xDS API简称(DS就是发现意思,如下图):
Listener Discovery Server:简称LDS(Listener侦听器)。下面的以此类推。
所以说,xDS API,其实就是由若干个子API组成的,统称xDS API。
这些配置API既可以通过不同的专用configuration Server获取配置,也可以由一个统一的Config Server提供配置。
2.3 DS 之间的依赖关系
并不是所有DS之间都有依赖关系
如:
路由RDS只能定义在LDS之上,因为流量是从LDS进来的。
端点EDS只能定义在集群CDS之上,因为如果发现端点,而没有配置集群CDS,那光有端点也没用,因为流量是按照集群CDS类别下发的。
换句话说,路由RDS只是LDS的一个子集,端点EDS也只是集群CDS的一个子集。
2.4 DS配置信息加载方式
(1)静态方式:直接配置在配置文件中。
(2)动态方式:通过XDS API动态加载
但是这里有个问题,就是如何知道配置服务器在哪儿,因此,还是需要提供配置文件(只包含了配置服务器地址和需要动态加载的配置)。
这种配置文件有一个专门的称呼:BootStarp Config File.
(3)动静混合
两种方式混合起来使用。
比如route动态加载,Listener静态配置,Cluster静态配置,Endpoint动态配置。
但是不管是什么方式,都要指定配置服务器的地址。
4. Envoy常用术语
官方文档:https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request#terminology
5. Envoy部署类型
官方文档:https://www.envoyproxy.io/docs/envoy/latest/intro/deployment_types/deployment_types
Envoy通常用于以容器编排系统为底层环境的服务网格中,并以sidecar的形式与主程序容器运行为单个Pod;
非编排系统环境中测试时,可以将主程序与Envoy运行于同一容器,或手动组织主程序容器与Envoy容器共享同一网络名称空间;
下图显示了最简单的 Envoy 部署,它使用 Envoy 作为面向服务的体系结构 (SOA) 内部所有流量的通信总线。
在此方案中,Envoy 公开了多个用于本地源流量以及服务到服务流量的侦听器。
5.1 仅服务到服务(网格内流量)
通常由服务网格控制平面通过自动注入机制,为每个pod自动添加边车容器。
5.1.1 Service to service ingress listener(服务到服务入口侦听器)
这种场景一般是集群内的A服务想要调用集群内的B服务。如下图:
当我们服务本身被其他服务请求时,这个请求会由Envoy代理并路由到我们服务本身,这个时候的Envoy扮演的就是入口侦听器的角色。
5.1.2 Service to service egress listener(服务到服务出口侦听器 )
当我们服务本身需要请求其他服务时,就会诞生一个出向的请求流量,这个流量会由服务本身的Envoy代理出去,这个时候的Envoy扮演的就是出口侦听器的角色,然后流量会到达被请求服务的Envoy入口侦听器,然后到被请求服务。
5.1.3 Optional external service egress listeners(可选的外部服务出口侦听器)
当网格内部的服务要访问网格外部(集群外部)的服务时,我们需要配置一个external service egress listeners,也就是外部服务出口侦听器,这样就可以在集群内部发现并访问集群外部的服务。
5.2 pod单独运行一个边缘代理Envoy(网关,南北向流量)
有规划的手动部署
就是在集群中以pod的形式,单独运行一个Envoy(非上面的边车模式),所有的集群外部请求都由该代理路由到对应的svc。
响应的出向流量也由该代理实现,但是集群内服务间的调用,不经过它了。
5.3 服务到服务加前置代理(边缘代理)
如下图:
客户端通过互联网发起HTTP请求,请求先到我们的边缘代理(front envoy),也称为入站网关,然后由边缘代理把客户端请求路由到具体的后端服务。
这个边缘代理Envoy工作模式和其他网格内部的代理Envoy工作模式完全相同,只是部署模式不同。
边缘代理的功能:
(1)终止TLS。
客户端请求到边缘代理时,会对数据进行加密传输,边缘代理收到后进行解密,然后以明文的方式发送到网格内部。
(2)支持 HTTP/1.1、HTTP/2 和 HTTP/3。
(3)完整的 HTTP L7 路由支持。
(4)通过Front-Envoy的Ingress接入请求,并结合发现服务与Service-to-Service的Envoy网格进行通信;
6. Envoy配置
6.1 配置概述
(1)启动时从Bootstrap配置文件中加载初始配置(静态配置)
(2)支持动态配置
xDS API
a. 从配置文件加载
b. 从管理服务器(Management Server)基于xds协议加载配置
runtime
a. 某些关键特性 (Feature flags) 保存为key/value数据
b. 支持多层配置和覆盖机制
(3)启用全动态配置机制后,仅极少数场景需要重新启动Envoy进程
- 支持热重启
6.2 配置方式
6.3 重要概念
BootStrap配置中几个重要的基础概念
关键字 | 描述 |
---|---|
node | 节点标识,就是指明这段配置信息是给那个节点使用的。 |
static_resources | 静态配置的资源,用于配置静态的listener、cluster和secret |
dynamic_resources | 动态配置的资源,用于配置基于xDS API获取listener、cluster和secret配置的lds_config、cds_config、ads_config。 |
admin | Envoy内置的管理接口。 |
tracing | 分布式跟踪。 |
layered_runtime | 层级化的运行时,支持使用RTDS从管理服务器动态加载。 |
hds_config | 使用HDS从管理服务器加载上游主机健康检测相关的配置。 |
overload_manager | 过载管理器。 |
stats_sinks | 统计信息接收器。 |
6.4 侦听器和集群配置基础
(1)侦听器
接收客户端请求的入口端点,通常由监听的套接字及调用的过滤器链所定义。
代理类的过滤器,负责路由请求,例如tcp-proxy和http_connection_manager等。
(2)集群
一组上游主机的逻辑组合。
每个主机映射为集群中的一个端点。
下游的请求被调度至上游主机。
如下图:
要让一个Envoy工作起来,得有Listeners和Cluster的定义,并且为了能够让流量能够路由到cluster,每个listerner内都会定义一串的filters,一般最后一个filter都是route或者proxy,由route把流量代理到指定的cluster。
cluster至少应该发现并找到一些endpoint,并在endpoint之上施加一些负载均衡策略,这样流量才能到达endpoint。
6.4.1 Listeners
(1)Envoy配置支持在单个进程中使用任意数量的侦听器。
独立部署时,建议每个主机仅部署单个Envoy实例,并在必要时于此实例上运行一到多个侦听器;
Enovy支持TCP和UDP两种类型的侦听器;
(2)每个侦听器都可以独立配置一定数量的网络层级(L3 /L4)过滤器,还可以引入L7过滤器。
侦听器收到的连接请求将由其过滤器链中的各过滤器进行处理。
L4过滤器的功能:
速率限制(Rate Limiting),也就是流量或者请求限制。
TLS客户端身份验证。
HTTP连接管理。
Raw TCP proxy(原始TCP代理)。
6.4.2 Upstream clusters
(1)Envoy可配置任意数量的上游集群,并使用Cluster Manager进行管理。
由集群管理器负责管理的各集群可以由用户静态配置,也可借助于API动态获取;
集群中的每个成员由endpoint进行标识,它可由用户静态配置,也可通过EDS或DNS服务动态发现;
# 发现配置方式
- Static:静态配置
- Strict DNS:严格DNS,Envoy将持续和异步地解析指定的DNS目标,并将DNS结果中的返回的每个IP地址视为上游集群中可用成员;
- LogicalDNS: 逻辑DNS,集群仅使用在需要启动新连接时返回的第一个IP地址,而非严格获取DNS查询的结果并假设它们构成整个上游集群;适用于必须通过DNS访问的大规模Web服务集群;
- Original destination:当传入连接通过iptables的REDIRECT或TPROXY target或使用代理协议重定向到Envov时,可以使用原始目标集群;
- Endpoint discovery service(EDS): EDS是一种基于GRPC或REST-SON API的xDS管理服务器获取集群成员的服务发现方式;
- Custom cluster: Envoy还支持在集群配置上的cluster_type字段中指定使用自定义集群发现机制;
(2)每个Cluster主要由集群名称,以及集群中的端点(通常是提供服务的IP地址和端口)所组成。
(3)Envoy Cluster支持纯静态定义方式来指定端点,也允许以动态方式发现各端点,甚至还支持自定义的发现机制。
(4)支持用户定义多种高级功能,例如:负载均衡策略、主动健康状态检查、被动健康状态检查和断路器等;
7. Envoy快速入门
7.1 部署方式
7.1.1 基于docker 镜像运行Envoy容器
官方文档:https://www.envoyproxy.io/docs/envoy/v1.23.12/start/install
Envoy项目为多种平台(例如amd64和arm64等) 维护有相应的Docker Image,我们可按需获取相应镜像后,以容器形式运行Envoy,而且它们存在以下几种变化形式:
- envoy: 基于Ubuntu Bionic制作的Docker Image;
- envoy-alpine和envoy-alpine-dev: 基于alpine制作的Docker Image;
- envoy-debug和envoy-debug-dev: 基于Ubuntu制作的带有debug环境的Docker Image;
- envoy-windows和envoy-windows-dev: 基于Windows 1809制作的Docker Image;
7.1.2 包管理器或者二进制
官方文档:https://www.envoyproxy.io/docs/envoy/v1.23.12/start/install
Get Envov项目为多个主流的Linux发行版(例如Ubuntu、CentOS和RHEL等) 维护了二进制的发行版,配置相应的仓库后,即可使用系统的包管理器进行安装;
7.2 部署Envoy过程中的常用命令
# 检查Envoy版本
envoy --version
# 获取帮助
envoy --help
# 检查配置文件语法是否有误
envoy --mode validate -c /path/to/my-envoy-config.yaml
# 运行envoy,并指定自定义的日志路径
envoy -c envoy-demo.yaml --log-path logs/custom.log
7.3 容器部署Envoy
7.3.1 下载资源清单
地址:https://github.com/iKubernetes/servicemesh_in_practise/tree/MageEdu_N66
[root@k8s-harbor01 ~]# ll -h servicemesh_in_practise-MageEdu_N66.zip
-rw------- 1 root root 21M 8月 28 16:02 servicemesh_in_practise-MageEdu_N66.zip
[root@k8s-harbor01 ~]# unzip servicemesh_in_practise-MageEdu_N66.zip
[root@k8s-harbor01 ~]# cd servicemesh_in_practise-MageEdu_N66/
[root@k8s-harbor01 servicemesh_in_practise-MageEdu_N66]# ll
总用量 40
drwxr-xr-x 11 root root 198 8月 5 2022 Cluster-Manager
drwxr-xr-x 7 root root 126 8月 5 2022 Dynamic-Configuration
drwxr-xr-x 10 root root 192 8月 5 2022 Envoy-Basics
drwxr-xr-x 5 root root 79 8月 5 2022 Envoy-TLS
drwxr-xr-x 10 root root 211 8月 5 2022 HTTP-Connection-Manager
-rw-r--r-- 1 root root 34523 8月 5 2022 LICENSE
drwxr-xr-x 11 root root 237 8月 5 2022 Monitoring-and-Tracing
-rw-r--r-- 1 root root 531 8月 5 2022 README.md
drwxr-xr-x 8 root root 125 8月 5 2022 Security
drwxr-xr-x 2 root root 57 8月 5 2022 template
7.3.2 示例:tcp proxy(L4 过滤器)
7.3.2.1 简介
TCP代理过滤器在下游客户端及上游集群之间执行1:1网络连接代理。
- 它可以单独用作隧道替换,也可以同其他过滤器(如MongoDB过滤器或速率限制过滤器) 结合使用;
- TCP代理过滤器严格执行由全局资源管理于为每个上游集群的全局资源管理器设定的连接限制;
- TCP代理过滤器检查上游集群的资源管理器是否可以在不超过该集群的最大连接数的情况下创建连接;
- TCP代理过滤器可直接将请求路由至指定的集群,也能够在多个目标集群间基于权重进行调度转发;
7.3.2.2 配置语法
{
"stat_prefix": "...", # 用于统计数据中输出时,使用的前缀字符;
"cluster": "...", # 路由到的目标集群标识
"weighted_clusters": "{...}",
"metadata_match": "{...}",
"idle_timeout": "{...}", # 上下游连接间的超时时长,既没有发送和接收报文的时长
"access_log": "[]", # 访问日志
"max_connect_attempts": "{...}" # 最大连接尝试次数
}
7.3.2.3 配置文件解读
[root@k8s-harbor01 servicemesh_in_practise-MageEdu_N66]# cd Envoy-Basics/tcp-front-proxy/
[root@k8s-harbor01 tcp-front-proxy]# ll
总用量 12
-rw-r--r-- 1 root root 934 8月 5 2022 docker-compose.yaml
-rw-r--r-- 1 root root 853 8月 5 2022 envoy.yaml
-rw-r--r-- 1 root root 465 8月 5 2022 README.md
[root@k8s-harbor01 tcp-front-proxy]# cat envoy.yaml
static_resources: # 静态资源配置
listeners: # 定义侦听器
name: listener_0 # 定义 侦听器 名称
address: # 定义 侦听器 地址
socket_address: { address: 0.0.0.0, port_value: 80 } # 具体地址为0.0.0.0:80
filter_chains: # 过滤器链列表,用于配置应用于请求的过滤器
- filters:
- name: envoy.tcp_proxy # 过滤器名称
typed_config: # 指定TCP代理过滤器的特定配置(不同版本的配置格式都不同,所以必须指定该配置字段)
"@type": type.googleapis.com/envoy.config.filter.network.tcp_proxy.v3.TcpProxy # 该扩展名称也必须指定
stat_prefix: tcp # 统计前缀,这样可以在统计数据中区分不同的TCP代理流量
cluster: test_cluster # 将请求转发到名为test_cluster的集群
# 总结起来,上面这段配置的作用是使用Envoy的TCP代理过滤器将TCP流量转发到名为test_cluster的集群中。
clusters: # 集群配置
- name: test_cluster # 集群名称,和filters中的cluster相关联
connect_timeout: 0.25s # 连接超时时间为0.25s
type: STATIC # 集群类型:静态(表示所有端点都是纯手动添加)
lb_policy: ROUND_ROBIN # 负载均衡策略:轮询(ROUND_ROBIN)
load_assignment: # 定义集群的负载分配配置
cluster_name: test_cluster # 集群的负载分配配置中指定的集群名称
endpoints: # 定义的端点
- lb_endpoints: # 负载端点
- endpoint:
address:
socket_address: { address: 172.31.1.11, port_value: 8080 } # 端点的地址:172.31.1.11:8080
- endpoint:
address:
socket_address: { address: 172.31.1.12, port_value: 8080 } # 端点的地址:172.31.1.12:8080
# 总的来说,这个配置文件的作用是将来自0.0.0.0:80的TCP流量通过TCP代理转发到名为test_cluster的集群中的两个端点上。
[root@k8s-harbor01 tcp-front-proxy]# cat docker-compose.yaml
# Author: MageEdu <mage@magedu.com>
# Site: www.magedu.com
version: '3.3'
services:
envoy:
image: envoyproxy/envoy:v1.23-latest
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
environment: # 容器启动时使用的用户:root
- ENVOY_UID=0
- ENVOY_GID=0
networks:
envoymesh: # 容器使用的网络
ipv4_address: 172.31.1.2
aliases:
- front-proxy
depends_on: # 依赖的服务
- webserver01
- webserver02
webserver01:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver01
networks:
envoymesh:
ipv4_address: 172.31.1.11
aliases:
- webserver01
webserver02:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver02
networks:
envoymesh:
ipv4_address: 172.31.1.12
aliases:
- webserver02
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.1.0/24
7.3.2.4 启动容器
[root@k8s-harbor01 tcp-front-proxy]# docker-compose up -d
[root@k8s-harbor01 tcp-front-proxy]# docker-compose ps
Name Command State Ports
--------------------------------------------------------------------------------
tcpfrontproxy_envoy_1 /docker-entrypoint.sh envo ... Up 10000/tcp
tcpfrontproxy_webserver01_1 /bin/sh -c python3 /usr/lo ... Up
tcpfrontproxy_webserver02_1 /bin/sh -c python3 /usr/lo ... Up
7.3.2.5 访问测试
[root@k8s-harbor01 tcp-front-proxy]# curl 172.31.1.2
iKubernetes demoapp v1.0 !! ClientIP: 172.31.1.2, ServerName: webserver02, ServerIP: 172.31.1.12!
[root@k8s-harbor01 tcp-front-proxy]# curl 172.31.1.2
iKubernetes demoapp v1.0 !! ClientIP: 172.31.1.2, ServerName: webserver01, ServerIP: 172.31.1.11!
# 从上面返回的结果,可以看到两次请求都是被代理到了不同的端点
7.3.2.6 清理环境
[root@k8s-harbor01 tcp-front-proxy]# docker-compose down
Stopping tcpfrontproxy_envoy_1 ... done
Stopping tcpfrontproxy_webserver02_1 ... done
Stopping tcpfrontproxy_webserver01_1 ... done
Removing tcpfrontproxy_envoy_1 ... done
Removing tcpfrontproxy_webserver02_1 ... done
Removing tcpfrontproxy_webserver01_1 ... done
Removing network tcpfrontproxy_envoymesh
7.3.3 示例:http proxy(L7 过滤器)
7.3.3.1 配置文件解读
[root@k8s-harbor01 tcp-front-proxy]# cd ..
[root@k8s-harbor01 Envoy-Basics]# cd http-front-proxy/
[root@k8s-harbor01 http-front-proxy]# ll
总用量 12
-rw-r--r-- 1 root root 818 8月 5 2022 docker-compose.yaml
-rw-r--r-- 1 root root 1535 8月 5 2022 envoy.yaml
-rw-r--r-- 1 root root 545 8月 5 2022 README.md
[root@k8s-harbor01 http-front-proxy]# cat envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager # http_connection_manager:是一个激活L7层http协议代理功能的L4层过滤器(这个name是不能自定义的,都是有固定的写法的)
typed_config: # 指定类型(指明对应的版本定义)
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager # 声明使用V3版本的http_connection_manager(v3.HttpConnectionManager),不同版本下面的参数语法也不通用的,需要注意,写法也是固定的(声明对应的版本语法)
stat_prefix: ingress_http # 统计数据前缀
codec_type: AUTO # 协议编码类型
route_config: # 路由配置
name: local_route # 路由名称
virtual_hosts: #虚拟主机配置
- name: web_service_1 # 虚拟主机名称
domains: ["*.ik8s.io", "ik8s.io"] # 域名配置
routes:
- match: { prefix: "/" } # 只要请求起始于/,就路由给下面的cluster
route: { cluster: local_cluster }
- name: web_service_2
domains: ["*.magedu.com",“magedu.com"]
routes:
- match: { prefix: "/" }
redirect: # 重定向配置,只要请求是起始于/,就把请求重定向到www.ik8s.io
host_redirect: "www.ik8s.io" # 这里就相当于上面的web_service_1
http_filters: # 上面的route部分要想生效,必须配置这里的7层过滤器
- name: envoy.filters.http.router # 名称(固定的,非自定义)
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router # 这里的版本也不能随便变更,否则可能会导致上面的语法出问题
clusters:
- name: local_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.31.2.11, port_value: 8080 }
- endpoint:
address:
socket_address: { address: 172.31.2.12, port_value: 8080 }
[root@k8s-harbor01 http-front-proxy]# cat docker-compose.yaml
version: '3.3'
services:
envoy:
image: envoyproxy/envoy:v1.23-latest
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
environment: # 容器启动时使用的用户:root
- ENVOY_UID=0
- ENVOY_GID=0
networks:
envoymesh:
ipv4_address: 172.31.2.2
aliases:
- front-proxy
depends_on:
- webserver01
- webserver02
webserver01:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver01
networks:
envoymesh:
ipv4_address: 172.31.2.11
aliases:
- webserver01
webserver02:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver02
networks:
envoymesh:
ipv4_address: 172.31.2.12
aliases:
- webserver02
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.2.0/24
7.3.3.2 启动容器
[root@k8s-harbor01 http-front-proxy]# docker-compose up -d
[root@k8s-harbor01 http-front-proxy]# docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
httpfrontproxy_envoy_1 /docker-entrypoint.sh envo ... Up 10000/tcp
httpfrontproxy_webserver01_1 /bin/sh -c python3 /usr/lo ... Up
httpfrontproxy_webserver02_1 /bin/sh -c python3 /usr/lo ... Up
7.3.3.3 访问测试
[root@k8s-harbor01 http-front-proxy]# curl -H "host: www.ik8s.io" 172.31.2.2
iKubernetes demoapp v1.0 !! ClientIP: 172.31.2.2, ServerName: webserver02, ServerIP: 172.31.2.12!
[root@k8s-harbor01 http-front-proxy]# curl -H "host: aaa.ik8s.io" 172.31.2.2
iKubernetes demoapp v1.0 !! ClientIP: 172.31.2.2, ServerName: webserver01, ServerIP: 172.31.2.11!
[root@k8s-harbor01 http-front-proxy]# curl -I -H "host: www.magedu.com" 172.31.2.2
HTTP/1.1 301 Moved Permanently
location: http://www.ik8s.io/
date: Mon, 28 Aug 2023 13:26:27 GMT
server: envoy
transfer-encoding: chunked
7.3.3.4 环境清理
[root@k8s-harbor01 http-front-proxy]# docker-compose down
7.3.4 示例:http-ingress(入向流量代理)
7.3.4.1 配置文件解读
[root@k8s-harbor01 http-front-proxy]# cd ../
[root@k8s-harbor01 Envoy-Basics]# cd http-ingress/
[root@k8s-harbor01 http-ingress]# ll -rt
总用量 12
-rw-r--r-- 1 root root 400 8月 5 2022 README.md
-rw-r--r-- 1 root root 1177 8月 5 2022 envoy.yaml
-rw-r--r-- 1 root root 555 8月 5 2022 docker-compose.yaml
[root@k8s-harbor01 http-ingress]# cat envoy.yaml
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager # 用于处理HTTP流量的HTTP连接管理器过滤器
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http # 指定统计前缀
codec_type: AUTO # 使用自动检测的编解码器类型
route_config: # 路由配置
name: local_route # 路由名称
virtual_hosts: # 虚拟主机
- name: web_service_1 # 虚拟主机名称
domains: ["*"] # 匹配所有域名
routes: # 路由规则
- match: { prefix: "/" } # 匹配所有
route: { cluster: local_cluster } # 凡是请求/的域名,都路由到local_cluster
http_filters: # 定义HTTP过滤器
- name: envoy.filters.http.router # 过滤器名称,这是一个基本的路由过滤器
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters: # 集群配置
- name: local_cluster # 集群名称
connect_timeout: 0.25s # 连接超时时间
type: STATIC # 集群类型:静态
lb_policy: ROUND_ROBIN # 负载均衡策略:轮询
load_assignment:
cluster_name: local_cluster # 集群名称
endpoints: # 集群端点
- lb_endpoints: # 被轮询的端点
- endpoint:
address:
socket_address: { address: 127.0.0.1, port_value: 8080 } # 由于业务pod中还有一个envoy proxy,而流量都是先打到envoy proxy上的,然后再由envoy proxy代理请求到业务pod,所以这里是127.0.0.1:8080(因为都在同一个pod中)
[root@k8s-harbor01 http-ingress]# cat docker-compose.yaml
version: '3'
services:
envoy:
image: envoyproxy/envoy:v1.23-latest
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
environment:
- ENVOY_UID=0
- ENVOY_GID=0
networks: # 使用的自定义网络
envoymesh:
ipv4_address: 172.31.3.2
aliases: # 别名
- ingress
webserver01:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
- HOST=127.0.0.1
network_mode: "service:envoy" # 这里webserver01和envoy要想以127.0.0.1通信,必须在同一个网络名称空间中。network_mode: "service:envoy"就表示webserver01将共享envoy的网络名称空间
depends_on:
- envoy
networks: # 自定义网络配置段
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.3.0/24
7.3.4.2 启动容器
[root@k8s-harbor01 http-ingress]# docker-compose up -d
Creating httpingress_envoy_1 ... done
Creating httpingress_envoy_1 ...
Creating httpingress_webserver01_1 ... done
[root@k8s-harbor01 http-ingress]# docker-compose ps
Name Command State Ports
------------------------------------------------------------------------------
httpingress_envoy_1 /docker-entrypoint.sh envo ... Up 10000/tcp
httpingress_webserver01_1 /bin/sh -c python3 /usr/lo ... Up
7.3.4.3 访问测试
[root@k8s-harbor01 http-ingress]# curl 172.31.3.2
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.1, ServerName: 169e38e30b2b, ServerIP: 172.31.3.2! # 这里ClientIP是127.0.0.1,这也就表示我们envoy是是通过127.0.0.1访问后端被代理的服务的
7.3.4.4 环境清理
[root@k8s-harbor01 http-ingress]# docker-compose down
7.3.5 示例:http-egress(出向流量代理)
7.3.5.1 配置文件解读
[root@k8s-harbor01 http-ingress]# cd ../http-egress/
[root@k8s-harbor01 http-egress]# ll
总用量 12
-rw-r--r-- 1 root root 979 8月 5 2022 docker-compose.yaml
-rw-r--r-- 1 root root 1344 8月 5 2022 envoy.yaml
-rw-r--r-- 1 root root 566 8月 5 2022 README.md
[root@k8s-harbor01 http-egress]# cat envoy.yaml
# Author: MageEdu <mage@magedu.com>
# Site: www.magedu.com
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 127.0.0.1, port_value: 80 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: web_service_1
domains: ["*"]
routes:
- match: { prefix: "/" }
route: { cluster: web_cluster }
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: web_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: web_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.31.4.11, port_value: 80 }
- endpoint:
address:
socket_address: { address: 172.31.4.12, port_value: 80 }
综上所述,上面的配置的作用是将通过listener_0侦听器接收到的HTTP流量,根据路由规则将其转发到名为web_cluster的集群中。该集群包含两个终端节点,分别是172.31.4.11:80和172.31.4.12:80,以实现负载均衡的效果。
[root@k8s-harbor01 http-egress]# cat docker-compose.yaml
# Author: MageEdu <mage@magedu.com>
# Site: www.magedu.com
version: '3.3'
services:
envoy:
image: envoyproxy/envoy:v1.23-latest
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
environment:
- ENVOY_UID=0
- ENVOY_GID=0
networks:
envoymesh:
ipv4_address: 172.31.4.2
aliases:
- front-proxy
depends_on:
- webserver01
- webserver02
client:
image: ikubernetes/admin-toolbox:v1.0
network_mode: "service:envoy"
depends_on:
- envoy
webserver01:
image: ikubernetes/demoapp:v1.0
hostname: webserver01
networks:
envoymesh:
ipv4_address: 172.31.4.11
aliases:
- webserver01
webserver02:
image: ikubernetes/demoapp:v1.0
hostname: webserver02
networks:
envoymesh:
ipv4_address: 172.31.4.12
aliases:
- webserver02
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.4.0/24
7.3.5.2 启动容器
[root@k8s-harbor01 http-egress]# docker-compose up -d
[root@k8s-harbor01 http-egress]# docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------
httpegress_client_1 /bin/sh -c sleep 999999 Up
httpegress_envoy_1 /docker-entrypoint.sh envo ... Up 10000/tcp
httpegress_webserver01_1 /bin/sh -c python3 /usr/lo ... Up
httpegress_webserver02_1 /bin/sh -c python3 /usr/lo ... Up
7.3.5.3 访问测试
[root@k8s-harbor01 http-egress]# docker exec -it httpegress_client_1 /bin/sh
[root@c6718d8c5c4f /]#
# 可以看到下面的2次请求,都分别被负载均衡到了不同的后端节点
[root@c6718d8c5c4f /]# curl 127.0.0.1
iKubernetes demoapp v1.0 !! ClientIP: 172.31.4.2, ServerName: webserver02, ServerIP: 172.31.4.12!
[root@c6718d8c5c4f /]# curl 127.0.0.1
iKubernetes demoapp v1.0 !! ClientIP: 172.31.4.2, ServerName: webserver01, ServerIP: 172.31.4.11!
7.3.5.4 环境清理
[root@c6718d8c5c4f /]# exit
[root@k8s-harbor01 http-egress]# docker-compose down
8. Envoy重要配置字段讲解与总结
8.1 基础部分总结
(1)Envoy
Envoy自己本身是工作在L7层的一个proxy(官方也是这样说明的),在7层它支持HTTP、HTTPS,还有Mongo、Mysql等filter。
但是,要想7层正常工作,必须要在L3或L4层,也就是网络层或传输层,去激活一些filter才行,比如常用的HTTP Connection Manager。
虽然看名称像是7层的HTTP Connection Manager,但实际上它是工作在4层的,将内核本身就能够处理的传输层以下的报文,再一次向上提升到应用层。
(2)调用filter
必须要指明name,并且要注意,各个filter.name,都有其固定的名称,也就是这个name是不能随便定义和修改的,如下:
- filters:
- name: envoy.filters.network.http_connection_manager
并且,各filter还需要适配不同的API版本,这个API版本也是固定的,不能随意更改(不同API版本语法参数不同),如下:
typed_config: # 下面这个@type,也是一个固定且必须使用的key,用来指明我们要使用的API版本
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager # 这是这个 v3.HttpConnectionManager ,现在基本都是V3,V1V2已经停止维护了
每个filter还可以引入其专用的配置参数,那这些配置参数就能形成一些新的、可以插入到我们配置文件当中的配置段,那些可以通过xDS API所发现的配置,通常不止一段配置的时候,每个配置段都可以已通过一个名称经进行标识,这个名称就没有什么固定的要求。如下:
listeners:
- name: listener_0
route_config:
name: local_route
clusters:
- name: web_cluster
8.2 Envoy工作逻辑
Envoy作为一个7层的反向代理来说,就相当于一个中介,连接着下游客户端(DownStream)和上游服务端(UPStream)。
Envoy面向下游客户端的时候,它必须要监听一个套接字(Socket),如下:
listeners:
- name: listener_0
address:
socket_address: { address: 127.0.0.1, port_value: 80 }
所以,Envoy需要通过一个listener来接入流量,而对listener而言(7层 HTTP代理),内部可以配置一到多个虚拟主机(virtual_hosts),凡是通过listener进来的请求,都会通过请求报文中的host,来获取请求的目标主机。:
virtual_hosts:
- name: web_service_1
domains: ["*.ik8s.io", "ik8s.io"]
而一个virtual_hosts内部,最为重要的一个配置,就是与该virtual_hosts相关的路由(route),只有配置了路由,Envoy才知道把请求代理到后端的哪一个集群中,如下:
routes:
- match: { prefix: "/" }
route: { cluster: web_cluster }
所以,对于下游来说,listeners这里最重要的几个配置,就是如下几个:
listeners.name.address.socket_address
filter_chains.filters # 注意:代理型的过滤器,在一个listeners中只需要配置一个
对于上游来说,重要的配置就是如下几个:
clusters.name # 集群名称
clusters.lb_policy # 负载均衡策略
clusters.load_assignment # 端点配置
clusters.type # 端点获取放回寺。有几种获取端点的配置如下:
(1)STATIC:手动配置。
(2)STRICT_DNS:会尝试把域名解析后的每一个IP地址,都配置为一个端点(适合局域网使用)。
(3)LOGICAL_DNS:和STRICT_DNS不同,只会解析后的第一个IP地址,配置为端点(适合跨互联网使用)。
(4)EDS:这是envoy原生的端点发现方式。
8.3 Envoy代理部署类型总结
Envoy部署分为3种类型:
(1)前端代理,也可成为边缘代理(Front/Edge Proxy)
这个时候它扮演的角色其实就是网关,但是网关也分为入向流量网关和出向流量网关。
(2)服务到服务(Service to Service Only)
这个时候的Envoy代理被称为:网格内部的数据平面(网格代理),这个时候每一个实例(服务),都应该有一个专属的代理,就是前面说的边车模式的pod。
如果按照侦听器划分,那就是:
Ingress Listener:入向流量侦听器,负责反向代理
Egress Listener:出向流量侦听器,负责正向代理
(3)Egress Listener To External:出向流量正向代理到集群外部服务
这个是可选的,不一定必须得要。
网关分类,就是说边缘代理,也可以分为2种类型:
(1)Ingress Gateway:入向流量网关
(2)Egress Gateway:出向流量网关
当我们不需要对出向流量做什么特殊处理的时候,其实只需要有入向流量网关就够了。
如果需要对出向流量做治理的时候,才需要出向流量网关
9. 扩展:Admin管理接口和Layered Runtime基础
9.1 Admin管理接口
官方文档:https://www.envoyproxy.io/docs/envoy/v1.23.12/operations/admin.html#administration-interface
9.1.1 介绍
Envoy内建了一个管理服务(administration server),它支持查询和修改操作。
但是它本身没有任何安全机制,有可能暴露私有数据(例如统计数据、集群名称和证书信息等),因此非常有必要精心编排其访问控制机制以避免非授权访问。
admin:
access_log: [] # 访问日志协议的相关配置,通常需要指定日志过滤器及日志配置等;
access_log_path: # 管理接口的访问日志文件路径,无须记录访问日志时可使用/dev/null;
profile_path: # cpu profile 的输出路径,默认为/var/log/envoy/envoy.prof
address: # 监听的套接字;
socket_address:
protocol:
address:
port_value:
# 配置示例
admin:
access_log: /tmp/admin_access.log
address:
socket_address: { address: 0.0.0.0, port_value: 9901 } # 此处仅为了方便测试,才监听0.0.0.0,正常来说,应该使用127.0.0.1,或者人为的把9901加上认证机制。
9.1.2 管理接口 admin速览
admin接口内置了多个/path,不同的path可能会分别接受不同的GET或POST请求;
9.1.3 配置Envoy的管理接口
9.1.3.1 添加配置
[root@k8s-harbor01 ~]# cd servicemesh_in_practise-MageEdu_N66/Envoy-Basics/admin-interface/
[root@k8s-harbor01 admin-interface]# ls
docker-compose.yaml envoy.yaml README.md
[root@k8s-harbor01 admin-interface]# cat envoy.yaml
admin: # 就admin这几行,就是开启管理接口。其他配置不用变
# 下面的profile_path和access_log_path如果不需要的话,一定要配置为/dev/null
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: web_service_1
domains: ["*.ik8s.io", "ik8s.io"]
routes:
- match: { prefix: "/" }
route: { cluster: local_cluster }
- name: web_service_2
domains: ["*.magedu.com",“magedu.com"]
routes:
- match: { prefix: "/" }
redirect:
host_redirect: "www.ik8s.io"
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: local_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.31.5.11, port_value: 8080 }
- endpoint:
address:
socket_address: { address: 172.31.5.12, port_value: 8080 }
# 这个docker配置文件不变
[root@k8s-harbor01 admin-interface]# cat docker-compose.yaml
version: '3.3'
services:
envoy:
image: envoyproxy/envoy:v1.23-latest
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
environment:
- ENVOY_UID=0
- ENVOY_GID=0
networks:
envoymesh:
ipv4_address: 172.31.5.2
aliases:
- front-proxy
depends_on:
- webserver01
- webserver02
webserver01:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver01
networks:
envoymesh:
ipv4_address: 172.31.5.11
aliases:
- webserver01
webserver02:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver02
networks:
envoymesh:
ipv4_address: 172.31.5.12
aliases:
- webserver02
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.5.0/24
9.1.3.2 启动容器
[root@k8s-harbor01 admin-interface]# docker-compose up -d
Creating admininterface_webserver01_1 ... done
Creating admininterface_webserver02_1 ... done
Creating admininterface_webserver01_1 ...
Creating admininterface_envoy_1 ... done
[root@k8s-harbor01 admin-interface]# docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
admininterface_envoy_1 /docker-entrypoint.sh envo ... Up 10000/tcp
admininterface_webserver01_1 /bin/sh -c python3 /usr/lo ... Up
admininterface_webserver02_1 /bin/sh -c python3 /usr/lo ... Up
9.1.3.3 访问测试
[root@k8s-harbor01 admin-interface]# curl 172.31.5.2:9901/help # 下面返回了很多可以访问的path
admin commands are:
/: Admin home page
/certs: print certs on machine
/clusters: upstream cluster status
/config_dump: dump current Envoy configs (experimental)
/contention: dump current Envoy mutex contention stats (if enabled)
/cpuprofiler: enable/disable the CPU profiler
/drain_listeners: drain listeners
/healthcheck/fail: cause the server to fail health checks
/healthcheck/ok: cause the server to pass health checks
/heapprofiler: enable/disable the heap profiler
/help: print out list of admin commands
/hot_restart_version: print the hot restart compatibility version
/init_dump: dump current Envoy init manager information (experimental)
/listeners: print listener info
/logging: query/change logging levels
/memory: print current allocation/heap usage
/quitquitquit: exit the server
/ready: print server state, return 200 if LIVE, otherwise return 503
/reopen_logs: reopen access logs
/reset_counters: reset all counters to zero
/runtime: print runtime values
/runtime_modify: modify runtime values
/server_info: print server version/status information
/stats: print server stats
/stats/prometheus: print server stats in prometheus format
/stats/recentlookups: Show recent stat-name lookups
/stats/recentlookups/clear: clear list of stat-name lookups and counter
/stats/recentlookups/disable: disable recording of reset stat-name lookup names
/stats/recentlookups/enable: enable recording of reset stat-name lookup names
1.3.4 比较重要的几个接口
/config_dump # GET 打印Envoy加载的各类配置信息,支持include_eds、master和resource等查询参数
/listners # GET 列出所有侦听器,支持使用“GET /listners?format=json”
/clusters # GET 额外支持使用 "GET /clusters?format=json"
/stats # 按需输出统计数据,例如 GET /stats?filter=regex,另外还支持json和prometheus格式
/stats/prometheus # 输出Prometheus统计信息
/drain_listners # POST 驱逐所有listner,支持使用inboundonly(仅入站侦听器)和graceful(优雅关闭)等查询参数;
/runtime # GET 以json格式输出所有运行时相关值
/runtime_modify # POST 修改运行时参数接口之一
/server_info
9.2 Envoy运行时配置
官方文档:https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime.html
9.2.1 介绍
(1)相较于静态资源配置来说,xDS API的动态配置机制使得Envoy的配置系统极具弹性;
- 但有时候配置的变动仅需要修改个别的功能特性,若通过xDS接口完成未免有些动静过大,Runtime便是面向这种场景的配置接口;
- Runtime就是一个虚拟文件系统树,可通过一至多个本地文件系统目录、静态资源、RTDS动态发现和Admin Interface进行定文和配置;
- 每个配置称为一个Layer,因而也称为"Layered Runtime",这些Layer最终叠加生效;
(2)换句话说,Runtime是与Envoy一起部署的外置实时配置系统,用于支持更改配置设置而无需重启Envov或更改主配置;
- 运行时配置相关的运行时参数也称为“功能标志 (feature flags)” 或“决策者 (decider)” ;
- 通过运行时参数更改配置将实时生效;
(3)运行时配置的实现也称为运行时配置供应者;
- Envoy当前支持的运行时配置的实现是由多个层级组成的虚拟文件系统;
- Envoy在配置的目录中监视符号链接的交换空间,并在发生交换时重新加载文件树;
- 但Envoy会使用默认运行时值和“null”提供给程序以确保其正确运行,因此,运行时配置系统并不必不可少;
9.2.2 如何配置Envoy运行时环境
启用Envov的运行时配置机制,需要在Bootstrap文件中予以启用和配置;
- 定义在bootstrap配置文件中的layered_runtime顶级字段之下;
- 一旦在bootstrap中给出layered_runtime字段,则至少要定义出一个layer;
# 示例
layered_runtime: # 运行配置供应者,未指定时则使用null供应者,即所有参数均加载其默认值;
layers: # 运行时的层级列表,后面的层将覆盖先前层上的配置;
- name: static_layer_0 # 运行时的层级名称,仅用于“GET/runtime”时的输出;
static_layer: {...} # 静态运行时层级,遵循运行时probobuf JSON编码格式,不同于静态的xDS资源,静态运行时层一样可被后面的层所覆盖;
disk_layer: {...} # 基于本地磁盘的运行时层级;
symlink_root: ... # 通过符号链接访问的文件系统树;
subdirectory: ... # 指定要在根目录中加载的子目录;
append_service_cluster: # 是否将服务集群附加至符号链接根目录下的子路径上;
admin_layer: {...} # 管理控制台运行时层级,即通过/runtime管理端点查看,通过/runtime_modify管理端点修改的配置方式;
rtds_layer: {...} # 运行时发现服务(runtime discovery service)层级,即通过xDS API中的RTDS API动态发现相关的层级配置;
name: ... # 在rtds_config上为RTDS层订阅的资源;
rtds_config: ... # RTDS的ConfigSource
9.2.3 部署示例
9.2.3.1 配置文件
[root@k8s-harbor01 layered-runtime]# cat envoy.yaml
# Author: MageEdu <mage@magedu.com>
# Version: v1.0.2
# Site: www.magedu.com
#
admin:
profile_path: /tmp/envoy.prof
access_log_path: /tmp/admin_access.log
address:
socket_address:
address: 0.0.0.0
port_value: 9901
layered_runtime:
layers:
- name: static_layer_0
static_layer:
health_check:
min_interval: 5
- name: admin_layer_0
admin_layer: {}
static_resources:
listeners:
- name: listener_0
address:
socket_address: { address: 0.0.0.0, port_value: 80 }
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
codec_type: AUTO
route_config:
name: local_route
virtual_hosts:
- name: web_service_1
domains: ["*.ik8s.io", "ik8s.io"]
routes:
- match: { prefix: "/" }
route: { cluster: local_cluster }
- name: web_service_2
domains: ["*.magedu.com",“magedu.com"]
routes:
- match: { prefix: "/" }
redirect:
host_redirect: "www.ik8s.io"
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
clusters:
- name: local_cluster
connect_timeout: 0.25s
type: STATIC
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: local_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address: { address: 172.31.14.11, port_value: 8080 }
- endpoint:
address:
socket_address: { address: 172.31.14.12, port_value: 8080 }
[root@k8s-harbor01 layered-runtime]# cat docker-compose.yaml
version: '3.3'
services:
envoy:
image: envoyproxy/envoy:v1.23-latest
volumes:
- ./envoy.yaml:/etc/envoy/envoy.yaml
environment:
- ENVOY_UID=0
- ENVOY_GID=0
networks:
envoymesh:
ipv4_address: 172.31.14.2
aliases:
- front-proxy
depends_on:
- webserver01
- webserver02
webserver01:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver01
networks:
envoymesh:
ipv4_address: 172.31.14.11
aliases:
- webserver01
webserver02:
image: ikubernetes/demoapp:v1.0
environment:
- PORT=8080
hostname: webserver02
networks:
envoymesh:
ipv4_address: 172.31.14.12
aliases:
- webserver02
networks:
envoymesh:
driver: bridge
ipam:
config:
- subnet: 172.31.14.0/24
9.2.3.2 启动容器
[root@k8s-harbor01 layered-runtime]# docker-compose up -d
[root@k8s-harbor01 layered-runtime]# docker-compose ps
Name Command State Ports
---------------------------------------------------------------------------------
layeredruntime_envoy_1 /docker-entrypoint.sh envo ... Up 10000/tcp
layeredruntime_webserver01_1 /bin/sh -c python3 /usr/lo ... Up
layeredruntime_webserver02_1 /bin/sh -c python3 /usr/lo ... Up
9.2.4 调用runtime接口获取数据
9.2.4.1 查看默认数据
[root@k8s-harbor01 layered-runtime]# curl 172.31.14.2:9901/runtime
{
"entries": {
"health_check.min_interval": {
"final_value": "5",
"layer_values": [
"5",
""
]
}
},
"layers": [ # 从这里可以看到有2个layer
"static_layer_0",
"admin_layer_0"
]
}
9.2.4.2 修改健康检查时间为10s
[root@k8s-harbor01 layered-runtime]# curl -XPOST 172.31.14.2:9901/runtime_modify?health_check.min_interval=10
OK
[root@k8s-harbor01 layered-runtime]# curl 172.31.14.2:9901/runtime
{
"layers": [
"static_layer_0",
"admin_layer_0"
],
"entries": {
"health_check.min_interval": {
"final_value": "10",
"layer_values": [
"5",
"10"
]
}
}
}
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)