Envoy Gateway 任务

概述

本文档扩展了主配置路径(operator → gateway → route → policy),介绍了超出之前文档涵盖的标准资源配置之外的高级任务。

在 Gateway API 中应用配置变更时,主要有三种方式:

  1. 修改标准 Gateway API 资源:直接编辑 GatewayHTTPRouteTCPRouteUDPRoute 等核心资源。
  2. 通过 PolicyAttachment 附加策略:使用 SecurityPolicyClientTrafficPolicyBackendTrafficPolicy 等策略资源扩展 Gateway 和 Route 的行为。
  3. 配置全局设置:修改 EnvoyGatewayCtl,改变 envoy-gateway 实例行为或影响所有网关的其他全局设置。

本文档聚焦于主配置路径之外的高级任务和特殊场景,包括跨命名空间路由、可观测性设置、部署定制和故障排查。

前提条件

  1. 配置 EnvoyGatewayCtl
  2. 配置 Gateway
  3. 配置 Route
  4. 配置 GatewayAPI 策略

高级任务

OpenTelemetry (OTel)

请按照 OpenTelemetry 集成 中的说明操作,但使用 EnvoyGatewayCtl 修改 envoy-gateway-config

如何附加到其他命名空间创建的 Listener

在 Gateway 的 listener 配置中,需要指定允许哪些命名空间将 Routes 附加到该 Listener。

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
spec:
  listeners:
    - name: http-80
      protocol: HTTP
      port: 80
      allowedRoutes:
        namespaces:
          from: All # 不限制
    - name: http-81
      protocol: HTTP
      port: 81
      allowedRoutes:
        namespaces:
          from: Same # 仅允许同命名空间的 Routes
    - name: http-82
      protocol: HTTP
      port: 82
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              team: frontend # 仅允许带有标签 team=frontend 的命名空间中的 Routes

详情请参阅 跨命名空间路由

如何使用其他命名空间创建的证书

若要使用其他命名空间创建的证书,需要在证书所在命名空间创建 ReferenceGrant。请参考 跨命名空间证书引用referencegrant 的说明。

NOTE

不能指定单个 secret 资源,必须允许整个命名空间

如何使用 SSL 透传

请参考以下文档:

如何修改最低 TLS 版本

请参考 自定义 Gateway TLS 参数

cat <<EOF | kubectl apply -f -
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: ClientTrafficPolicy
metadata:
  name: enforce-tls-13
  namespace: default
spec:
  targetRefs:
  - group: gateway.networking.k8s.io
    kind: Gateway
    name: eg
  tls:
    minVersion: "1.3"
EOF

ClientTrafficPolicy 中的 .spec.tls 字段是 clienttlssettings。如果除了最低 TLS 版本外还需要自定义密码套件,请参考同一上游任务和 API 参考。

如何在使用 NodePort 服务时指定 NodePort

使用 NodePort 服务时,Kubernetes 会为每个服务端口分配一个 NodePort。通过节点 IP 访问服务时,应使用分配的 NodePort,而非服务端口。

有两种方式:

手动获取 NodePort 分配,参考 从 svc 端口获取 nodeport

EnvoyProxy 配置中手动指定 NodePort,而非让 Kubernetes 自动分配。

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: demo
spec:
  ipFamily: DualStack
  provider:
    kubernetes:
      envoyDeployment:
        container:
          imageRepository: registry.alauda.cn:60080/acp/envoyproxy/envoy
      envoyService:
        patch:
          type: StrategicMerge
          value:
            spec:
              ports:
                - nodeport: 31888
                  port: 80
        type: NodePort
    type: Kubernetes
  1. 使用 patch 字段对生成的 Service 资源进行补丁,指定 NodePort
NOTE

NodePort 只能在特定范围内,通常为 30000-32767。若希望 Gateway listener 端口与 NodePort 一致,listener 端口也必须在 NodePort 范围内。

如何在使用 MetalLB 时指定 VIP

使用 MetalLB 作为 LoadBalancer 提供者时,可以通过 Service 注解为 Gateway 服务指定静态 VIP。

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: demo
  namespace: demo
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyService:
        type: LoadBalancer
        annotations:
          metallb.universe.tf/address-pool: production
          metallb.universe.tf/loadBalancerIPs: VIP_IP
  1. envoyService.annotations 字段添加 MetalLB 注解
  2. 指定地址池名称以从中分配 IP
  3. 或指定具体 IP 地址(必须在地址池范围内)

可用注解:

注解说明
metallb.universe.tf/address-pool选择用于分配 IP 的地址池
metallb.universe.tf/loadBalancerIPs指定具体 IP 地址(支持多个,逗号分隔)
NOTE
  • 指定的 IP 必须在已配置的 MetalLB 地址池内
  • 确保 MetalLB 已正确安装和配置后再指定 VIP
  • 有关 MetalLB 配置,请参阅 配置 MetalLB

如何在 Envoy Gateway 中添加 Pod 注解

添加 Pod 注解

如何为 envoy-gateway-operator 设置 NodeSelector 和 Tolerations

更新 Subscription 资源。

# nodeSelector 和 tolerations 示例
kubectl patch subscription envoy-gateway-operator  -n envoy-gateway-operator   --type='merge' -p '
{
  "spec": {
    "config": {
      "nodeSelector": {
        "node-role.kubernetes.io/infra": ""
      },
      "tolerations": [
        {
          "effect": "NoSchedule",
          "key": "node-role.kubernetes.io/infra",
          "operator": "Equal",
          "value": "reserved"
        }
      ]
    }
  }
}'

