ubuntu 下部署envoy 并作为前端代理

前言

Envoy 是一个开源的高性能、可扩展的代理服务,最初由 Lyft 公司开发。它设计用于处理现代的微服务架构中的网络通信,并提供了许多功能,包括负载均衡、服务发现、路由、认证、授权等。Envoy 被广泛用于构建和部署云原生应用程序以及微服务体系结构。

本文将通过将envoy作为前端代理来演示envoy的安装、配置和简单使用。

本文使用环境

  • Ubuntu 22.04.3 LTS Desktop 64-bit

1 安装

envoy 编译比较复杂,可以使用Envoy 社区提供的docker镜像和getenvoy项目,不过getenvoy所使用的版本比较老。在Linux下最简单的方式还是直接使用官方的envoy预编译二进制文件。

1.1 下载

  • 从Envoy 的 GitHub 发行版页面下载 Ubuntu 的最新版的envoy预编译二进制文件,这里选择"envoy-1.28.0-linux-x86_64"
ruby 复制代码
https://github.com/envoyproxy/envoy/releases

1.2 安装envoy

新建项目目录,将文件复制到该目录下(本文使用/home/zhg/Mine/Workplace/getenvoy/)

  • 下载完成后如果是.tar.gz则需要解压
  • 如果是(application/x-executable)可执行文件,则需要添加添加可执行权限
bash 复制代码
# 重命名为"envoy"方便输入命令
sudo mv envoy-1.28.0-linux-x86_64 envoy

# 添加可执行权限
chmod +x envoy 

通过以下命令可以查看envoy版本,以验证envoy是否正确安装

bash 复制代码
./envoy --version

2 配置

配置参考官网

www.envoyproxy.io/docs/envoy/...

envoy 可以通过静态配置和动态配置两种方式实现,静态文件通常yaml格式的文件进行配置,主要字段有:

listeners(监听器)

listeners 字段用于定义Envoy监听的网络地址和协议。它描述了Envoy如何接收和处理传入的连接请求。

diff 复制代码
listeners:
-   name: 给监听器命名,方便引用。
-   address: 指定监听的 IP 地址和端口。
-   filters:指定用于处理传入连接的过滤器链,包括协议转码、路由、TLS 等。
filter(过滤器)

filters字段通常用于通过配置文件引入和加载Envoy的各种过滤器。过滤器是Envoy的功能组件,用于在请求或响应的处理过程中执行特定的操作。过滤器可以添加、修改或删除请求或响应的头信息,执行转换,执行日志记录等操作。

envoy.http_connection_manager 是Envoy的HTTP连接管理器,它用于处理HTTP请求和响应。它是Envoy配置的核心组件之一,负责管理HTTP连接的生命周期、处理HTTP协议、执行各种过滤器等。该连接管理器允许您配置各种HTTP功能,包括路由、重试、负载均衡、超时等

yaml 复制代码
filters:                           # 过滤器列表
  - name: envoy.http_connection_manager   # 使用 Envoy 的 HTTP 连接管理器过滤器
    typed_config:                   # 配置该过滤器的类型和参数
      "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
      codec_type: HTTP2             # 使用 HTTP/2 编解码器
      stat_prefix: ingress_http     # 用于生成统计信息的前缀
      route_config:                  # 路由配置
        name: local_route           # 路由的名称
        virtual_hosts:               # 虚拟主机列表
clusters(集群)

clusters 字段用于定义集群(clusters)。集群是Envoy用于负载均衡和路由请求的基本单元,定义后端服务的地址、端口、协议等信息

diff 复制代码
clusters:
-  name: 定义集群的名称。
-  type: 指定集群类型,如 static, strict_dns, sds 等。
-  connect_timeout: 连接超时时间。
-  lb_policy: 负载均衡策略,如 round_robin, least_request 等。
-  hosts: 指定集群的后端主机。
-  tls_context: 配置 TLS。
routes(路由)

routes 字段用于定义路由规则。路由规则确定了Envoy在接收到请求时应该将其转发到哪个后端服务

diff 复制代码
routes:
-   prefix: URL 前缀匹配。
-   cluster: 指定请求应该转发到的集群。
-   timeout: 设置请求超时时间。
-   retry_policy: 配置请求重试策略。
admin(管理控制)

