Envoy 教程

1. 核心概念

Envoy 是一个专为云原生应用设计的开源边缘和服务代理,由 Lyft 开发并捐赠给 CNCF(云原生计算基金会)。它采用 C++ 编写,提供了高性能、可扩展的网络代理功能,特别适合微服务架构和容器化环境。

1.1 主要特点

  • 高性能:基于事件驱动的架构,使用异步 I/O 模型,提供低延迟、高吞吐量的代理服务
  • 可观测性:内置丰富的指标收集、日志记录和追踪功能,与 Prometheus、Grafana、Jaeger 等工具集成
  • 动态配置:支持通过 xDS API 进行动态配置管理,无需重启服务
  • 服务发现集成:与 Consul、etcd、Kubernetes 等服务发现系统无缝集成
  • 流量管理:提供细粒度的流量控制、负载均衡、健康检查等功能
  • 安全特性:支持 TLS 终止、mTLS、JWT 认证等安全功能

1.2 架构组件

  • Listener:监听特定端口的网络连接
  • Filter Chain:应用于入站连接的一系列过滤器
  • Cluster:后端服务集群的抽象
  • Endpoint:集群中的具体服务实例
  • Route:请求路由规则
  • Secret: TLS 证书等敏感信息

2. 安装配置

2.1 安装方式

Envoy 提供多种安装方式,包括二进制安装、容器部署和包管理器安装。

2.1.1 使用容器部署

# 拉取 Envoy 镜像
docker pull envoyproxy/envoy:v1.29-latest

# 运行 Envoy 容器
docker run -d --name envoy -p 8080:8080 -v $(pwd)/envoy.yaml:/etc/envoy/envoy.yaml envoyproxy/envoy:v1.29-latest

2.1.2 使用包管理器安装

Ubuntu/Debian

# 添加 Envoy 仓库
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl gnupg2 lsb-release
curl -sL 'https://deb.dl.getenvoy.io/public/gpg.KEY' | sudo gpg --dearmor -o /usr/share/keyrings/getenvoy-archive-keyring.gpg
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/getenvoy-archive-keyring.gpg] https://deb.dl.getenvoy.io/public/deb/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/getenvoy.list

# 安装 Envoy
sudo apt-get update
sudo apt-get install -y getenvoy-envoy

CentOS/RHEL

# 添加 Envoy 仓库
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.dl.getenvoy.io/public/config.rhel/7/public.repo

# 安装 Envoy
sudo yum install -y getenvoy-envoy

2.2 配置文件结构

Envoy 使用 YAML 格式的配置文件,主要包含以下部分:

static_resources:
  listeners:  # 监听器配置
  clusters:   # 集群配置
  secrets:    # 密钥配置

dynamic_resources:
  cds_config:  # 集群发现服务配置
  lds_config:  # 监听器发现服务配置
  eds_config:  # 端点发现服务配置
  rds_config:  # 路由发现服务配置

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

3. 基本使用

3.1 简单代理示例

下面是一个基本的 Envoy 配置,实现 HTTP 代理功能:

static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        address: 0.0.0.0
        port_value: 8080
    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
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: service_backend
          http_filters:
          - name: envoy.filters.http.router
  clusters:
  - name: service_backend
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_backend
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 8081

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

3.2 启动 Envoy

# 使用配置文件启动 Envoy
envoy -c envoy.yaml

# 检查 Envoy 状态
curl http://localhost:9901/config_dump
curl http://localhost:9901/stats

3.3 健康检查

Envoy 提供了丰富的健康检查功能,可以监控后端服务的状态:

clusters:
- name: service_backend
  connect_timeout: 0.25s
  type: STRICT_DNS
  lb_policy: ROUND_ROBIN
  health_checks:
  - timeout: 1s
    interval: 5s
    no_traffic_interval: 30s
    unhealthy_threshold: 3
    healthy_threshold: 2
    http_health_check:
      path: "/health"
  load_assignment:
    cluster_name: service_backend
    endpoints:
    - lb_endpoints:
      - endpoint:
          address:
            socket_address:
              address: 127.0.0.1
              port_value: 8081

