3、Envoy使用案例
Envoy使用案例
目录
[toc]
本节实战
实战名称 |
---|
🚩 实战:前端代理-2023.11.2(测试成功) |
🚩 实战:流量镜像-2023.11.4(测试成功) |
🚩 实战:故障注入过滤器-2023.11.4(测试成功) |
🚩 实战:MySQL 过滤器-2023.11.4(测试成功) |
🚩 实战:Golang HTTP 过滤器-2023.11.4(测试成功) |
前言
前面我们已经学习了 Envoy 的基础知识,接下来我们就可以来学习如何使用 Envoy 来进行流量管理了。Envoy 作为一个高性能的边缘和内部代理,可以用于许多不同的场景。在本节中,我们将介绍 Envoy 的流量管理功能,包括路由、负载平衡、故障转移、故障注入、速率限制和等方面。
这些案例都位于 Envoy 官方代码仓库中的 examples目录下,我们可以在这里找到各种使用案例。
所以我们可以先 Clone 一份 Envoy 的代码仓库到本地,然后在本地的 examples 目录下面找到对应的案例进行学习。
$gitclonehttps:- name:www2domains:- "*"routes:- match:prefix:/runtime_fraction:# 额外匹配指定的运行时键值,每次评估匹配路径时,它必需低于此字段指示的匹配百分比;支持渐进式修改;default_value:numerator:50denominator:HUNDREDruntime_key:routing.traffic_shift.helloworldroute:cluster:helloworld_v1- match:prefix:/route:cluster:helloworld_v2
Envoy 使用首个匹配策略来匹配路由。如果路由具有 runtime_fraction
对象,则将基于 runtime_fraction
值额外匹配请求(如果未指定值,则为默认值)。上面的配置中我们可以看到在第一条路由中指定了 runtime_fraction
对象,可以通过更改 runtime_fraction
值来实现流量转移。
首先,将 routing.traffic_shift.helloworld
设置为 100
,这样对于 helloworld
虚拟主机的所有请求,都将与 v1
路由匹配,并由 helloworld_v1
集群提供服务。
要开始转移流量到 helloworld_v2
集群,将 routing.traffic_shift.helloworld
的值设置为 0 <x <100
。例如设置为 90
,此时到 helloworld
虚拟主机的每 10 个请求中有 1 个请求将与 v1
路由不匹配,并将进入 v2
路由。
逐渐减少 routing.traffic_shift.helloworld
的值以便更大比例的请求与 v2
路由匹配。
当 routing.traffic_shift.helloworld
的值设置为 0 时,没有到 helloworld
虚拟主机的请求与 v1 路由匹配。所有流量此时会进入 v2
路由,由 helloworld_v2
集群提供服务。
2.跨多个上游的流量拆分
现在我们有三个(v1、v2 和 v3)而不是两个版本。可以使用 weighted_clusters
选项可以用来指定每个上游集群的权重来在三个版本之间平均分配流量(比如 33%、33%、34%)。
与前面的示例不同,一个路由条目就够了。路由中的 weighted_clusters
配置块可用于指定多个上游集群以及每个上游集群的权重。
virtual_hosts:- name:www2domains:- "*"routes:- match:{prefix:/}route:weighted_clusters:runtime_key_prefix:routing.traffic_split.helloworldclusters:- name:helloworld_v1weight:33- name:helloworld_v2weight:33- name:helloworld_v3weight:34
默认情况下,权重的和必须等于 100。然后就可以通过运行时变量
routing.traffic_split.helloworld.helloworld_v1
、
routing.traffic_split.helloworld.helloworld_v2
和
routing.traffic_split.helloworld.helloworld_v3
对每个集群的权重进行动态地调整。
2、前端代理
==🚩 实战:前端代理-2023.11.2(测试成功)==
实验环境:
DockerComposeversionv2.23.0docker20.10.21-ce(具有docker环境)
实验软件:
这些案例大部分都是基于官方提供的一个 Front proxy来进行演示的,该示例可以使用 Docker Compose 进行管理,其将部署一个前置 Envoy 和几个后端服务(简单的 aiohttp
应用程序),如下图所示:
所有传入请求都通过前端 Envoy 进行路由,前端 Envoy 充当位于 envoymesh
网络边缘的反向代理。 Docker Compose 将端口 8080、8443 和 8001 三个端口,分别处理对服务的 HTTP、HTTPS 调用和对 /admin
的请求,docker-compose.yml
文件内容如下所示:
services:front-envoy:build:context:.dockerfile:../shared/envoy/Dockerfiledepends_on:service-envoy-1:condition:service_healthyservice-envoy-2:condition:service_healthyports:- "${PORT_PROXY:-8080}:8080"- "${PORT_HTTPS:-8443}:8443"- "${PORT_STATS:-8001}:8001"service-envoy-1:build:context:.dockerfile:../shared/envoy/Dockerfiletarget:envoy-adminargs:ENVOY_CONFIG:./service-envoy.yamlENVOY_ADMIN_PORT:8001depends_on:service1:condition:service_healthyservice1:build:context:../shared/pythontarget:aiohttp-tracing-service2environment:- SERVICE_NAME=1service-envoy-2:build:context:.dockerfile:../shared/envoy/Dockerfiletarget:envoy-adminargs:ENVOY_ADMIN_PORT:8001ENVOY_CONFIG:./service-envoy-2.yamldepends_on:service2:condition:service_healthyservice2:build:context:../shared/pythontarget:aiohttp-tracing-service2environment:- SERVICE_NAME=2
Front Envoy 路由到服务容器的所有流量实际上都被路由到 Service Envoy 上,对应的 envoy.yaml
配置如下所示:
# envoy.yamlstatic_resources:listeners:- address:socket_address:address:0.0.0.0port_value:8080filter_chains:- filters:- name:envoy.filters.network.http_connection_managertyped_config:"@type":type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagercodec_type:AUTOstat_prefix:ingress_httproute_config:name:local_routevirtual_hosts:- name:backenddomains:- "*"routes:- match:prefix:"/service/1"route:cluster:service1-envoy- match:prefix:"/service/2"route:cluster:service2-envoyhttp_filters:- name:envoy.filters.http.routertyped_config:"@type":type.googleapis.com/envoy.extensions.filters.http.router.v3.Router- address:socket_address:address:0.0.0.0port_value:8443filter_chains:- filters:- name:envoy.filters.network.http_connection_managertyped_config:"@type":type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagercodec_type:AUTOstat_prefix:ingress_httproute_config:name:local_routevirtual_hosts:- name:backenddomains:- "*"routes:- match:prefix:"/service/1"route:cluster:service1-envoy- match:prefix:"/service/2"route:cluster:service2-envoyhttp_filters:- name:envoy.filters.http.routertyped_config:"@type":type.googleapis.com/envoy.extensions.filters.http.router.v3.Routertransport_socket:name:envoy.transport_sockets.tlstyped_config:"@type":type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContextcommon_tls_context:tls_certificates:# The following self-signed certificate pair is generated using:# $ openssl req -x509 -newkey rsa:2048 -keyout a/front-proxy-key.pem -out a/front-proxy-crt.pem -days 3650 -nodes -subj '/CN=front-envoy'## Instead of feeding it as an inline_string,certificate pair can also be fed to Envoy# via filename. Reference:https:## Or in a dynamic configuration scenario,certificate pair can be fetched remotely via# Secret Discovery Service (SDS). Reference:https:- certificate_chain:inline_string:|-----BEGIN CERTIFICATE-----MIICqDCCAZACCQCquzpHNpqBcDANBgkqhkiG9w0BAQsFADAWMRQwEgYDVQQDDAtmcm9udC1lbnZveTAeFw0yMDA3MDgwMTMxNDZaFw0zMDA3MDYwMTMxNDZaMBYxFDASBgNVBAMMC2Zyb250LWVudm95MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAthnYkqVQBX+Wg7aQWyCCb87hBce1hAFhbRM8Y9dQTqxoMXZiA2n8G089hUouoQpEdJgitXVS6YMFPFUUWfwcqxYAynLK4X5im26Yfa1eO8La8sZUS+4Bjao1gF5/VJxSEo2yZ7fFBo8M4E44ZehIIocipCRS+YZehFs6dmHoq/MGvh2eAHIa+O9xssPtofFcQMR8rwBHVbKy484O10tNCouX4yUkyQXqCRy6HRu7kSjOjNKSGtjfG+h5M8bh10W7ZrsJ1hWhzBulSaMZaUY3vh5ngpws1JATQVSK1Jm/dmMRciwlTK7KfzgxHlSX58ENpS7yPTISkEICcLbXkkKGEQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCmj6HgvwOxWz0xu+6fSfRL6PGJUGq6wghCfUvjfwZ7zppDUqU47fk+yqPIOzuGZMdAqi7Nv1DXkeO4A3hnMD22Rlqt25vfogAaZVToBeQxCPd/ALBLFrvLUFYuSlS3zXSBpQqQNy2IKFYsMllz5RSROONHBjaJOn5OwqenJ91MPmTAG7ujXKN6INSBM0PjX9Jy4Xb9zT+I85jRDQHnTFce1WICBDCYidTIvJtdSSokGSuy4/xyxAAc/BpZAfOjBQ4G1QRe9XwOi790LyNUYFJVyeOvNJwveloWuPLHb9idmY5YABwikUY6QNcXwyHTbRCkPB2Im+/R4XnmL4cKQ+5Z-----END CERTIFICATE-----private_key:inline_string:|-----BEGIN PRIVATE KEY-----MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2GdiSpVAFf5aDtpBbIIJvzuEFx7WEAWFtEzxj11BOrGgxdmIDafwbTz2FSi6hCkR0mCK1dVLpgwU8VRRZ/ByrFgDKcsrhfmKbbph9rV47wtryxlRL7gGNqjWAXn9UnFISjbJnt8UGjwzgTjhl6EgihyKkJFL5hl6EWzp2Yeir8wa+HZ4Achr473Gyw+2h8VxAxHyvAEdVsrLjzg7XS00Ki5fjJSTJBeoJHLodG7uRKM6M0pIa2N8b6HkzxuHXRbtmuwnWFaHMG6VJoxlpRje+HmeCnCzUkBNBVIrUmb92YxFyLCVMrsp/ODEeVJfnwQ2lLvI9MhKQQgJwtteSQoYRAgMBAAECggEAeDGdEkYNCGQLe8pvg8Z0ccoSGpeTxpqGrNEKhjfi6NrBNwyVav10iq4FxEmPd3nobzDPkAftfvWc6hKaCT7vyTkPspCMOsQJ39/ixOk+jqFxlNa1YxyoZ9IV2DIHR1iaj2Z5gB367PZUoGTgstrbafbaNY9IOSyojCIO935ubbcxDWwL24XAf51ez6sXnI8V5tXmrFlNXhbhJdH8iIxNyM45HrnlUlOk0lCK4gmLJjy910IS2H2Wh3M5zsTpihH1JvM56oAH1ahrhMXs/rVFXXkg50yD1KV+HQiEbglYKUxOeMYtfaY9i2CuLwhDnWp3oxP3HfgQQhD09OEN3e0IlQKBgQDZ/3poG9TiMZSjfKqLxnCABMXGVQsfFWNC8THoW6RRx5Rqi8q08yJrmhCu32YKvccsOljDQJQQJdQO1g09e/adJmCnTrqxNtjPkX9txV23Lp6Ak7emjiQ5ICu7iWxrcO3zf7hmKtj7z+av8sjOmDI7NkX5vnlE74nztBEjp3eC0wKBgQDV2GeJV028RW3b/QyP3Gwmax2+cKLR9PKRnJnmO5bxAT0nQ3xuJEAqMIss/Rfb/macWc2N/6CWJCRT6a2vgy6xBW+bqG6RdQMBxEZXFZl+sSKhXPkc5Wjb4lQ14YWyRPrTjMlwez3k4UolIJhJmwl+D7OkMRrOUEROEtUvc7odCwKBgBi+nhdZKWXveM7B5N3uzXBKmmRz3MpPdC/yDtcwJ8u8msUpTv4RJxQNrd0bsIqBli0YBmFLYEMg+BwjAee7vXeDFq+HCTv6XMva2RsNryCO4yD3I359XfE6DJzB8ZOUgv4Dvluie3TB2Y6ZQV/p+LGt7G13yG4hvofyJYvlg3RPAoGAcjDg+OH5zLN2eqah8qBN0CYa9/rFt0AJ19+7/smLTJ7QvQq4g0gwS1couplcCEnNGWiK72y1n/ckvvplmPeAE19HveMvR9UoCeV5ej86fACy8V/oVpnaaLBvL2aCMjPLjPP9DWeCIZp8MV86cvOrGfngf6kJG2qZTueXl4NAuwkCgYEArKkhlZVXjwBoVvtHYmN2o+F6cGMlRJTLhNc391WApsgDZfTZSdeJsBsvvzS/Nc0burrufJg0wYioTlpReSy4ohhtprnQQAddfjHP7rh2LGt+irFzhdXXQ1ybGaGM9D764KUNCXLuwdly0vzXU4HUq5sGxGrC1RECGB5Zwx2S2ZY=-----END PRIVATE KEY-----clusters:- name:service1-envoytype:STRICT_DNSlb_policy:ROUND_ROBINload_assignment:cluster_name:service1-envoyendpoints:- lb_endpoints:- endpoint:address:socket_address:address:service-envoy-1port_value:8000- name:service2-envoytype:STRICT_DNSlb_policy:ROUND_ROBINload_assignment:cluster_name:service2-envoyendpoints:- lb_endpoints:- endpoint:address:socket_address:address:service-envoy-2port_value:8000admin:address:socket_address:address:0.0.0.0port_value:8001layered_runtime:# 用于设置 Envoy 的运行时参数layers:- name:static_layer_0static_layer:# 静态层,用于设置 Envoy 的运行时参数envoy:resource_limits:listener:example_listener_name:connection_limit:10000
上面的配置文件我们可以看到 Envoy 中定义了两个 Listener,分别监听 8080 和 8443 端口,分别对应 http 和 https 请求,我们可以看到 8443 这个监听器配置了 TLS 证书,这个证书是自签名的。然后根据路由规则,将匹配路由 /service/1
的请求路由到 service1-envoy
这个集群中,将匹配路由 /service/2
的请求路由到 service2-envoy
这个集群中。
这两个集群分别对应了 service-envoy-1
和 service-envoy-2
这两个后端服务,需要注意的是这里的两个后端服务并不是最终的 aiohttp
应用程序,而是 aiohttp
应用前面的 Service Envoy 代理,这样所有的请求都会先经过 Envoy 代理,然后再路由到最终的 aiohttp
应用程序中。
下面是 service1
这个服务前面的 Envoy 代理的配置文件:
# service-envoy.yamlstatic_resources:listeners:- address:socket_address:address:0.0.0.0port_value:8000filter_chains:- filters:- name:envoy.filters.network.http_connection_managertyped_config:"@type":type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManagercodec_type:AUTOstat_prefix:service_envoy_1route_config:name:local_routevirtual_hosts:- name:backenddomains:- "*"routes:- match:prefix:"/service/1"route:cluster:service1http_filters:- name:envoy.filters.http.routertyped_config:"@type":type.googleapis.com/envoy.extensions.filters.http.router.v3.Routerclusters:- name:service1type:STRICT_DNSlb_policy:ROUND_ROBINload_assignment:cluster_name:service1endpoints:- lb_endpoints:- endpoint:address:socket_address:address:service1port_value:8080admin:address:socket_address:address:0.0.0.0port_value:8001
我们可以看到收到的请求都会被路由到 service1
这个集群中,这个集群对应的是 service1
这个服务,这个服务就是一个 真正的后端 aiohttp
应用程序了,Service Envoy 相当于充当应用程序的 Sidecar,这样所有请求均由 Envoy 处理,然后有效路由到您的服务。
🍀
下面我们路由到 examples/front-proxy
目录,然后使用 Docker Compose 启动这个案例:
这个是要安装docker-compose的。
$pwd/Users/cnych/Documents/course/istio/manifests/envoy/examples/front-proxy$docker-composeup--build-d#docker compose up --build -d$docker-composepsNAMEIMAGECOMMANDSERVICECREATEDSTATUSPORTSfront-proxy-front-envoy-1front-proxy-front-envoy"/docker-entrypoint.sh /usr/local/bin/envoy -c /etc/envoy.yaml"front-envoyAboutaminuteagoUp35seconds0.0.0.0:8001->8001/tcp,:::8001->8001/tcp,0.0.0.0:8080->8080/tcp,:::8080->8080/tcp,0.0.0.0:8443->8443/tcp,:::8443->8443/tcp,10000/tcpfront-proxy-service-envoy-1-1front-proxy-service-envoy-1"/docker-entrypoint.sh /usr/local/bin/envoy -c /etc/envoy.yaml"service-envoy-1AboutaminuteagoUp37seconds(healthy) 10000/tcpfront-proxy-service-envoy-2-1front-proxy-service-envoy-2"/docker-entrypoint.sh /usr/local/bin/envoy -c /etc/envoy.yaml"service-envoy-2AboutaminuteagoUp37seconds(healthy) 10000/tcpfront-proxy-service1-1front-proxy-service1"python3 /code/service.py"service1AboutaminuteagoUp38seconds(healthy)front-proxy-service2-1front-proxy-service2"python3 /code/service.py"service2AboutaminuteagoUp38seconds(healthy)
在使用docker-compose启动的时候报错了:。。。
汇总踩坑如下:
1.要升级docker-compse版本新一点2.要手动拉取2个镜像才行
⚠️ 注意:
安装docker compose出问题了。。。
老师当时测试都是没问题的。
- 报错现象
- 当前环境(自己之前的docker-compse版本是v1.26.2)
[root@docker front-proxy]#docker-compose --versiondocker-composeversion1.26.2,buildeefe0d31docker-ce20.10.21
- 奇怪,不知道是哪里出了问题。。。-->感觉还是自己的docker compose有点问题。。。,可能自己docker compose版本太低了。。。
- 安装了新版本,还是不行。。。
[root@docker front-proxy]#docker-compose --versionDockerComposeversionv2.23.0
- 提问
- 自己再次测试
==这次就可以了,估计还是和自己的docker-compose版本有关。==
- 拉取报错了:。。。
第一次拉取失败:。。。
第2次拉取失败:。。。
估计还是自己linux虚机无法访问外网导致的。。。
- 自己pc是可以科学上网的的。
export https_proxy=http:*About to connect() to localhost port 8080 (#0)*Trying::1...*Connected to localhost (::1) port 8080 (#0)>GET/service/1HTTP/1.1>User-Agent:curl/7.29.0>Host:localhost:8080>Accept:*/*><HTTP/1.1 200 OK<content-type:text/plain;charset=utf-8<content-length:79<date:Fri,03 Nov 2023 22:51:21 GMT<server:envoy<x-envoy-upstream-service-time:4<HellofrombehindEnvoy(service 1)!hostname221f01bef482resolved172.19.0.3*Connection #0 to host localhost left intact
service2
[root@docker front-proxy]#curl -v localhost:8080/service/2*About to connect() to localhost port 8080 (#0)*Trying::1...*Connected to localhost (::1) port 8080 (#0)>GET/service/2HTTP/1.1>User-Agent:curl/7.29.0>Host:localhost:8080>Accept:*/*><HTTP/1.1 200 OK<content-type:text/plain;charset=utf-8<content-length:79<date:Fri,03 Nov 2023 22:51:41 GMT<server:envoy<x-envoy-upstream-service-time:4<HellofrombehindEnvoy(service 2)!hostnameeb0e9d483971resolved172.19.0.2*Connection #0 to host localhost left intact
可以看到每个请求我们都是直接发送到 Front Envoy,然后 Front Envoy 再根据路由规则将请求路由到对应的 Service Envoy,然后再路由到最终的
aiohttp
应用程序中的。
🍀
此外还可以使用 HTTPS 来调用 Envoy 后面的服务,例如调用 service1:
[root@docker front-proxy]#curl https:*About to connect() to localhost port 8443 (#0)*Trying::1...*Connected to localhost (::1) port 8443 (#0)*InitializingNSSwithcertpath:sql:/etc/pki/nssdb*skipping SSL peer certificate verification*SSL connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256*Server certificate:*subject:CN=front-envoy*start date:7月 08 01:31:46 2020 GMT*expire date:7月 06 01:31:46 2030 GMT*common name:front-envoy*issuer:CN=front-envoy>GET /service/1 HTTP/1.1>User-Agent:curl/7.29.0>Host:localhost:8443>Accept:*/*><HTTP/1.1 200 OK<content-type:text/plain;charset=utf-8<content-length:79<date:Fri,03 Nov 2023 22:52:35 GMT<server:envoy<x-envoy-upstream-service-time:3<HellofrombehindEnvoy(service 1)!hostname221f01bef482resolved172.19.0.3*Connection #0 to host localhost left intact
🍀
接下来我们还可以继续测试 Envoy 的负载均衡功能,我们可以将 service1
服务扩展到 3 个实例:
[root@docker front-proxy]#docker-compose scale service1=3[+] Running 3/3✔Containerfront-proxy-service1-1Running0.0s✔Containerfront-proxy-service1-3Started0.0s✔Containerfront-proxy-service1-2Started0.0s
🍀
然后我们多次向 service1
发送请求,前端 Envoy 将通过对三台 service1
机器进行轮询来对请求进行负载平衡:
[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostname221f01bef482resolved172.19.0.3[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostname221f01bef482resolved172.19.0.3[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostname4f39d0e0afc7resolved172.19.0.7[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostnamef6699d0a5de9resolved172.19.0.8[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostname4f39d0e0afc7resolved172.19.0.7[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostnamef6699d0a5de9resolved172.19.0.8[root@docker front-proxy]#curl localhost:8080/service/1HellofrombehindEnvoy(service 1)!hostname221f01bef482resolved172.19.0.3
🍀
测试完成后可以执行 docker-compose down
命令来停止所有容器。
[root@docker front-proxy]#docker-compose down[+] Running 8/8✔Containerfront-proxy-front-envoy-1Removed0.2s✔Containerfront-proxy-service-envoy-2-1Removed0.2s✔Containerfront-proxy-service-envoy-1-1Removed0.2s✔Containerfront-proxy-service2-1Removed0.3s✔Containerfront-proxy-service1-1Removed0.4s✔Containerfront-proxy-service1-3Removed0.4s✔Containerfront-proxy-service1-2Removed0.3s✔Networkfront-proxy_defaultRemoved0.1s[root@docker front-proxy]#docker-compose psNAMEIMAGECOMMANDSERVICECREATEDSTATUSPORTS[root@docker front-proxy]#docker psCONTAINERIDIMAGECOMMANDCREATEDSTATUSPORTSNAMES
测试结束。😘
3、流量镜像
这里说的集群都是envoy集群。
流量镜像功能允许您将流量复制到另一个集群,而不会影响主要流量。这对于测试新版本的服务或将流量发送到另一个集群以进行分析非常有用。
==🚩 实战:流量镜像-2023.11.4(测试成功)==
实验环境:
DockerComposeversionv2.23.0docker20.10.21-ce(具有docker环境)
实验软件: