部署Envoy

Envoy常用术语

envoy文档官网    Life of a Request — envoy 1.31.0-dev-e543e1 documentationicon-default.png?t=N7T8https://www.envoyproxy.io/docs/envoy/latest/intro/life_of_a_request#terminology

基础总结

(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

工作逻辑

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原生的端点发现方式。

代理总结

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:出向流量网关
当我们不需要对出向流量做什么特殊处理的时候,其实只需要有入向流量网关就够了。
如果需要对出向流量做治理的时候,才需要出向流量网关

docker 镜像拉取

# docker pull envoyproxy/envoy:latest
latest: Pulling from envoyproxy/envoy
fe703b657a32: Pull complete 
f9df1fafd224: Pull complete 
a645a4b887f9: Pull complete 
57db7fe0b522: Pull complete 
8239c375d005: Pull complete 
dadf1a36dc1a: Pull complete 
aaa45c35c46c: Pull complete 
2927ac61eca5: Pull complete 
d3f2b341deed: Pull complete 
Digest: sha256:ccaf9e0135bf498fb8396ad49defd7f8567bf706411d9a707efb3978fb842c89
Status: Downloaded newer image for envoyproxy/envoy:latest
docker.io/envoyproxy/envoy:latest

容器部署Envoy

1.1.1 下载资源清单 

地址:https://github.com/iKubernetes/servicemesh_in_practise/tree/MageEdu_N66

1.1.2 上传包
$ ll
total 40
drwxrwxr-x 11 root root   198 May 30 14:43 Cluster-Manager
drwxrwxr-x  7 root root   126 May 30 14:43 Dynamic-Configuration
drwxrwxr-x  2 root root    90 May 30 14:43 envoy-alpine
drwxrwxr-x  9 root root   173 May 30 14:43 Envoy-Basics
drwxrwxr-x  6 root root   103 May 30 14:43 Envoy-Mesh
drwxrwxr-x 10 root root   211 May 30 14:43 HTTP-Connection-Manager
-rw-rw-r--  1 root root 35184 May 30 14:43 LICENSE
drwxrwxr-x 11 root root   237 May 30 14:43 Monitoring-and-Tracing
-rw-rw-r--  1 root root  2125 May 30 14:43 README.md
drwxrwxr-x  8 root root   125 May 30 14:43 Security
drwxrwxr-x  2 root root    57 May 30 14:43 template

2 tcp proxy(L4 过滤器)

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

它可以单独用作隧道替换,也可以同其他过滤器(如MongoDB过滤器或速率限制过滤器) 结合使用;
TCP代理过滤器严格执行由全局资源管理于为每个上游集群的全局资源管理器设定的连接限制;
TCP代理过滤器检查上游集群的资源管理器是否可以在不超过该集群的最大连接数的情况下创建连接;
TCP代理过滤器可直接将请求路由至指定的集群,也能够在多个目标集群间基于权重进行调度转发;

2.1.1 cat envoy.yaml
# 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.tcp_proxy
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.tcp_proxy.v3.TcpProxy
          stat_prefix: tcp
          cluster: local_cluster

  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: 192.168.34.61, port_value: 8080 }
        - endpoint:
            address:
              socket_address: { address: 192.168.34.62, port_value: 8080 }
2.1.2 cat docker-compose.yaml
# cat docker-compose.yaml 
version: '3.3'

services:
  envoy:
    image: envoyproxy/envoy:v1.23.4
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    networks:
      envoymesh:
        ipv4_address: 192.168.1.60
        aliases:
        - front-proxy
    depends_on:
    - webserver01
    - webserver02

  webserver01:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver01
    networks:
      envoymesh:
        ipv4_address: 192.168.1.61
        aliases:
        - webserver01

  webserver02:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver02
    networks:
      envoymesh:
        ipv4_address: 192.168.1.62
        aliases:
        - webserver02

networks:
  envoymesh:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24
