暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

云原生架构下的微服务之:4 Envoy 快速入门

运维老狗 2021-12-06
1709

Envoy 快速入门1 部署和运行Envoy的常用方法1.1 部署和运行Envoy的常用方法1.2 部署并运行Envoy1.2.1 启动Envoy1.3 静态资源和动态资源配置1.4  Listener的简易静态配置1.4.1 echo 过滤器演示1.5 Cluster 简易静态配置1.5.1 Cluster配置示例1.6 L4 过滤器 tcp_proxy1.6.1 TCP 代理配置示例(Front Proxy)1.7 L4 过滤器 http_connection_manager1.7.1 路由基础配置概览1.7.2 HTTP L7路由基础配置1.7.3 L7 Front Proxy 路由代理配置示例1.8 L7 Front Proxy代理配置示例1.9 L7 Ingress Listener代理配置示例1.10 L7 Egress Listener代理配置示例

Envoy 快速入门


1 部署和运行Envoy的常用方法

Enovy部署类型回顾

  • Envoy通常用于以容器编排系统为底层环境的服务网格中,并以sidecar的形式与主程序容器运行为单个Pod;

    • 非编排系统环境中测试时,可以将主程序与Envoy运行于同一容器,或手动组织主程序容器与Envoy容器共享同一网络名称空间;

    • Front Proxy类型的Envoy可独立运行为守护进程或容器;

    • 具体使用时的常见部署类型如下图所示:

1.1 部署和运行Envoy的常用方法

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

Get Envoy项目为多个主流的Linux发行版(例如Ubuntu、CentOS和RHEL等)维护了二进制的发行版,配置相应的仓库后,即可使用系统的包管理器进行安装;

  • Ubuntu:https://dl.bintray.com/tetrate/getenvoy-deb

  • CentOS:https://tetrate.bintray.com/getenvoy-rpm/centos/

  • RHEL:https://tetrate.bintray.com/getenvoy-rpm/rhel/

部署文档(建议使用稳定版)

https://www.envoyproxy.io/docs/envoy/latest/start/install


1.2 部署并运行Envoy

部署Envoy,以Debian/Ubuntu Linux发行版为例

$ sudo apt update
$ sudo apt install apt-transport-https ca-certificates curl gnupg2 software-properties-common
$ curl -sL 'https://getenvoy.io/gpg' | sudo apt-key add -
# 检查密钥
$ apt-key fingerprint 6FF974DB | grep "5270 CEAC"
$ sudo add-apt-repository "deb [arch=amd64] https://dl.bintray.com/tetrate/getenvoy-deb $(lsb_release -cs) stable"
$ sudo apt update
$ sudo apt install getenvoy-envoy

运行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

  • 示例配置文件(提示:被代理的服务是Google,建议修改为其他可用地址)

    • https://www.envoyproxy.io/docs/envoy/latest/_downloads/92dcb9714fb6bc288d042029b34c0de4/envoy-demo.yaml

1.2.1 启动Envoy

启动Envoy时,需要通过-c
选项为其指定初始配置文件以提供引导配置(Bootstrap configuration),这也是使用 v3 API 的必然要求;

  • envoy -c <path to config>.{json,yaml,pb,pb_text}

    • 扩展名代表了配置信息的组织格式;

  • 引导配置是Envoy配置信息的基点,用于承载Envoy的初始配置,它可能包括静态资源和动态资源的定义

    • 静态资源(static_resources)于启动直接加载

    • 动态资源(dynamic_resources)则需要通过配置的xDS服务获取并生成

  • 通常,Listener 和 Cluster 是 Envoy 得以运行的基础,而二者的配置可以全部为静态格式,也可以混合使用动态及静态方式提供,或者全部配置为动态;

    • 例如,一个 yaml 格式纯静态的基础配置框架:


静态资源配置伪代码:

static_resources: # 静态资源
 listeners:
- name: ...
 address: {}
 filter_chains: []
clusters:
- name: ...
 type: ...
 connect_timeout: {}
 dns_lookup_family: V4_ONLY
 load_assignment: {}


总结:

要想启动 envoy 的话,正常情况下 envoy -c 加载一个 bootstrap 配置,而 bootstrap 配置文件中有两种配置格式分别是动态、静态,静态资源都定义在 static_resources
中。


