探索Envoy和Kong的世界,了解流量管理、安全性和性能优化的高级模式。您将学习多租户路由、自定义插件,以及如何实现零信任架构,即使是最偏执的安全专家也会点头称赞。

流量管理:驯服请求的狂野西部

让我们从流量管理开始。在微服务的世界中,管理流量就像赶猫一样——混乱、不可预测,有时还很搞笑。

负载均衡:不仅仅是健身爱好者的专利

Envoy和Kong提供了超越简单轮询策略的复杂负载均衡功能。让我们看看一些高级技术:

  • 最少请求:将请求路由到活动请求最少的实例。适合那些情绪多变的服务。
  • 加权轮询:允许为不同实例分配不同的权重。当您有一台强大的服务器可以处理比其他服务器更多的负载时,这非常有用。
  • 环形哈希:根据键一致地将请求映射到同一实例。适用于缓存以及希望同一用户的请求总是命中同一服务器的情况。

以下是如何在Envoy中配置加权负载均衡的一个简单示例:


clusters:
  - name: my_backend_service
    type: STRICT_DNS
    lb_policy: WEIGHTED_ROUND_ROBIN
    load_assignment:
      cluster_name: my_backend_service
      endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: backend1.example.com
                  port_value: 8080
            load_balancing_weight: 75
          - endpoint:
              address:
                socket_address:
                  address: backend2.example.com
                  port_value: 8080
            load_balancing_weight: 25

断路器:因为有时候你得知道什么时候该放手

断路器就像是为您的服务配备了保镖。它可以防止一个失败的服务拖垮整个系统。Envoy和Kong都支持断路器,但让我们看看Envoy的实现:


clusters:
  - name: my_backend_service
    type: STRICT_DNS
    circuit_breakers:
      thresholds:
        - priority: DEFAULT
          max_connections: 1000
          max_pending_requests: 1000
          max_requests: 1000
          max_retries: 3

此配置为连接、挂起请求、活动请求和重试设置了断路器阈值。当这些阈值被超出时,Envoy将开始拒绝请求以保护系统。

多租户路由:与他人友好相处

在多租户环境中,您需要确保不同租户的流量被隔离并正确路由。Kong在这方面表现出色,拥有强大的路由能力。

通往幸福的路

以下是如何在Kong中设置多租户路由的示例:


# 创建服务
curl -i -X POST http://localhost:8001/services \
  --data name=myservice \
  --data url='http://myservice.com'

# 为租户A创建路由
curl -i -X POST http://localhost:8001/services/myservice/routes \
  --data 'hosts[]=tenanta.myapi.com' \
  --data 'paths[]=/v1/tenanta'

# 为租户B创建路由
curl -i -X POST http://localhost:8001/services/myservice/routes \
  --data 'hosts[]=tenantb.myapi.com' \
  --data 'paths[]=/v1/tenantb'

此设置确保租户A和租户B的请求被正确路由到各自的端点,即使它们访问的是同一底层服务。

请求转换:改变您的API

有时,您的后端服务与客户端使用不同的语言。这时,请求转换就派上用场了。Kong的请求转换插件就像是您的API的通用翻译器。

不再迷失在翻译中!

以下是如何使用请求转换插件修改头和查询参数:


curl -X POST http://localhost:8001/routes/{route_id}/plugins \
    --data "name=request-transformer" \
    --data "config.add.headers=x-tenant-id:$(tenant_id)" \
    --data "config.add.querystring=version:v2" \
    --data "config.rename.headers=x-old-header:x-new-header"

此配置添加了租户ID头,附加了版本查询参数,并重命名了现有头。就像在请求到达后端服务之前给它们做了一次改造。

高级限流:保持派对的秩序

限流对于保护您的API免受滥用并确保公平使用至关重要。但基本的限流已经过时了。让我们看看Kong的一些高级限流技术。

增强版限流

Kong的限流插件提供了高级功能,如按头值或消费者组限流。以下是一个配置示例:


curl -X POST http://localhost:8001/plugins \
    --data "name=rate-limiting" \
    --data "config.limit=5" \
    --data "config.window_size=30" \
    --data "config.limit_by=header" \
    --data "config.header_name=x-consumer-group"

此设置基于消费者组头限制请求,允许您为不同类型的用户或租户实施分级限流。

自定义插件开发:因为有时候你得自己动手

现成的插件很好,但有时您需要量身定制的东西。Envoy和Kong都允许您开发自定义插件以扩展其功能。

制作您自己的Kong插件

以下是一个自定义Kong插件的示例:


local CustomPlugin = {
  PRIORITY = 1000,
  VERSION = "1.0.0",
}

function CustomPlugin:access(conf)
  -- 您的自定义逻辑
  kong.log.debug("来自CustomPlugin的问候!")
  
  local headers = kong.request.get_headers()
  if not headers["x-api-key"] then
    return kong.response.exit(401, { message = "缺少API密钥" })
  end
end

return CustomPlugin

这个简单的插件检查API密钥的存在,如果缺少则返回401。可能性是无穷的——您可以实现自定义身份验证、复杂的转换,甚至与外部服务集成。

安全最佳实践:偏执即服务