2.1.3 拉取服务镜像
docker pull ikubernetes/demoapp:v1.0
v1.0: Pulling from ikubernetes/demoapp
c9b1b535fdd9: Pull complete 
3cbce035cd7c: Pull complete 
b83463f478a5: Pull complete 
34b1f286d5e2: Pull complete 
Digest: sha256:6698b205eb18fb0171398927f3a35fe27676c6bf5757ef57a35a4b055badf2c3
Status: Downloaded newer image for ikubernetes/demoapp:v1.0
docker.io/ikubernetes/demoapp:v1.0
2.1.4 启动容器
$ docker-compose up -d
Creating network "tcp-front-proxy_envoymesh" with driver "bridge"
Creating tcp-front-proxy_webserver02_1 ... done
Creating tcp-front-proxy_webserver01_1 ... done
Creating tcp-front-proxy_envoy_1       ... done
2.1.5 检查进程
$ docker-compose ps
            Name                           Command               State     Ports  
----------------------------------------------------------------------------------
tcp-front-proxy_envoy_1         /docker-entrypoint.sh envo ...   Up      10000/tcp
tcp-front-proxy_webserver01_1   /bin/sh -c python3 /usr/lo ...   Up               
tcp-front-proxy_webserver02_1   /bin/sh -c python3 /usr/lo ...   Up  
2.1.6 访问测试,轮寻访问2个服务
$ curl 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
$ curl 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
$ curl 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
$ curl 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
2.1.7 进入容器后,可直接执行envoy命令
root@e7d74ecd3159:/usr/bin# envoy --version

envoy  version: 3504d40f752eb5c20bc2883053547717bcb92fd8/1.14.1/Clean/RELEASE/BoringSSL
2.1.8 数据流程如下

2.1.9 停止
$ docker-compose down
Stopping tcp-front-proxy_envoy_1       ... done
Stopping tcp-front-proxy_webserver02_1 ... done
Stopping tcp-front-proxy_webserver01_1 ... done
Removing tcp-front-proxy_envoy_1       ... done
Removing tcp-front-proxy_webserver02_1 ... done
Removing tcp-front-proxy_webserver01_1 ... done
Removing network tcp-front-proxy_envoymesh

3 http proxy(L7 过滤器)

cd http-front-proxy/
$ ll
total 12
-rw-rw-r-- 1 root root  862 May 30 15:36 docker-compose.yaml
-rw-rw-r-- 1 root root 1581 May 30 15:35 envoy.yaml
-rw-rw-r-- 1 root root  572 May 30 14:43 README.md
3.1.1 cat envoy.yaml
$ 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
        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: 192.168.1.61, port_value: 8080 }
        - endpoint:
            address:
              socket_address: { address: 192.168.1.62, port_value: 8080 }
3.1.2 cat docker-compose.yaml
$ cat docker-compose.yaml 
version: '3.3'

services:
  envoy:
    image: envoyproxy/envoy:v1.23.4
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    networks:
      envoymesh:
        ipv4_address: 192.168.1.60
        aliases:
        - front-proxy
    depends_on:
    - webserver01
    - webserver02

  webserver01:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver01
    networks:
      envoymesh:
        ipv4_address: 192.168.1.61
        aliases:
        - webserver01

  webserver02:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver02
    networks:
      envoymesh:
        ipv4_address: 192.168.1.62
        aliases:
        - webserver02

networks:
  envoymesh:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24
3.1.3 启动服务
$ docker-compose up -d
Creating network "http-front-proxy_envoymesh" with driver "bridge"
Creating http-front-proxy_webserver01_1 ... done
Creating http-front-proxy_webserver02_1 ... done
Creating http-front-proxy_envoy_1       ... done
3.1.4 检查进程
$ docker-compose  ps
             Name                           Command               State     Ports  