1.3 静态资源和动态资源配置

静态资源配置:

纯静态资源配置方式主是直接在配置文件中通过 static_resources
配置参数明确定义 listeners、clusters
secrets
的配置方式,各配置参数的数据类型如下面的配置所示;

  • 其中,listeners 用于配置纯静态类型的侦听器列表,clusters 用于定义可用的集群列表及每个集群的端点,而可选的 secrets 用于定义 TLS 通信中用到数字证书等配置信息

  • 具体使用时,admin 和 static_resources 两参数即可提供一个最小化的资源配置,甚至 admin 也可省略

  • 静态配置伪代码:

    {
     "listeners": [],
     "clusters": [],
     "secrets": []
    }


动态资源配置:

动态资源,是指由 envoy 通过 xDS 协议发现所需要的各项配置的机制,相关的配置信息保存于称之为管理服务器(Management Server)的主机上,经由 xDS API 向外暴露;下面是一个纯动态资源的基础配置框架;

{
 "lds_config": "{...}", # 侦听器发现
 "cds_config": "{...}", # cluster 发现
 "ads_config": "{...}"  # 聚合发现,意思就是用 ads 既能发现 lds 又能发现 cds
}


1.4  Listener的简易静态配置

侦听器主要用于定义 Envoy 监听的用于接收 Downstreams 请求的套接字、用于处理请求时调用的过滤器链及相关的其它配置属性;

# 对于监听器来讲有下面几个关键配置
listeners:
- name: # 定义监听器名称
 address:
   socket_address: { address: ..., port_value: ..., protocol: ... } # 指定地址端口和协议,如果不指定的话默认都是 TCP
 filter_chains: # 定义过滤链
 - filters:
   - name:
     config:


L4 过滤器 echo 主要用于演示网络过滤器 API 的功能,它会回显接收到的所有数据至下游的请求者;在配置文件中调用时其名称为 envoy.echo;


下面是一个最简单的静态侦听器配置示例伪代码:

static_resources:
listeners:
  name: listener_0
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 15001
  filter_chains:
  - filters:
    - name: envoy.echo


1.4.1 echo 过滤器演示

echo 过滤器我刚才在上面已经说过了他会回显所有接收到得数据信息演示如下


环境说明

一个Service:

  • envoy:Front Proxy,地址为 10.0.10.2

运行和测试

1.编写 docker-compose 文件

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/envoy-echo# vim docker-compose.yaml 
version: '3.3'

services:
envoy:
  image: envoyproxy/envoy-alpine:v1.20.0
  volumes:
  - ./envoy.yaml:/etc/envoy/envoy.yaml # 将 envoy 配置文件挂载只容器 /etc/envoy/ 目录下
  networks:
    envoymesh:
      ipv4_address: 10.0.10.2
      aliases:
      - envoy-echo

networks:
envoymesh:
  driver: bridge
  ipam:
    config:
      - subnet: 10.0.10.0/24


2.编写 envoy.yaml 文件

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/envoy-echo# cat envoy.yaml 
static_resources:
listeners: # 开启监听器
- name: listener_0
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 8080
  filter_chains:
  - filters:
    - name: envoy.filters.network.echo # 使用的 filter 是 echo 过滤器


3.创建

docker-compose up


4.测试,于宿主机上运行如下命令

# 测试访问8080端口,并键入任意字符串
root@envoy:~# telnet 10.0.10.2 8080
Trying 10.0.10.2...
Connected to 10.0.10.2.
Escape character is '^]'.

# 下面为我任意输出的字符,可以看到已经回显
1
1
22
22
echo  
echo


5.停止后清理

docker-compose down


1.5 Cluster 简易静态配置

通常,集群代表了一组提供相同服务的上游服务器(端点)的组合,它可由用户静态配置,也能够通过 CDS 动态获取;

集群需要在“预热”环节完成之后方能转为可用状态,这意味着集群管理器通过 DNS 解析或 EDS 服务完成端点初始化,以及健康状态检测成功之后才可用;

cluster 配置解析:

