Envoy Gateway 任务

概述

在完成主要配置路径后,请使用这些高级 Envoy Gateway 任务:operator、gateway、route 和 policy。

在 Gateway API 中应用配置更改时,主要有三种可用方法:

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

高级任务和特殊场景包括跨命名空间路由、 可观测性设置、部署自定义和故障排查。

前提条件

  1. 配置 EnvoyGatewayCtl
  2. 配置 Gateway
  3. 配置 Route
  4. 配置 GatewayAPI Policy

高级任务

OpenTelemetry (OTel)

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

如何附加到在其他命名空间中创建的监听器

在 Gateway 的监听器配置中,你需要指定允许哪些命名空间向其附加 Routes。

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 # without limit
    - name: http-81
      protocol: HTTP
      port: 81
      allowedRoutes:
        namespaces:
          from: Same # only allow routes in the same namespace
    - name: http-82
      protocol: HTTP
      port: 82
      allowedRoutes:
        namespaces:
          from: Selector
          selector:
            matchLabels:
              team: frontend # only allow routes in the namespace with label team=frontend

有关更多详细信息,请参阅 跨命名空间路由

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

要使用在其他命名空间中创建的证书,请在存储证书的命名空间中创建一个 ReferenceGrant。请按照 cross-namespace-certificate-referencesreferencegrant 中的说明进行操作。

NOTE

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

如何使用 SSL Passthrough

请按照以下说明进行操作:

如何更改最小 TLS 版本

请按照 customize-gateway-tls-parameters 中的说明进行操作

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 Service 时指定 NodePort

在使用 NodePort service 时,Kubernetes 会为每个 service 端口分配一个 NodePort 值。通过节点 IP 访问 service 时,请使用分配的 NodePort,而不是 service 端口。

有两种方法:

按照 get nodeport from svc port 手动获取 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 监听器端口和 NodePort 保持一致,那么监听器端口也必须位于 NodePort 范围内。

如何在使用 MetalLB 时指定 VIP

当使用 MetalLB 作为 LoadBalancer 提供程序时,你可以通过 service 注解为 Gateway service 指定一个静态 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 地址(支持多个 IP,使用逗号分隔)
NOTE
  • 指定的 IP 必须位于已配置的 MetalLB 地址池中
  • 在指定 VIP 之前,请确保 MetalLB 已正确安装和配置
  • 有关 MetalLB 配置,请参阅 Configure MetalLB

如何在 Envoy Gateway 中添加 Pod 注解

EnvoyProxy.spec.provider.kubernetes.envoyDeployment.patch.value.spec.template.metadata.annotations 中设置 annotations

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: demo
spec:
  infrastructure:
    parametersRef:
      group: gateway.envoyproxy.io
      kind: EnvoyProxy
      name: demo
  gatewayClassName: envoy-gateway-operator-cpaas-default
  listeners:
    - name: http
      port: 80
      protocol: HTTP
---
apiVersion: gateway.envoyproxy.io/v1alpha1
kind: EnvoyProxy
metadata:
  name: demo
spec:
  provider:
    kubernetes:
      envoyDeployment:
        replicas: 1
        patch:
          type: StrategicMerge
          value:
            spec:
              template:
                metadata:
                  annotations:
                    your-annotation-key: 'your-annotation-value'
        container:
          imageRepository: registry.alauda.cn:60080/acp/envoyproxy/envoy
    type: Kubernetes

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

更新 Subscription 资源。

# example of nodeSelector and 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 资源。

# in default $NAME=cpaas-default and $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 Pods 直接使用宿主机网络命名空间。这在以下场景中很有用:

  • 获得更好的网络性能
  • 通过节点 IP 直接访问 gateway

注意事项:

  • 使用 hostNetwork 的 Pods 会直接绑定到宿主机的网络接口
  • 如果多个 Pods 尝试在同一节点上使用同一端口,可能会发生端口冲突
  • 由于 Pods 共享宿主机的网络命名空间,安全隔离会降低
  • 你应该使用 nodeSelectoraffinity 规则来控制 Pod 调度位置并避免端口冲突

根据你是否希望直接使用特权端口(< 1024),有两种配置 hostNetwork 的方法:

方法 1:使用端口偏移(默认,推荐)

这是默认且推荐的方法。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                    # Enable host network mode
                  dnsPolicy: ClusterFirstWithHostNet   # Required for proper DNS resolution
        pod:
          nodeSelector:                                # Recommended: control pod placement to avoid conflict
            kubernetes.io/hostname: "demo"

访问方式:

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

方法 2:使用 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  # Disable port offset
      envoyDeployment:
        patch:
          type: StrategicMerge
          value:
            spec:
              template:
                spec:
                  hostNetwork: true
                  dnsPolicy: ClusterFirstWithHostNet
                  containers:
                  - name: envoy
                    command:
                      - /usr/local/bin/envoy-with-cap  # use envoy with filecap
                    securityContext:
                      capabilities:
                        add:
                        - NET_BIND_SERVICE  # Required for binding to privileged ports
        pod:
          nodeSelector:                                # Recommended: control pod placement to avoid conflict
            kubernetes.io/hostname: "demo"

访问方式:

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

如何从集群内部访问 LoadBalancer VIP

默认情况下,Envoy Gateway 会创建 externalTrafficPolicy: Local 的 LoadBalancer service。此策略可保留客户端源 IP 地址,但有一个重要限制:来自没有 Envoy Gateway Pods 的集群节点的请求将会失败,因为流量不会转发到其他节点。

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

对于在集群内部运行的应用,请使用 service 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 Tasks