-----------------------------------------------------------------------------------
http-front-proxy_envoy_1         /docker-entrypoint.sh envo ...   Up      10000/tcp
http-front-proxy_webserver01_1   /bin/sh -c python3 /usr/lo ...   Up               
http-front-proxy_webserver02_1   /bin/sh -c python3 /usr/lo ...   Up 
 3.1.5 访问测试
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
$ curl -H "host: www.ik8s.io" 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
3.1.6 查看服务
$ curl -I -H "host: www.ik8s.io" 192.168.1.60
HTTP/1.1 200 OK
content-type: text/html; charset=utf-8
content-length: 101
server: envoy
date: Thu, 30 May 2024 07:44:09 GMT
x-envoy-upstream-service-time: 4
3.1.7 停止
$ docker-compose down
Stopping http-front-proxy_envoy_1       ... done
Stopping http-front-proxy_webserver02_1 ... done
Stopping http-front-proxy_webserver01_1 ... done
Removing http-front-proxy_envoy_1       ... done
Removing http-front-proxy_webserver02_1 ... done
Removing http-front-proxy_webserver01_1 ... done
Removing network http-front-proxy_envoymesh

4 http-ingress(入向流量代理)

ll http-ingress/
total 12
-rw-rw-r-- 1 root root  581 May 30 14:43 docker-compose.yaml
-rw-rw-r-- 1 root root 1214 May 30 14:43 envoy.yaml
-rw-rw-r-- 1 root root  425 May 30 14:43 README.md
4.1.1 cat envoy.yaml
# 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中)
4.1.2 cat docker-compose.yaml
$ cat docker-compose.yaml 
version: '3'

services:
  envoy:
    image: envoyproxy/envoy:v1.23.4
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    environment:
      - ENVOY_UID=0
      - ENVOY_GID=0
    networks:
      envoymesh:
        ipv4_address: 192.168.1.60
        aliases:
        - ingress

  webserver01:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
      - HOST=127.0.0.1
    network_mode: "service:envoy"
    depends_on:
    - envoy

networks:
  envoymesh:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24
4.1.3 启动容器
$ docker-compose  up -d
Creating network "http-ingress_envoymesh" with driver "bridge"
Creating http-ingress_envoy_1 ... done
Creating http-ingress_webserver01_1 ... done

$ docker-compose ps 
           Name                         Command               State     Ports  
-------------------------------------------------------------------------------
http-ingress_envoy_1         /docker-entrypoint.sh envo ...   Up      10000/tcp
http-ingress_webserver01_1   /bin/sh -c python3 /usr/lo ...   Up  
4.1.4 测试
$ curl 192.168.1.60
iKubernetes demoapp v1.0 !! ClientIP: 127.0.0.1, ServerName: d835488efd6a, ServerIP: 192.168.1.60!
4.1.5 进入容器中检查
# id
uid=0(root) gid=0(root) groups=0(root)
4.1.6 停止
$ docker-compose down
Stopping http-ingress_webserver01_1 ... done
Stopping http-ingress_envoy_1       ... done
Removing http-ingress_webserver01_1 ... done
Removing http-ingress_envoy_1       ... done
Removing network http-ingress_envoymesh

5.http-egress(出向流量代理)

 ll  http-egress/
total 12
-rw-rw-r-- 1 root root  961 May 30 14:43 docker-compose.yaml
-rw-rw-r-- 1 root root 1386 May 30 14:43 envoy.yaml
-rw-rw-r-- 1 root root  593 May 30 14:43 README.md
5.1.1 cat envoy.yaml
$ 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: 192.168.1.61, port_value: 80 }
        - endpoint:
            address:
              socket_address: { address: 192.168.1.62, port_value: 80 }
5.1.2 cat docker-compose.yaml
$ cat docker-compose.yaml 
# Author: MageEdu <mage@magedu.com>
# Site: www.magedu.com
version: '3.3'

services:
  envoy:
    image: envoyproxy/envoy:v1.23.4
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    networks:
      envoymesh:
        ipv4_address: 192.168.1.60
        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: 192.168.1.61
        aliases:
        - webserver01

  webserver02:
    image: ikubernetes/demoapp:v1.0
    hostname: webserver02
    networks:
      envoymesh:
        ipv4_address: 192.168.1.62
        aliases:
        - webserver02

networks:
  envoymesh:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24