clusters:
- name: ... # 集群的惟一名称,且未提供 alt_stat_name 时将会被用于统计信息中;也就意味着我们统计信息会显示那个集群生成的信息
 alt_state_name: ... # 统计信息中使用的集群代名称;
 type: ... # 用于解析的集群类型(生成集群端点)时使用的服务发现类型,可用值有STATIC、STRICT_DNS、LOGICAL_DNS、ORIGINAL_DST和EDS等;
 lb_policy: # 负载均衡算法,支持ROUND_ROBIN(轮询)、LEAST_REQUEST(最小连接数)、RING_HASH(一致性哈希)、RANDOM(随机调度)、MAGLEV(磁悬浮哈希固定值在 0-65535)和CLUSTER_PROVIDED(集群自身调度算法);
 load_assignment: # 为STATIC、STRICT_DNS 或 LOGICAL_DNS 类型的集群指定成员获取方式;EDS 类型的集成要使用eds_cluster_config字段配置;
   cluster_name: ... # 集群名称与上面的 name 保持一致;
   endpoints: # 端点列表;
   - locality: {} # 标识上游主机所处的位置,通常以 region、zone 等进行标识,用于区域感知路由;
     lb_endpoints: # 属于指定位置的端点列表;
     - endpoint_name: ... # 端点的名称;
       endpoint: # 端点定义;
         socket_adddress: # 端点地址标识;
           address: ... # 端点地址;
           port_value: ... # 端点端口;
           protocol: ... # 协议类型;


1.5.1 Cluster 配置示例

静态Cluster的各端点可以在配置中直接给出,也可借助 DNS 服务进行动态发现;

下面的示例直接给出了两个端点地址

clusters:
- name: test_cluster # test_cluster 集群名称
 connect_timeout: 0.25s
 type: STATIC # 集群类型 static 静态集群
 lb_policy: ROUND_ROBIN # 调度算法轮询
 load_assignment:
   cluster_name: test_cluster # 于上面的 -name 字段保持一致
   endpoints: # 端点列表
   - lb_endpoints:
     - endpoint: # 定义第一个后端 endpoint
       address:
         socket_address: { address: 172.17.0.3, port_value: 80 } # 地址:端口
     - endpoint: # 定义第二个后端 endpoint
       address:
         socket_address: { address: 172.17.0.4, port_value: 80 } # 地址:端口


1.6 L4 过滤器 tcp_proxy

TCP 代理过滤器在下游客户端及上游集群之间执行1:1网络连接代理

  • 它可以单独用作隧道替换,也可以同其他过滤器(如 MongoDB 过滤器或速率限制过滤器)结合使用;

  • TCP 代理过滤器严格执行由全局资源管理于为每个上游集群的全局资源管理器设定的连接限制

    • TCP 代理过滤器检查上游集群的资源管理器是否可以在不超过该集群的最大连接数的情况下创建连接;

  • TCP 代理过滤器可直接将请求路由至指定的集群,也能够在多个目标集群间基于权重进行调度转发;

TCP 代理过滤器使用起来也较为简单,如下配置

{
 "stat_prefix": "...", # 用于统计数据中输出时使用的前缀字符;
 "cluster": "...", # 路由到的目标集群标识;
 "weighted_clusters": "{...}", # 基于权重路由
 "metadata_match": "{...}",
 "idle_timeout": "{...}", # 上下游连接间的超时时长,即没有发送和接收报文的超时时长;
 "access_log": [], # 访问日志;
 "max_connect_attempts": "{...}" # 最大连接尝试次数;
}


1.6.1 TCP 代理配置示例(Front Proxy)

下面的示例基于TCP代理将下游用户(本机)请求代理至后端的两个web服务器

提示:为便于建立测试环境,自本节起,后面的示例将以 docker-compose 工具编排运行

static_resources:
listeners:
  name: listener_0
  address:
    socket_address: { address: 0.0.0.0, port_value: 80 }
  filter_chains:
  - filters:
    - name: envoy.tcp_proxy # 中需要注意的是 filters 使用的是 envoy.tcp_proxy ,这个就是专门只在 tcp 层做 3L/4L 代理的,也是 3L/4L 过滤器
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy # 这里我们使用的是 envoy v3 版本的协议,envoy 自身本版必须要是 1.16 之后才能兼容
        stat_prefix: tcp
        cluster: local_cluster # 通过 type 的方式直接将接收到的流量转发给该 cluster