admin是用于提供管理和监控功能的配置选项。通过 Envoy 的 admin`接口,用户可以查看运行时统计信息、配置信息,执行一些诊断命令等

diff 复制代码
admin:
-   access_log_path: 指定访问日志文件的路径。
-   address:指定 Envoy 管理界面的监听地址和端口。

以下是一份配置实例,在项目目录打开终端,输入以下命令创建配置文件,并将配置内容复制到文件中。

bash 复制代码
touch envoy_conf.yaml
yaml 复制代码
# Envoy 管理配置
admin:
  # 访问日志路径
  access_log_path: "/home/zhg/Mine/Workplace/getenvoy/envoy.log"
  # 管理界面监听地址和端口
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 10001

# 静态资源配置
static_resources:
  listeners:
    # 定义一个监听器,监听在 0.0.0.0:10000
    - address:
        socket_address: { protocol: TCP, address: 0.0.0.0, port_value: 10000 }
      filter_chains:
        - filters:
            # 使用 HTTP 连接管理器过滤器
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                codec_type: auto
                stat_prefix: http
                access_log:
                  # 记录 HTTP 请求到文件
                  - name: envoy.access_loggers.file
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
                      path: "/home/zhg/Mine/Workplace/getenvoy/envoy_http.log"
                      log_format:
                        text_format: |
                          >>>>
                          start_time: "%START_TIME%"  
                          method: "%REQ(:METHOD)%", original_path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%", protocol: "%PROTOCOL%", response_code: "%RESPONSE_CODE%", response_flags: "%RESPONSE_FLAGS%"
                          user_agent: "%REQ(USER-AGENT)%"
                          authority: "%REQ(:AUTHORITY)%"
                          upstream_host: "%UPSTREAM_HOST%"
                          request_id: "%REQ(X-REQUEST-ID)%"
                          custom_header: "%REQ(custom_header)%"
                          static_header: "%REQ(static_header)%"
                route_config:
                  name: search_route
                  virtual_hosts:
                    - name: backend
                      domains:
                        - "*"
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            # 将请求发送到 baidu 集群
                            cluster: baidu
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
    - name: baidu
      connect_timeout: 1s
      # 使用 STRICT_DNS 模式进行 DNS 解析
      type: STRICT_DNS
      dns_lookup_family: V4_ONLY
      lb_policy: round_robin
      load_assignment:
        cluster_name: baidu
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      # 目标服务器地址
                      address: www.baidu.com
                      port_value: 80
   

3 运行envoy

写好配置文件后,就可以在项目目录打开终端,输入以下命令启动envoy

bash 复制代码
# 通过静态配置文件直接启动 Envoy
# -l debug :设置日志级别为debug,可省略
./envoy -c envoy_conf.yaml -l debug

//查看帮助
envoy --help

4.测试

4.1 查看envoy admin

打开浏览器,输入localhost:10001,可以看到envoy已经启动起来,可以正常访问admin页面

4.2 代理配置验证

普通 curl 请求

css 复制代码
zhg@zhg-pc:~/Mine/Workplace/envoytest$ curl -vvv baidu.com
*   Trying 39.156.66.10:80...
* Connected to baidu.com (39.156.66.10) port 80 (#0)
> GET / HTTP/1.1
> Host: baidu.com
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Thu, 16 Nov 2023 03:42:54 GMT
< Server: Apache
< Last-Modified: Tue, 12 Jan 2010 13:48:00 GMT
< ETag: "51-47cf7e6ee8400"
< Accept-Ranges: bytes
< Content-Length: 81
< Cache-Control: max-age=86400
< Expires: Fri, 17 Nov 2023 03:42:54 GMT
< Connection: Keep-Alive
< Content-Type: text/html
< 
<html>
<meta http-equiv="refresh" content="0;url=http://www.baidu.com/">
</html>
* Connection #0 to host baidu.com left intact

使用 curl 访问 Envoy,并添加 Header 字段 host: baidu.com

  • curl -v -H 'Host: baidu.com' 127.0.0.1:10000
  • 可以看到请求被转发到了 baidu.com,在响应头中,server: envoy 表示服务器使用的是 Envoy 代理。这是 Envoy 代理的标识,表示请求经过了 Envoy
yaml 复制代码
zhg@zhg-pc:~/Mine/Workplace/envoytest$ curl -vvv -H 'Host: baidu.com' 127.0.0.1:15001
*   Trying 127.0.0.1:15001...
* Connected to 127.0.0.1 (127.0.0.1) port 15001 (#0)
> GET / HTTP/1.1
> Host: baidu.com
> User-Agent: curl/7.81.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< accept-ranges: bytes
< cache-control: private, no-cache, no-store, proxy-revalidate, no-transform
< content-length: 2381
< content-type: text/html
< date: Thu, 16 Nov 2023 03:45:17 GMT
< etag: "588604dc-94d"
< last-modified: Mon, 23 Jan 2017 13:27:56 GMT
< pragma: no-cache
< server: envoy
< set-cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
< x-envoy-upstream-service-time: 18
< 
<!DOCTYPE html>
...省略...
</html>
* Connection #0 to host 127.0.0.1 left intact

4.3 代理到本机web服务

4.3.1 修改配置

在clusters字段下增加一个名为"localserver"的集群,配置如下:

yaml 复制代码
  clusters:
    - name: baidu
      connect_timeout: 1s
      # 使用 STRICT_DNS 模式进行 DNS 解析
      type: STRICT_DNS
      dns_lookup_family: V4_ONLY
      lb_policy: round_robin
      load_assignment:
        cluster_name: baidu
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      # 目标服务器地址
                      address: www.baidu.com
                      port_value: 80
    - name: localserver
      connect_timeout: 1s
      # 使用 STATIC 模式,直接指定目标地址
      type: STATIC
      dns_lookup_family: V4_ONLY
      lb_policy: round_robin
      load_assignment:
        cluster_name: localserver
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      # 本地服务器地址
                      address: 127.0.0.1
                      port_value: 9001

并将routes的cluster 修改为改localserver

yaml 复制代码
  routes:
    - match:
        prefix: "/"
      route:
        # 将请求发送到 baidu 集群
        cluster: localserver

4.3.2 使用Python搭建简易HTTP 服务器

适用:小型 web 项目在局域网内的预览

编写网页

新建项目目录和文件:web/index.html,并输入以下内容,创建一个简易的网页以进行验证。

xml 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
     WebServer for hello Envoy! 
</body>
</html>

4.3.3 启动http服务器

在项目目录运行启动http服务器

bash 复制代码
# 服务器默认监听端口是 8000,支持自定义端口号
python3 -m http.server 9001

#服务器默认工作目录为当前目录,可通过 -d/--directory 参数指定工作目录
python -m http.server --directory /tmp/

4.3.4 验证地址

    1. 输入以下命令获取ubuntu的本机IP地址,假设ip是192.168.2.30
ruby 复制代码
# ubuntu 查看本机ip地址
$ ip a
  • 2.访问网页 例如ubuntu虚拟机所在的主机,使用浏览器连接ubuntu的ip地址,端口是envoy的监听端口9000,即

http://192.168.2.30:10000/

  • 这时候应该能看到Ubuntu本地服务器web/index.html网页的内容,注意这里用的是10000端口,这是envoy程序的监听端口,如果是9001则是http服务器的端口,

参考链接

1\] [envoy Official documentation](https://link.juejin.cn?target=https%3A%2F%2Fwww.envoyproxy.io%2Fdocs%2Fenvoy%2Flatest%2F "https://www.envoyproxy.io/docs/envoy/latest/") \[2\] [安装 -- Envoy 中文指南, by cloudnative](https://link.juejin.cn?target=https%3A%2F%2Fcloudnative.to%2Fenvoy%2Findex.html "https://cloudnative.to/envoy/index.html") \[3\] [Envoy 文档, by icloudnative](https://link.juejin.cn?target=https%3A%2F%2Ficloudnative.io%2Fenvoy-handbook%2Fdocs%2Fgettingstarted%2Fquick-start%2F "https://icloudnative.io/envoy-handbook/docs/gettingstarted/quick-start/")

相关推荐
wowocpp1 小时前
spring boot Controller 和 RestController 的区别
java·spring boot·后端
后青春期的诗go1 小时前
基于Rust语言的Rocket框架和Sqlx库开发WebAPI项目记录(二)
开发语言·后端·rust·rocket框架
freellf1 小时前
go语言学习进阶
后端·学习·golang
全栈派森3 小时前
云存储最佳实践
后端·python·程序人生·flask
CircleMouse3 小时前
基于 RedisTemplate 的分页缓存设计
java·开发语言·后端·spring·缓存
獨枭4 小时前
使用 163 邮箱实现 Spring Boot 邮箱验证码登录
java·spring boot·后端
维基框架4 小时前
Spring Boot 封装 MinIO 工具
java·spring boot·后端
秋野酱4 小时前
基于javaweb的SpringBoot酒店管理系统设计与实现(源码+文档+部署讲解)
java·spring boot·后端
☞无能盖世♛逞何英雄☜5 小时前
Flask框架搭建
后端·python·flask
进击的雷神5 小时前
Perl语言深度考查:从文本处理到正则表达式的全面掌握
开发语言·后端·scala