5.1.3 docker pull
$ docker pull ikubernetes/admin-toolbox:v1.0
v1.0: Pulling from ikubernetes/admin-toolbox
c9b1b535fdd9: Already exists 
1de2c4c6c672: Pull complete 
Digest: sha256:620435ec75aee84cfaf40e75c7466d5a4d10e71f5884ccc5cf7a475538fdc937
Status: Downloaded newer image for ikubernetes/admin-toolbox:v1.0
docker.io/ikubernetes/admin-toolbox:v1.0
5.1.4 启动容器与检查
$ docker-compose up -d
Creating network "http-egress_envoymesh" with driver "bridge"
Creating http-egress_webserver02_1 ... done
Creating http-egress_webserver01_1 ... done
Creating http-egress_envoy_1       ... done
Creating http-egress_client_1      ... done

$ docker-compose  ps
          Name                         Command               State     Ports  
------------------------------------------------------------------------------
http-egress_client_1        /bin/sh -c sleep 999999          Up               
http-egress_envoy_1         /docker-entrypoint.sh envo ...   Up      10000/tcp
http-egress_webserver01_1   /bin/sh -c python3 /usr/lo ...   Up               
http-egress_webserver02_1   /bin/sh -c python3 /usr/lo ...   Up 
5.1.5 访问测试
$ docker ps | grep egress
970b9d4ea168   ikubernetes/admin-toolbox:v1.0                      "/bin/sh -c 'sleep 9…"   About a minute ago   Up About a minute               http-egress_client_1
b1e4094c1c05   envoyproxy/envoy:v1.23.4                            "/docker-entrypoint.…"   About a minute ago   Up About a minute   10000/tcp   http-egress_envoy_1
92d446d8fc5c   ikubernetes/demoapp:v1.0                            "/bin/sh -c 'python3…"   About a minute ago   Up About a minute               http-egress_webserver01_1
c01fb7e252c2   ikubernetes/demoapp:v1.0                            "/bin/sh -c 'python3…"   About a minute ago   Up About a minute               http-egress_webserver02_1


$ docker exec -it http-egress_client_1 /bin/sh
[root@b1e4094c1c05 /]# curl 127.0.0.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
[root@b1e4094c1c05 /]# curl 127.0.0.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver01, ServerIP: 192.168.1.61!
[root@b1e4094c1c05 /]# curl 127.0.0.1
iKubernetes demoapp v1.0 !! ClientIP: 192.168.1.60, ServerName: webserver02, ServerIP: 192.168.1.62!
[root@b1e4094c1c05 /]# curl 127.0.0.1
5.1.6 清理容器
$ docker-compose down
Stopping http-egress_client_1      ... done
Stopping http-egress_envoy_1       ... done
Stopping http-egress_webserver01_1 ... done
Stopping http-egress_webserver02_1 ... done
Removing http-egress_client_1      ... done
Removing http-egress_envoy_1       ... done
Removing http-egress_webserver01_1 ... done
Removing http-egress_webserver02_1 ... done
Removing network http-egress_envoymesh

6 admin接口

Administration interface — envoy 1.23.12-9689bc documentationicon-default.png?t=N7T8https://www.envoyproxy.io/docs/envoy/v1.23.12/operations/admin.html#administration-interface

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加上认证机制。

 ll  admin-interface/
total 12
-rw-rw-r-- 1 foot foot  917 May 30 14:43 docker-compose.yaml
-rw-rw-r-- 1 foot foot 1832 May 30 14:43 envoy.yaml
-rw-rw-r-- 1 foot foot  713 May 30 14:43 README.md

6.1.1 cat envoy.yaml
$ cat envoy.yaml 
# profile_path和access_log_path如果不需要的话,一定要配置为/dev/null
admin:
  profile_path: /tmp/envoy.prof
  access_log_path: /tmp/admin_access.log
#
admin:
  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: 192.168.1.61, port_value: 8080 }
        - endpoint:
            address:
              socket_address: { address: 192.168.1.62, port_value: 8080 }
6.1.2 cat docker-compose.yaml
$ cat docker-compose.yaml 
admin:
  profile_path: /tmp/envoy.prof
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
       address: 0.0.0.0
       port_value: 9901
version: '3.3'