clusters:
- name: local_cluster # 指定 cluster name 绑定上面的 envoy
  connect_timeout: 0.25s
  type: STATIC # 集群类型
  lb_policy: ROUND_ROBIN
  load_assignment:
    cluster_name: local_cluster
    endpoints: # 后端端点配置
    - lb_endpoints:
      - endpoint:
          address:
            socket_address: { address: 10.0.10.11, port_value: 8080 }
      - endpoint:
          address:
            socket_address: { address: 10.0.10.12, port_value: 8080 }


1.7 L4 过滤器 http_connection_manager

http_connection_manager
通过引入 L7 过滤器链实现了对 http 协议的操纵,其中 router 过滤器用于配置路由转发;

listeners:
- name:
address:
  socket_address: { address: ..., port_value: ..., protocol: ... }
filter_chains:
- filters:
  - name: envoy.filters.network.http_connection_manager # 使用的 filter 必须是这个才能开启 http_connection_manager
    typed_config: # 类型化的配置
      "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager # 也是固定不能修改
      stat_prefix: ... # 统计信息中使用的易读性的信息前缀;
      route_config: # 静态路由配置;动态配置应该使用 rds 字段进行指定;
        name: ... # 路由配置的名称;
        virtual_hosts: # 虚拟主机列表,用于构成路由表也可以定义多个;
          - name: ... # 虚拟主机的逻辑名称,用于统计信息,与路由无关;
            domains: [] # 用来适配请求报文当中的那个主机头,如果用户的请求到这能够适配,那么就交给这个虚拟主机来处理否则就交给下一个虚拟主机,如果都没有虚拟主机能够处理那么这个 listener 是无法被处理,支持使用“*”通配符;匹配搜索次序为精确匹配、前缀通配、后缀通配及完全通配;
            routes: [] # 一旦 domains 匹配到该交给那个路由来处,路由列表,执行时按顺序搜索,第一个匹配到路由信息即为使用的路由机制;
      http_filters: # 定义http过滤器链
      - name: envoy.filters.http.router # 调用7层的路由过滤器


提示:

  • 处理请求时,Envoy 首先根据下游客户端请求的 “host” 来搜索虚拟主机列表中各 virtual_host 中的 domains 列表中的定义,第一个匹配到的 Domain 的定义所属的 virtual_host 即可处理请求的虚拟主机;

  • 而后搜索当前虚拟主机中的 routes 列表中的路由列表中各路由条目的 match 的定义,第一个匹配到的 match 后的路由机制(route、redirect或direct_response)即生效;


1.7.1 路由基础配置概览

match

  • 基于prefix、path或regex三者其中任何一个进行URL匹 配

    • 提示:regex 在 v3 版本中将会被 safe_regex 取代;

  • 可额外根据 headers 和 query_parameters 完成报文匹配

  • 匹配的到报文可有三种路由机制

    • redirect

    • direct_response

    • route

  • route

    • 支持 cluster、weighted_clusters 和 cluster_header 三者之一定义目标路由

    • 转发期间可根据 prefix_rewrite 和 host_rewrite 完成 URL 重写;

    • 可额外配置流量管理机制,例如 timeout、retry_policy、cors、request_mirror_policy 和 rate_limits 等;