4. 高级特性

4.1 流量管理

4.1.1 流量分流

Envoy 支持基于权重的流量分流,用于蓝绿部署、金丝雀发布等场景:

routes:
- match:
    prefix: "/"
  route:
    weighted_clusters:
      clusters:
      - name: service_v1
        weight: 90
      - name: service_v2
        weight: 10

4.1.2 重试策略

route:
  cluster: service_backend
  retry_policy:
    retry_on: "connect-failure,refused-stream,unavailable,cancelled,resource-exhausted,retriable-status-codes"
    num_retries: 3
    retry_back_off:
      base_interval: 0.25s
      max_interval: 1s

4.2 安全配置

4.2.1 TLS 终止

listeners:
- name: listener_0
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 443
  filter_chains:
  - filter_chain_match:
      server_names:
      - "example.com"
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
        common_config:
          tls_certificates:
          - certificate_chain:
              filename: "/etc/envoy/certs/cert.pem"
            private_key:
              filename: "/etc/envoy/certs/key.pem"
    filters:
    - name: envoy.filters.network.http_connection_manager
      # ... 其他配置 ...

4.2.2 mTLS 配置

clusters:
- name: service_backend
  connect_timeout: 0.25s
  type: STRICT_DNS
  lb_policy: ROUND_ROBIN
  transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
      common_config:
        tls_certificates:
        - certificate_chain:
            filename: "/etc/envoy/certs/client-cert.pem"
          private_key:
            filename: "/etc/envoy/certs/client-key.pem"
        validation_context:
          trusted_ca:
            filename: "/etc/envoy/certs/ca-cert.pem"
  load_assignment:
    # ... 其他配置 ...

4.3 可观测性配置

4.3.1 指标收集

admin:
  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: 8080
    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
          # ... 其他配置 ...
          http_filters:
          - name: envoy.filters.http.router
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: /var/log/envoy/access.log
              log_format:
                json_format:
                  time: "%START_TIME%"
                  method: "%REQ(:METHOD)%"
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                  status: "%RESPONSE_CODE%"
                  duration: "%DURATION%"
                  upstream_address: "%UPSTREAM_HOST%"

5. 最佳实践

5.1 性能优化

  • 调整线程数:根据 CPU 核心数设置合适的工作线程数
  • 配置连接池:合理设置连接池大小和超时时间
  • 启用压缩:对 HTTP 响应启用 gzip 压缩
  • 使用 Keep-Alive:启用 TCP Keep-Alive 减少连接建立开销
  • 配置资源限制:设置合适的内存和 CPU 限制

5.2 部署建议

  • 容器化部署:使用 Docker 容器部署 Envoy,便于管理和扩展
  • Kubernetes 集成:在 Kubernetes 环境中,使用 Istio 或直接部署 Envoy 作为 sidecar
  • 配置管理:使用配置管理工具(如 Consul、etcd)存储和管理 Envoy 配置
  • 监控告警:设置合理的监控指标和告警规则,及时发现和处理问题
  • 滚动更新:使用滚动更新策略部署 Envoy,确保服务可用性

5.3 安全最佳实践

  • 定期更新证书:确保 TLS 证书及时更新
  • 使用最小权限:以非 root 用户运行 Envoy
  • 限制管理端口访问:只允许特定 IP 访问管理端口
  • 启用访问日志:记录详细的访问日志,便于审计和故障排查
  • 使用 mTLS:在服务间通信中启用 mTLS,增强安全性

6. 实用案例

6.1 作为边缘代理

场景:在应用架构的最外层部署 Envoy,作为所有入站流量的入口点。

配置示例

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
          route_config:
            name: local_route
            virtual_hosts:
            - name: web_service
              domains:
              - "example.com"
              routes:
              - match:
                  prefix: "/api"
                route:
                  cluster: api_service
              - match:
                  prefix: "/"
                route:
                  cluster: web_service
          http_filters:
          - name: envoy.filters.http.router
  clusters:
  - name: api_service
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: api_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: api.internal
                port_value: 8000
  - name: web_service
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: web_service
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: web.internal
                port_value: 8000

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