services:
  envoy:
    image: envoyproxy/envoy:v1.23.4
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    environment:
      - ENVOY_UID=0
      - ENVOY_GID=0
    networks:
      envoymesh:
        ipv4_address: 192.168.1.60
        aliases:
        - front-proxy
    depends_on:
    - webserver01
    - webserver02

  webserver01:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver01
    networks:
      envoymesh:
        ipv4_address: 192.168.1.61
        aliases:
        - webserver01

  webserver02:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver02
    networks:
      envoymesh:
        ipv4_address: 192.168.1.62
        aliases:
        - webserver02

networks:
  envoymesh:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24
6.1.3 启动与检查
$ docker-compose up -d
Creating network "admin-interface_envoymesh" with driver "bridge"
Creating admin-interface_webserver01_1 ... done
Creating admin-interface_webserver02_1 ... done
Creating admin-interface_envoy_1       ... done

$ docker-compose ps
            Name                           Command               State     Ports  
----------------------------------------------------------------------------------
admin-interface_envoy_1         /docker-entrypoint.sh envo ...   Up      10000/tcp
admin-interface_webserver01_1   /bin/sh -c python3 /usr/lo ...   Up               
admin-interface_webserver02_1   /bin/sh -c python3 /usr/lo ...   Up 
6.1.4 访问测试
$ curl 192.168.1.60:9901/help
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
  /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
6.1.5 常用的接口
/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
6.1.6 停止
$ docker-compose down
Stopping admin-interface_envoy_1       ... done
Stopping admin-interface_webserver02_1 ... done
Stopping admin-interface_webserver01_1 ... done
Removing admin-interface_envoy_1       ... done
Removing admin-interface_webserver02_1 ... done
Removing admin-interface_webserver01_1 ... done
Removing network admin-interface_envoymesh

7 运行时接口

Runtime — envoy 1.31.0-dev-e543e1 documentationicon-default.png?t=N7T8https://www.envoyproxy.io/docs/envoy/latest/configuration/operations/runtime.html

7.1.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”提供给程序以确保其正确运行,因此,运行时配置系统并不必不可少;
7.1.2 配置运行时
启用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

$ ll  layered-runtime/
total 12
-rw-rw-r-- 1 root root  861 May 30 14:43 docker-compose.yaml
-rw-rw-r-- 1 root root 2002 May 30 14:43 envoy.yaml
-rw-rw-r-- 1 root root  576 May 30 14:43 README.md

7.1.3 cat envoy.yaml
$ cat envoy.yaml 

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: 192.168.1.61, port_value: 8080 }
        - endpoint:
            address:
              socket_address: { address: 192.168.1.62, port_value: 8080 }
7.1.4 cat docker-compose.yaml
$ cat docker-compose.yaml 
version: '3.3'

services:
  envoy:
    image: envoyproxy/envoy:v1.23.4
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    networks:
      envoymesh:
        ipv4_address: 192.168.1.60
        aliases:
        - front-proxy
    depends_on:
    - webserver01
    - webserver02

  webserver01:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver01
    networks:
      envoymesh:
        ipv4_address: 192.168.1.61
        aliases:
        - webserver01

  webserver02:
    image: ikubernetes/demoapp:v1.0
    environment:
      - PORT=8080
    hostname: webserver02
    networks:
      envoymesh:
        ipv4_address: 192.168.1.62
        aliases:
        - webserver02

networks:
  envoymesh:
    driver: bridge
    ipam:
      config:
        - subnet: 192.168.1.0/24
7.1.5 启动与检查
$ docker-compose up -d
Creating network "layered-runtime_envoymesh" with driver "bridge"
Creating layered-runtime_webserver01_1 ... done
Creating layered-runtime_webserver02_1 ... done
Creating layered-runtime_envoy_1       ... done

$ docker-compose ps
            Name                           Command               State     Ports  
----------------------------------------------------------------------------------
layered-runtime_envoy_1         /docker-entrypoint.sh envo ...   Up      10000/tcp
layered-runtime_webserver01_1   /bin/sh -c python3 /usr/lo ...   Up               
layered-runtime_webserver02_1   /bin/sh -c python3 /usr/lo ...   Up   

7.1.6 查看默认数据

