使用 Kubernetes Gateway API 在 ambient 模式下通过网关路由出口流量

本指南演示如何结合 Kubernetes Gateway API 和 waypoint 代理,在 ambient 模式下通过出口网关路由出站 HTTP 流量。

前提条件

  • 已安装 Alauda Service Mesh v2 Operator。
  • IstioIstioCNI 资源已使用 ambient 配置文件进行配置。
  • 已创建 Ztunnel 资源。
  • 请确认Linux 内核兼容性

操作步骤

  1. 创建名为 egress-gateway 的命名空间:

    kubectl create namespace egress-gateway
  2. egress-gateway 命名空间添加 istio-discovery=enabled 标签:

    kubectl label namespace egress-gateway istio-discovery=enabled
  3. 通过应用数据平面模式标签启用该命名空间的 ambient 模式:

    kubectl label namespace egress-gateway istio.io/dataplane-mode=ambient
  4. 创建名为 egress-se.yaml 的 YAML 文件,定义外部服务的 ServiceEntryistio.io/use-waypoint 标签将该条目与 waypoint 代理关联。

    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: httpbin-ext
      namespace: egress-gateway
      labels:
        istio.io/use-waypoint: waypoint
    spec:
      hosts:
        - httpbin.org
      ports:
        - number: 80
          name: http
          protocol: HTTP
      resolution: DNS
    1. 指示此 ServiceEntry 的流量通过同一命名空间中名为 waypoint 的 waypoint 代理。
  5. 应用该 ServiceEntry

    kubectl apply -f egress-se.yaml
  6. 创建名为 waypoint.yaml 的 YAML 文件,在 egress-gateway 命名空间部署 waypoint 代理。waypoint 代理拦截并处理该命名空间内服务的 L7 流量。

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: waypoint
      namespace: egress-gateway
      labels:
        istio.io/waypoint-for: service
    spec:
      gatewayClassName: istio-waypoint
      listeners:
        - name: mesh
          port: 15008
          protocol: HBONE
    1. istio.io/waypoint-for: service 标签表示该 waypoint 处理服务的流量。标签值决定处理的流量类型。详情请参见 Waypoint traffic types(Istio 文档)。
    2. 指定 istio-waypoint 网关类,部署的是 waypoint 代理,而非标准的入口网关。
  7. 应用 waypoint 代理配置:

    kubectl apply -f waypoint.yaml
    NOTE

    除了手动创建 YAML 文件外,还可以使用以下命令部署 waypoint 代理:

    istioctl waypoint apply --enroll-namespace --name waypoint --namespace egress-gateway

    使用 --enroll-namespace 选项时,egress-gateway 命名空间中的所有服务(包括 ServiceEntry)都会通过该 waypoint 路由流量。

验证

  1. 通过检查状态确认 waypoint 代理已就绪:

    kubectl get gateways.gateway.networking.k8s.io waypoint -n egress-gateway

    PROGRAMMED 列应显示 True,表示配置成功。

    示例输出

    NAME       CLASS            ADDRESS      PROGRAMMED   AGE
    waypoint   istio-waypoint   10.4.61.76   True         38s
  2. egress-gateway 命名空间部署 curl 客户端:

    kubectl apply -n egress-gateway -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/curl/curl.yaml
  3. curl pod 名称存储到变量中:

    export CURL_POD=$(kubectl get pods -n egress-gateway -l app=curl -o jsonpath='{.items[*].metadata.name}')
    echo "CURL_POD=$CURL_POD"
  4. curl 客户端验证是否能通过出口网关访问 httpbin.org

    kubectl exec $CURL_POD -n egress-gateway -- \
      curl -sS -v http://httpbin.org/get

    成功收到来自 httpbin.org 的响应,说明出口流量已通过配置的网关路由。

    示例输出

    < HTTP/1.1 200 OK
    ...
    < server: istio-envoy
    ...

    ztunnel 日志应显示流量通过 waypoint,类似如下输出:

    示例 ztunnel 日志输出

    2026-03-09T10:18:02.686121Z	info	access	connection complete
      src.addr=10.3.0.134:35092
      src.workload="curl-c658c5974-6zsnb"
      src.namespace="egress-gateway"
      src.identity="spiffe://cluster.local/ns/egress-gateway/sa/curl"
      dst.addr=10.3.0.131:15008
      dst.hbone_addr=240.240.0.3:80
      dst.service="httpbin.org"
      dst.workload="waypoint-7d688546dc-v8x9c"
      dst.namespace="egress-gateway"
      dst.identity="spiffe://cluster.local/ns/egress-gateway/sa/waypoint"
      direction="outbound"
      bytes_sent=78
      bytes_recv=641
      duration="790ms"

清理

删除 egress-gateway 命名空间及所有相关资源:

# 从 ambient 数据平面移除该命名空间标签
kubectl label namespace egress-gateway istio.io/dataplane-mode-
# 删除命名空间
kubectl delete namespace egress-gateway