6.2 在 Kubernetes 中使用

场景:在 Kubernetes 集群中部署 Envoy 作为服务网格的一部分。

部署示例

apiVersion: apps/v1
kind: Deployment
metadata:
  name: envoy
  labels:
    app: envoy
spec:
  replicas: 2
  selector:
    matchLabels:
      app: envoy
  template:
    metadata:
      labels:
        app: envoy
    spec:
      containers:
      - name: envoy
        image: envoyproxy/envoy:v1.29-latest
        ports:
        - containerPort: 8080
        - containerPort: 9901
        volumeMounts:
        - name: envoy-config
          mountPath: /etc/envoy
      volumes:
      - name: envoy-config
        configMap:
          name: envoy-config
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: envoy-config
data:
  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.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains:
                  - "*"
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      cluster: kubernetes_service
              http_filters:
              - name: envoy.filters.http.router
      clusters:
      - name: kubernetes_service
        connect_timeout: 0.25s
        type: STRICT_DNS
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: kubernetes_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: kubernetes.default.svc.cluster.local
                    port_value: 443
        transport_socket:
          name: envoy.transport_sockets.tls
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
            sni: kubernetes.default.svc.cluster.local
    admin:
      access_log_path: /tmp/admin_access.log
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 9901
---
apiVersion: v1
kind: Service
metadata:
  name: envoy
spec:
  selector:
    app: envoy
  ports:
  - port: 80
    targetPort: 8080
  type: LoadBalancer

6.3 与服务发现集成

场景:使用 Consul 作为服务发现系统,Envoy 自动发现后端服务。

配置示例

dynamic_resources:
  cds_config:
    api_config_source:
      api_type: GRPC
      transport_api_version: V3
      grpc_services:
      - envoy_grpc:
          cluster_name: xds_cluster
  lds_config:
    api_config_source:
      api_type: GRPC
      transport_api_version: V3
      grpc_services:
      - envoy_grpc:
          cluster_name: xds_cluster

static_resources:
  clusters:
  - name: xds_cluster
    connect_timeout: 0.25s
    type: STRICT_DNS
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: xds_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: consul-server
                port_value: 8502

admin:
  access_log_path: /tmp/admin_access.log
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9901

6. 总结

Envoy 是一款功能强大、性能优异的云原生代理,为现代应用架构提供了可靠的网络基础设施。通过本教程的学习,您应该已经掌握了 Envoy 的核心概念、安装配置、基本使用和高级特性,可以根据实际需求灵活应用 Envoy 构建安全、可靠、高性能的服务网络。

6.1 关键要点回顾

  • Envoy 是专为云原生应用设计的边缘和服务代理,提供高性能、可观测性和动态配置等核心特性
  • 掌握 Envoy 的基本配置结构和主要组件,包括 Listener、Filter Chain、Cluster 等
  • 熟悉 Envoy 的高级特性,如流量管理、安全配置和可观测性
  • 遵循最佳实践,优化 Envoy 性能和安全性
  • 根据实际场景灵活应用 Envoy,如作为边缘代理、在 Kubernetes 中使用、与服务发现集成等

6.2 后续学习建议

  • 深入学习 xDS API:了解 Envoy 的动态配置 API,实现更灵活的配置管理
  • 探索 Istio:学习 Istio 服务网格,它基于 Envoy 提供了更高级的服务网格功能
  • 实践项目:在实际项目中应用 Envoy,积累经验和技巧
  • 参与社区:关注 Envoy 社区动态,学习最新特性和最佳实践
  • 性能调优:深入研究 Envoy 的性能调优策略,根据具体场景进行优化

通过不断学习和实践,您将能够充分发挥 Envoy 的强大功能,为您的应用架构提供可靠的网络代理服务。

« 上一篇 APISIX 教程 下一篇 » Istio 教程 - 云原生服务网格