$ curl 192.168.1.60:9901/runtime
{
 "layers": [
  "static_layer_0",
  "admin_layer_0"
 ],
 "entries": {
  "health_check.min_interval": {
   "final_value": "5",
   "layer_values": [
    "5",
    ""
   ]
  }
 }
}

7.1.7 修改超时时间

$ curl -XPOST 192.168.1.60:9901/runtime_modify?health_check.min_interval=15
OK

$ curl 192.168.1.60:9901/runtime
{
 "layers": [
  "static_layer_0",
  "admin_layer_0"
 ],
 "entries": {
  "health_check.min_interval": {
   "final_value": "15",
   "layer_values": [
    "5",
    "15"
   ]
  }
 }
}


 参考文档连接               
原文链接:https://blog.csdn.net/qq_42515722/article/details/132363590

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/665122.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

知了汇智携手川农大,为计算机学子打造实战型综合项目实训

随着数字化产业的迅猛发展和产业数字化转型的不断深入&#xff0c;产业对数字人才的需求也在发生变化。为了培养适应市场需求的高素质应用型人才&#xff0c;5月24日&#xff0c;知了汇智携手四川农业大学&#xff0c;为信息工程学院计算机科学与技术专业22级学子带来一场兼具实…

NV link

NV link比PCIe有什么厉害的地方 NV link是并行总线 NV link是去CPU中心化的 NV link只针对GPU 实际上&#xff0c;PCIe依然会和NV link一起使用

2024年大屏幕互动源码+动态背景图和配乐素材+搭建教程

2024年大屏幕互动源码动态背景图和配乐素材搭建教程 php宝塔搭建部署活动现场大屏幕互动系统php源码 运行环境&#xff1a;PHPMYSQL 下载源码地址&#xff1a;极速云

【c++入门】this指针

this指针引出&#xff1a; 我们知道一个类可以有多个实例化对象&#xff0c;但是这多个实例化对象所调用的成员函数是在公共代码区&#xff1b; 我们先来定义一个Date类&#xff1a; class Date { public:void init(int year, int month, int day){_year year;_month month;…

在Ubuntu乌班图上安装Docker

最近在学习乌班图相关的内容&#xff0c;找了一些文档安装的都是报错的&#xff0c;于是记录一下学习过程&#xff0c;希望也能帮助有缘人&#xff0c;首先查看乌班图的系统版本&#xff0c;我的是如下的&#xff1a; cat /proc/version以下是在Ubuntu 20.04版本上安装Docker。…

excel怎么对非数字求和汇总?

如&#xff1a;学生小王的成绩为&#xff1a;A&#xff0c;A&#xff0c;A&#xff0c;A&#xff0c;B&#xff0c;B-……想得到的成绩汇总求和为&#xff1a;2A,2A,1B,1B- 如果在低版本里&#xff0c;用公式计算可能相当复杂&#xff0c;但是有了TEXTJOIN函数和UNIQUE函数&…

【Linux系列】深入解析 `kill` 命令:Linux 下的进程管理利器

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

JDK JRE JVM 三者的关系

总结&#xff1a; 1. jdk 中 的 javac 编译器将 .java 文件编译为 .class 字节码文件 &#xff08;编译&#xff09; 2. jre 执行 .class 字节码文件 &#xff08;运行&#xff09; 3. jre 通过 jvm 运行程序&#xff0c;确保程序能够在不同平台上正确执行&#xff08;实现跨平…

一文学懂Base64编码原理

前言 Base64编码与ASCII编码一样&#xff0c;也是一种编码方式。不同的是ASCII码采用7位二进制数表示&#xff08;包括大小写字母、数字、标点符号和一些不可见字符&#xff09;&#xff0c;而Base64采用6位二进制数表示&#xff08;包括大小写字母、0~9数字、和/&#xff09;…

越洗越黑”的Pandas数据清洗

引言 先来一个脑筋急转弯活跃一下枯燥工作日常&#xff0c;问&#xff1a;“什么东西越洗越黑&#xff1f;” 有没有猜到的&#xff1f;猜不到我告诉你吧&#xff01; 答案是“煤球”。那么这个脑机急转弯跟我们要讨论的话题有没有关系呢&#xff1f; 嗯是的&#xff0c;还是沾…