看上图路由定义我们有两个阶段:

  • 第一个阶段:match:用于匹配条件,首先我们必须要匹配那种流量路由到那个地方去,所以我们需要先做流量筛选,只有符合我们条件的流量才分发到某个特定位置去处理,先有匹配条件符合了然后再进行有处理逻辑,而处理逻辑一旦匹配以后又有三种

    • prefix:检查路径前缀

    • path:检查路径精确值

    • regex:对路径做正则匹配

    • 我们在进行条件匹配的时候还可以附加条件,比如在上面三个核心条件之上还可以通过:

    • headers:检查某个标头

    • parameters:用于检查某个参数

    • 匹配条件在检查的时候核心三个条件:

  • 第二阶段处理逻辑:

    • 路由部分又非为目标路由

    • 路由弹性相关路由:

    • 高级 rewrite 处理:

    • cluster:直接路由给某个集群

    • weighted_clusters:或者把流量分割以后路由到多个集群,意思就是基于权重我定义了多个集群,这些集群的权重加起来是个总和,然后请求的流量就按照这个比例进行切割再分发给多个集群

    • cluster_header:基于请求报文中 header 指定的集群进行路由,允许客户端指定说要访问的集群

    • timeout:超时

    • retry_policy:重试策略,比如上游服务响应码 503 或者 5XX 状态码就进行重试。或者 timeout 了就进行重试,通过人为指定重试条件和次数

    • rate_limits:限流或者叫限速,在使用 rate_limits 限速的时候需要借助到外部的限速器来限速

    • prefix_rewrite:前缀重写处理

    • host_rewrite:主机重写处理

    • status & body:通过响应码和请求体响应

    • scheme_redirect:协议重定向,如对 http 的请求统统给 https

    • host_redirect:host 重定向

    • path_redirect:路径重定向

    • port_redirect:端口重定向

    • prefix_redirect:前缀重定向

    • redirect:重定向,重定向的话又有多种重定向

    • direct_response:代理直接响应,就不再往后代理

    • route:这个才是我们关注的最多的一种,直接向后端路由


以上我只是列出来相对核心的配置,很显然我们通常条件只需要指定一个,处理逻辑也只需要指定一个,比如 match 了某一个 prefix , 我就将他 route 到某个位置去,或者说 match 某个 path 就给他 redirect 到某个地方去等等就类似这种方式来进行定义


看了上面的介绍之后再来看看路由配置伪代码相信你已经能够看的比较清晰了:

routes: 
- name: ... # 此路由条目的名称;
match:
  prefix: ... # 请求的 URL 的前缀;
route: # 路由条目;
  cluster: # 目标下游集群;


1.7.2 HTTP L7路由基础配置

配置文件中 route_config.virtual_hosts.routes
配置的路由信息用于将下游的客户端请求路由至合适的上游集群中某 Server 上;

  • 其路由方式是将 url 匹配 match 字段的定义

    • match 字段可通过 prefix(前缀)、path(路径)或 safe_regex(正则表达式)三者之一来表示匹配模式;

  • 与 match 相关的请求将由 route(路由规则)、redirect(重定向规则)或 direct_response(直接响应)三个字段其中之一完成路由

  • 由 route 定义的路由目标必须是 cluster(上游集群名称)、cluster_header(根据请求标头中的cluster_header的值确定目标集群)或weighted_clusters(路由目标有多个集群,每个集群拥有一定的权重)其中之一;


1.7.3 L7 Front Proxy 路由代理配置示例

下面是一个 egress 类型的 Envoy 配置示例,它定义了两个 virtual_host ,不过,发往第二个 virtual_host 的请求将被重定向至第一个 server ;

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.filters.network.http_connection_manager # 使用 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 # 定义 web_service_1 虚拟主机匹配的域是 ik8s.io
            domains: ["*.ik8s.io", "ik8s.io"]
            routes: # 路由
            - match: { prefix: "/" } # 路由条件匹配路由前缀是 /
              route: { cluster: local_cluster } # 直接路由给 local_cluster 集群后端服务
          - name: web_service_2 # 定义 web_service_2 虚拟主机
            domains: ["39.105.137.222:8089"] # 访问 39.105.137.222:8089 这个 ip
            routes: # 路由
            - match: { prefix: "/" } # 路由条件匹配路由前缀是 /
              redirect: # 如果访问的路径前缀是 / 就直接重定向
                host_redirect: "www.ik8s.io" # 主机重定向再次将请求发送至 www.ik8s.io
        http_filters: # 定义http过滤器链
        - name: envoy.filters.http.router # 调用7层的路由过滤器,正是这个 route 的启用使得这里所有 4 层的过滤器可以实现这些高级路由配置功能

# 上面的配置就是不管用户访问 ik8s.io 还是访问 39.105.137.222:8089 都会将请求发送至 local_cluster 这个后端集群服务


1.8 L7 Front Proxy代理配置示例

前面给出了 Listener 的配置,Cluster 配置我们采用前面 tcp-proxy 示例中的配置;