如何为 envoy-gateway 设置 NodeSelector 和 Tolerations

更新 EnvoyGatewayCtl 资源。

# 默认情况下 $NAME=cpaas-default,$NS=envoy-gateway-operator
kubectl patch envoygatewayctl $NAME -n $NS --type='merge' -p '
{
  "spec": {
    "deployment": {
      "pod": {
        "nodeSelector": {
          "node-role.kubernetes.io/infra": ""
        },
        "tolerations": [
          {
            "effect": "NoSchedule",
            "key": "node-role.kubernetes.io/infra",
            "operator": "Equal",
            "value": "reserved"
          }
        ]
      }
    }
  }
}'

如何为 envoy-proxy 设置 NodeSelector 和 Tolerations

更新 EnvoyProxy 资源。

kubectl patch envoyproxy $NAME -n $NS --type='merge' -p '
{
  "spec": {
    "provider": {
      "kubernetes": {
        "envoyDeployment": {
          "pod": {
            "nodeSelector": {
              "node-role.kubernetes.io/infra": ""
            },
            "tolerations": [
              {
                "effect": "NoSchedule",
                "key": "node-role.kubernetes.io/infra",
                "operator": "Equal",
                "value": "reserved"
              }
            ]
          }
        }
      }
    }
  }
}'

如何在 envoy-proxy 中使用 hostNetwork

使用 hostNetwork: true 允许 Envoy proxy Pod 直接使用宿主机网络命名空间。适用于:

  • 提升网络性能
  • 通过节点 IP 直接访问网关

注意事项:

  • 使用 hostNetwork 的 Pod 会直接绑定宿主机网络接口
  • 若多个 Pod 在同一节点使用相同端口,可能发生端口冲突
  • 安全隔离降低,Pod 共享宿主机网络命名空间
  • 建议使用 nodeSelectoraffinity 规则控制 Pod 调度,避免端口冲突

配置 hostNetwork 有两种方式,取决于是否需要直接使用特权端口(< 1024):

方式一:使用端口偏移(默认,推荐)

这是默认且推荐的方式。Envoy Gateway 会自动对特权端口加上 10000 的偏移,避免需要特殊权限。

优点:

  • 无需特殊权限或能力
  • 更安全,作为非 root 用户运行,无额外权限
  • 配置简单
  • 开箱即用

缺点:

  • 客户端需使用偏移端口(10080、10443)

配置示例:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: demo
  namespace: demo
spec:
  provider:
    type: Kubernetes
    kubernetes:
      envoyDeployment:
        patch:
          type: StrategicMerge
          value:
            spec:
              template:
                spec:
                  hostNetwork: true                    # 启用 hostNetwork 模式
                  dnsPolicy: ClusterFirstWithHostNet   # 保证 DNS 正确解析
        pod:
          nodeSelector:                                # 推荐:控制 Pod 调度避免冲突
            kubernetes.io/hostname: "demo"

访问方式:

  • 端口 80 → 通过 http://<node-ip>:10080 访问
  • 端口 443 → 通过 https://<node-ip>:10443 访问

方式二:使用特权端口,启用 useListenerPortAsContainerPort

此方式允许 Envoy 直接绑定特权端口(< 1024),如 80 和 443。

优点:

  • 可直接使用标准端口 80 和 443
  • 与期望标准端口的客户端兼容性更好

缺点:

  • 需要 NET_BIND_SERVICE 能力
  • 安全性较端口偏移方式略低
  • 配置更复杂

配置示例:

apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: demo
  namespace: demo
spec:
  provider:
    type: Kubernetes
    kubernetes:
      useListenerPortAsContainerPort: true  # 关闭端口偏移
      envoyDeployment:
        patch:
          type: StrategicMerge
          value:
            spec:
              template:
                spec:
                  hostNetwork: true
                  dnsPolicy: ClusterFirstWithHostNet
                  containers:
                  - name: envoy
                    command:
                      - /usr/local/bin/envoy-with-cap  # 使用带 filecap 的 envoy
                    securityContext:
                      capabilities:
                        add:
                        - NET_BIND_SERVICE  # 绑定特权端口所需
        pod:
          nodeSelector:                                # 推荐:控制 Pod 调度避免冲突
            kubernetes.io/hostname: "demo"

访问方式:

  • 端口 80 → 通过 http://<node-ip>:80 访问
  • 端口 443 → 通过 https://<node-ip>:443 访问

如何从集群内部访问 LoadBalancer VIP

默认情况下,Envoy Gateway 创建的 LoadBalancer 服务使用 externalTrafficPolicy: Local。该策略保留客户端源 IP,但存在重要限制:来自没有 Envoy Gateway Pod 的集群节点的请求会失败,因为流量不会转发到其他节点。

解决方案 1:使用 Service ClusterIP(推荐集群内访问)

集群内运行的应用应使用服务的 ClusterIP,而非 LoadBalancer VIP,避免路由限制。

解决方案 2:修改为 Cluster 流量策略

若需从任意集群节点访问 LoadBalancer VIP,可将 externalTrafficPolicy 改为 Cluster

kubectl patch envoyproxy $GATEWAY_NAME -n $GATEWAY_NS --type='json' -p='[
  {"op": "replace", "path": "/spec/provider/kubernetes/envoyService/externalTrafficPolicy", "value": "Cluster"}
]'

相关文档

更多配置

请参阅 EnvoyGateway 任务