CUDA学习(1)

(一)CUDA简介 CUDA&#xff0c;全称Compute Unified Device Architecture&#xff0c;是由NVIDIA公司开发的一种计算平台和编程模型。它允许软件开发者和程序员使用NVIDIA的图形处理单元&#xff08;GPU&#xff09;来进行非常复杂的计算任务。简单来说&#xff0c;CUDA让普通…

安全风险 - 检测设备是否为模拟器

在很多安全机构的检测中&#xff0c;关于模拟器的运行环境一般也会做监听处理&#xff0c;有的可能允许执行但是会提示用户&#xff0c;有的可能直接禁止在模拟器上运行我方APP 如何判断当前 app 是运行在Android真机&#xff0c;还是运行在模拟器? 可能做 Framework 的朋友思…

DKTCDR:Domain-Oriented Knowledge Transfer for Cross-Domain Recommendation

Domain-Oriented Knowledge Transfer for Cross-Domain Recommendation IEEE(CCF B.SCI 1)-Guoshuai Zhao, Xiaolong Zhang, Hao Tang, Jialie Shen, and Xueming Qian-2024 思路 在CDR中,构建连接两个域的桥梁是实现跨域推荐的基础。然而现在的CDR方法往往在连接两个域时忽…

Usage - hackthebox

简介 靶场&#xff1a;hackmyvm 靶机&#xff1a;Usage(10.10.11.18) 难度&#xff1a;Easy 靶机链接:https://app.hackthebox.com/machines/Usage 攻击机1&#xff1a;ubuntu22.04 (10.10.16.21) 攻击机2&#xff1a;windows11(10.10.14.33) 扫描 nmap起手 nmap -sT …

身份认证与口令攻击

身份认证与口令攻击 身份认证身份认证的五种方式口令认证静态口令动态口令(一次性口令)动态口令分类 密码学认证一次性口令认证S/KEY协议改进的S/KEY协议 其于共享密钥的认证 口令行为规律和口令猜测口令规律口令猜测 口令破解操作系统口令破解Windows密码存储机制Windows密码破…

整合框架(spring...) 统一异常处理

1、 我们想让异常结果也显示为统一的返回结果对象&#xff0c;并且统一处理系统的异常信息&#xff0c;那么需要统一异常处理。 附加&#xff1a;创建封装错误状态码和错误消息VO 代码如下&#xff1a; Result import io.swagger.v3.oas.annotations.media.Schema; impo…

数组的应用-24点游戏

目录 24点游戏 游戏规则 游戏主要分为三部分 电脑出牌 用户输入算式 电脑判断胜负 总结 24点游戏 游戏规则&#xff1a; 54张扑克抽出大小王&#xff0c;剩余52张用来用于游戏&#xff1b;每一轮从52张牌中随机抽出4张&#xff1b;玩家运用加&#xff0c;减&#xff0…

Java集合【超详细】

文章目录 一、集合框架1.1 概述1.2 数组和集合的区别1.3 Java集合框架体系1.4 数据结构1.4.1 栈、队列、数组、队列1.4.2 二叉树【理解】1.4.3 二叉查找树【理解】1.4.4 平衡二叉树【理解】1.4.5 红黑树【理解】 1.5 泛型 二、Collection集合2.1 Collection 集合概述和使用【应…

统计各个商品今年销售额与去年销售额的增长率及排名变化

文章目录 测试数据需求说明需求实现分步解析 测试数据 -- 创建商品表 DROP TABLE IF EXISTS products; CREATE TABLE products (product_id INT,product_name STRING );INSERT INTO products VALUES (1, Product A), (2, Product B), (3, Product C), (4, Product D), (5, Pro…

VIO System 丨适用于控制器开发前期的测试系统

VIO综述 嵌入式软件的HIL测试需要复杂的测试系统及完整的ECU硬件&#xff0c;这导致通常只能在开发流程的后期阶段进行测试。全新推出的低成本解决方案VIO System&#xff0c;使得在开发前期不仅可以进行总线通讯测试&#xff0c;也可以同时进行I/O信号测试。 该系统旨在通过…