在API的世界中,安全不仅重要——它至关重要。让我们探索一些可以通过Envoy和Kong实现的高级安全模式。

mTLS:因为在技术中信任问题是健康的

双向TLS(mTLS)确保客户端和服务器都验证彼此的证书。以下是如何在Envoy中配置mTLS:


listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 8443
    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: backend
              domains:
              - "*"
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: service_backend
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
          require_client_certificate: true
          common_tls_context:
            tls_certificates:
            - certificate_chain:
                filename: "/etc/envoy/certs/server.crt"
              private_key:
                filename: "/etc/envoy/certs/server.key"
            validation_context:
              trusted_ca:
                filename: "/etc/envoy/certs/ca.crt"

JWT验证:谁在那里?

JSON Web Tokens(JWTs)是一种流行的身份验证和授权方法。Kong的jwt插件使验证JWT变得简单:


curl -X POST http://localhost:8001/routes/{route_id}/plugins \
    --data "name=jwt" \
    --data "config.secret_is_base64=false" \
    --data "config.claims_to_verify=exp"

此配置在特定路由上启用JWT验证,检查令牌的过期声明。

零信任架构:不信任任何人,甚至自己

使用API网关实现零信任架构涉及多个组件:

  • 基于身份的访问:为每个请求使用强身份验证。
  • 微分段:在服务级别实施细粒度的访问控制。
  • 持续监控:利用Envoy和Kong的日志记录和监控功能检测异常。

以下是如何使用Kong的key-auth插件结合ACL实现基于身份的访问的示例:


# 启用密钥认证
curl -X POST http://localhost:8001/routes/{route_id}/plugins \
    --data "name=key-auth"

# 创建消费者
curl -X POST http://localhost:8001/consumers \
    --data "username=alice"

# 为消费者创建密钥
curl -X POST http://localhost:8001/consumers/alice/key-auth \
    --data "key=secret_key_123"

# 启用ACL插件
curl -X POST http://localhost:8001/routes/{route_id}/plugins \
    --data "name=acl" \
    --data "config.whitelist=group_a"

# 将消费者分配到组
curl -X POST http://localhost:8001/consumers/alice/acls \
    --data "group=group_a"

此设置确保只有具有正确组成员身份的经过身份验证的用户才能访问受保护的路由。

调试和性能调优:当事情出错时

即使是最周密的计划,也可能出错。让我们看看一些调试和优化API网关设置的策略。

专业日志记录

Envoy和Kong都提供了广泛的日志记录功能。以下是如何在Envoy中配置详细的访问日志:


static_resources:
  listeners:
  - 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
          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%"
                  protocol: "%PROTOCOL%"
                  duration: "%DURATION%"
                  request_method: "%REQ(:METHOD)%"
                  request_host: "%REQ(HOST)%"
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                  response_code: "%RESPONSE_CODE%"
                  response_flags: "%RESPONSE_FLAGS%"
                  bytes_received: "%BYTES_RECEIVED%"
                  bytes_sent: "%BYTES_SENT%"
                  upstream_host: "%UPSTREAM_HOST%"
                  upstream_cluster: "%UPSTREAM_CLUSTER%"
                  upstream_local_address: "%UPSTREAM_LOCAL_ADDRESS%"

此配置设置了详细的JSON格式访问日志,对于调试和性能分析非常有价值。

性能调优:榨取每一滴性能

在性能调优方面,有几个领域需要关注:

  • 连接池:正确配置连接池以平衡资源使用和性能。
  • 缓存:在网关级别实现缓存以减少后端服务的负载。
  • 超时和重试策略:微调这些设置以在弹性和响应性之间取得平衡。

以下是如何在Envoy中配置连接池的示例:


clusters:
  - name: my_backend_service
    type: STRICT_DNS
    connect_timeout: 0.25s
    lb_policy: ROUND_ROBIN
    http2_protocol_options: {}
    upstream_connection_options:
      tcp_keepalive:
        keepalive_time: 300
    max_requests_per_connection: 1000
    circuit_breakers:
      thresholds:
        - priority: DEFAULT
          max_connections: 100
          max_pending_requests: 1000
          max_requests: 1000
    health_checks:
      - timeout: 1s
        interval: 10s
        unhealthy_threshold: 3
        healthy_threshold: 2
        http_health_check:
          path: "/healthz"

此配置设置了带有keep-alive的连接池,限制每个连接的请求数量,配置断路器,并为后端服务设置健康检查。

总结:通往API极乐的网关

我们已经探索了Envoy和Kong的API网关高级模式,从复杂的流量管理到坚如磐石的安全实践。记住,能力越大,责任越大——当然也有可能实现一些非常酷的API设置。

在实施这些模式时,请记住每个系统都是独特的。对一个系统有效的方法可能对另一个无效。始终测试、测量和迭代。最重要的是,享受乐趣!毕竟,如果您不享受构建API基础设施的过程,那您可能做错了。

现在,带着您对高级网关模式的新知识,去征服API宇宙吧。愿您的请求迅速,安全性紧密,服务始终可用!

“做伟大工作的唯一方法就是热爱你所做的事情。” - 史蒂夫·乔布斯

(当然,还要有一个非常棒的API网关设置。)