而后于主机上使用 curl 命令即可发起测试

  • 由下面的命令及结果可知,发往第一个“domain”的请求被调度至后端主机的各端点之上

  • 发往第二个“domain”的请求被重定向至“http://www.ik8s.io”,而该Location又对应于上面的第一个domain中的主机

~$ curl -H "host: www.ik8s.io" 172.31.0.2
iKubernetes demoapp v1.0 !! ClientIP: 172.31.0.2, ServerName: webserver01, ServerIP: 172.31.0.11!

~$ curl -H "host: www.ik8s.io" 172.31.0.2
iKubernetes demoapp v1.0 !! ClientIP: 172.31.0.2, ServerName: webserver02, ServerIP: 172.31.0.12!

~$ curl -I -H "host: www.magedu.com" 172.31.0.2
HTTP/1.1 301 Moved Permanently
location: http://www.ik8s.io/
date: Tue, 18 May 2021 03:14:37 GMT
server: envoy
transfer-encoding: chunked


1.9 L7 Ingress Listener代理配置示例

ingress 模式下的 envoy 其实就是以 sidecar 的模式部署在我们后端服务旁边,共享的是和我们后端服务同一个网络空间,如果是 K8S 部署的话只需要在同一个 pod 中部署两个容器即可,下面我演示的是在 docker-compose 来部署

将运行的 envoy 和 demoapp 两个应用的容器设定为共享同一个Network Namespace来模拟Ingress代理的场景

  • envoy容器(Sidecar):监听于 0.0.0.0:80 套接字,接收客户端请求,并代理至 demoapp 容器

  • demoapp容器:监听于 127.0.0.1:8080 套接字,接收来自于同一网络名称空间中的envoy代理的请求


如下是 envoy 的配置文件

1.编写 envoy 文件

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-ingress# cat envoy.yaml 
static_resources:
listeners: # 开启监听器
- name: listener_0
  address:
    socket_address: { address: 0.0.0.0, port_value: 80 } # envoy 监听地址
  filter_chains:
  - filters:
    - name: envoy.filters.network.http_connection_manager # 使用的 filter
      typed_config: # filter 类型配置
        "@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: ["*"] # 所有域的请求只要匹配条件是 / 就都路由到 local_cluster
            routes:
            - match: { prefix: "/" }
              route: { cluster: local_cluster } # 指定路由集群
        http_filters: # 定义http过滤器链
        - name: envoy.filters.http.router # 调用 7 层的路由过滤器

clusters: # 定义集群
- name: local_cluster # 指定群集名称与上面 router 规则相绑定
  connect_timeout: 0.25s
  type: STATIC # 集群类型 static 静态集群
  lb_policy: ROUND_ROBIN # 调度算法
  load_assignment: # 负载配置
    cluster_name: local_cluster # 与上面的 cluster name 相互匹配
    endpoints: # 后端 server 配置
    - lb_endpoints:
      - endpoint:
          address:
            socket_address: { address: 127.0.0.1, port_value: 8080 } # 暴露自己的 8080 端口给 envoy 进行绑定


2.编写docker-compose

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-ingress# cat docker-compose.yaml 
version: '3'
 
services:
envoy: # 一个是 sidecar envoy
  image: envoyproxy/envoy-alpine:v1.20.0
  volumes:
  - ./envoy.yaml:/etc/envoy/envoy.yaml # 将当前目录下的 envoy.yaml 配置文件挂在至容器的 /etc/envoy/ 目录下
  networks:
    envoymesh:
      ipv4_address: 10.0.10.77 # 直接给这个 envoy 容器指定静态地址
      aliases:
      - ingress

webserver01: # 一个是 webserver
  image: ikubernetes/demoapp:v1.0
  environment:
    - PORT=8080 # 监听后端 server 的 8080 端口
    - HOST=127.0.0.1 # 监听后端 server ip
  network_mode: "service:envoy" # 直接共享 service.envoy 字段下也就是上面 10.0.0.77 的网络,这样才能模拟出来 sidecar 的意义
  depends_on:
  - envoy

# 手动定义用户空间的网络
networks:
envoymesh:
  driver: bridge # 使用本地桥接网络
  ipam:
    config:
      - subnet: 10.0.10.0/24 # 该容器的地址段


3.启动

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-ingress# docker-compose up


4.访问验证

root@envoy:~# curl 10.0.10.77
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.1, ServerName: b41b8b3822c3, ServerIP: 10.0.10.77!

# 这里访问的是 envoy 的地址和端口


1.10 L7 Egress Listener代理配置示例

egress 部署模式话就是将 envoy 部署在外部,通过出入流量接口来实现对后端服务的访问,往往 egress 的 envoy 都是部署在用户的请求出口处

将运行的 envoy 和 client 两个应用的容器设定为共享同一个 Network Namespace 来模拟 Egress 代理的场景

  • envoy容器(Sidecar):监听于 127.0.0.1:80 套接字,接收客户端请求,并代理至 demoapp 容器

  • client容器:直接向同一网络名称空间中的 envoy 代理的127.0.0.1:80套接字发请求


1.编写 envoy.yaml

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-egress# cat envoy.yaml 
# Author: ZGY
static_resources:
listeners:
- name: listener_0
  address:
    socket_address: { address: 127.0.0.1, port_value: 80 }  # envoy 监听本地的 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: egress_http
        codec_type: AUTO
        route_config:
          name: local_route
          virtual_hosts:
          - name: web_service_1
            domains: ["*"]
            routes:
            - match: { prefix: "/" }
              route: { cluster: web_cluster } # 绑定的路由 cluster
        http_filters:
        - name: envoy.filters.http.router

clusters:
- name: web_cluster
  connect_timeout: 0.25s
  type: STRICT_DNS # 将类型改为 STRICT_DNS 就表示说我们要基于 STRICT_DNS 代理
  lb_policy: ROUND_ROBIN
  load_assignment:
    cluster_name: web_cluster
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address: { address: myservice, port_value: 80 } # 并将 address 改为 myservice 也就是在 docker-compose 中指定的别名,随后 envoy 会解析 myservice 这个地址


2.编写 docker-compose

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-egress# cat docker-compose.yaml 
# Author: zgy
version: '3.3'

services:
# 定义 envoy
envoy:
  image: envoyproxy/envoy-alpine:v1.18-latest
  volumes:
  - ./envoy.yaml:/etc/envoy/envoy.yaml
  networks:
    envoymesh:
      ipv4_address: 10.0.10.2 # 定义 envoy 容器的 ip
      aliases:
      - front-proxy
  depends_on:
  - webserver01
  - webserver02

# 定义 client 共享了 envoy 的网络空间,也就是 10.0.10.2 这个 ip
client:
  image: ikubernetes/admin-toolbox:v1.0 # 为了等会跑起来之后模拟客户端的交互式,所以这里自己做了一个镜像,里面内置了一些 curl 命令等工具
  network_mode: "service:envoy"
  depends_on:
  - envoy

# server 01 定义
webserver01:
  image: ikubernetes/demoapp:v1.0
  hostname: webserver01
  networks:
    envoymesh:
      ipv4_address: 10.0.10.11
      aliases:
      - webserver01
      - myservice # 注意定义别名

# server 02 定义
webserver02:
  image: ikubernetes/demoapp:v1.0
  hostname: webserver02
  networks:
    envoymesh:
      ipv4_address: 10.0.10.12
      aliases:
      - webserver02
      - myservice # 注意定义别名

# 定义网络
networks:
envoymesh:
  driver: bridge
  ipam:
    config:
      - subnet: 10.0.10.0/24


3.启动

root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-egress# docker-compose up


4.进入到客户端容器中

root@envoy:~# cd servicemesh_in_practise-develop/Envoy-Basics/http-egress/
root@envoy:~/servicemesh_in_practise-develop/Envoy-Basics/http-egress# docker-compose exec client /bin/sh
[root@f19ac290fcac /]# curl myservice
iKubernetes demoapp v1.0 !! ClientIP: 10.0.10.2, ServerName: webserver02, ServerIP: 10.0.10.12!
[root@f19ac290fcac /]# curl myservice
iKubernetes demoapp v1.0 !! ClientIP: 10.0.10.2, ServerName: webserver01, ServerIP: 10.0.10.11!



文章转载自运维老狗,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论