使用 Kubernetes Gateway API 通过网关路由出口流量

本节介绍如何使用 Kubernetes Gateway API 将出站 HTTP 流量通过出口网关进行路由。

目录

前提条件

  • 已安装 Alauda Service Mesh v2 Operator。
  • 已部署 Istio 控制平面。

操作步骤

  1. 使用以下命令创建一个名为 egress-gateway 的命名空间:

    kubectl create namespace egress-gateway
  2. 创建一个名为 egress-gateway-cr.yaml 的 YAML 文件,用于定义出口网关。

    出口网关 CR 文件示例
    # ServiceEntry 允许访问 httpbin.org 的流量
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: httpbin-ext
    spec:
      hosts:
        - httpbin.org
      ports:
        - number: 80
          name: http
          protocol: HTTP
      location: MESH_EXTERNAL
      resolution: DNS
    ---
    # Gateway API 的出口 Gateway
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-egress-gateway
      annotations:
        networking.istio.io/service-type: ClusterIP
    spec:
      gatewayClassName: istio
      listeners:
        - name: http
          hostname: httpbin.org
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: All
    ---
    # HTTPRoute 将流量从 sidecar 定向到出口网关
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: direct-httpbin-to-egress-gateway
    spec:
      parentRefs:
        - kind: ServiceEntry
          group: networking.istio.io
          name: httpbin-ext
      rules:
        - backendRefs:
            - name: httpbin-egress-gateway-istio
              port: 80
    ---
    # HTTPRoute 将流量从出口网关转发到 httpbin.org
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: forward-httpbin-from-egress-gateway
    spec:
      parentRefs:
        - name: httpbin-egress-gateway
      hostnames:
        - httpbin.org
      rules:
        - backendRefs:
            - kind: Hostname
              group: networking.istio.io
              name: httpbin.org
              port: 80

    通过执行以下命令应用该 YAML 文件:

    kubectl -n egress-gateway apply -f egress-gateway-cr.yaml
  3. 通过运行以下命令检查网关配置状态:

    kubectl -n egress-gateway get gtw httpbin-egress-gateway

    PROGRAMMED 列的值为 True 时,表示配置成功。

    示例输出

    NAME                     CLASS   ADDRESS                                                         PROGRAMMED   AGE
    httpbin-egress-gateway   istio   httpbin-egress-gateway-istio.egress-gateway.svc.cluster.local   True         22h

验证

  1. 通过执行以下命令创建一个名为 curl 的命名空间:

    kubectl create namespace curl
  2. 为该命名空间启用 sidecar 注入。如果您的环境使用 InPlace 升级策略,运行以下命令:

    kubectl label namespace curl istio-injection=enabled
    NOTE

    如果您使用的是 RevisionBased 升级策略,请执行以下命令:

    1. 运行以下命令以查询您的 <revision-name>

      kubectl get istiorevisions.sailoperator.io

      示例输出:

      NAME      NAMESPACE      PROFILE   READY   STATUS    IN USE   VERSION   AGE
      default   istio-system             True    Healthy   True     v1.26.3   47h
    2. 使用查询到的 revision 名称为命名空间打标签以启用 sidecar 注入:

      kubectl label namespace curl istio.io/rev=default
  3. 通过运行以下命令部署 curl 应用:

    kubectl apply -n curl -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/curl/curl.yaml
  4. 初始化并导出一个名为 CURL_POD 的环境变量,包含 curl pod 的名称:

    export CURL_POD=$(kubectl get pod -n curl -l app=curl -o jsonpath='{.items[0].metadata.name}')
  5. 使用 curl 客户端确认是否能通过出口网关访问 httpbin.org,执行以下命令:

    kubectl exec "$CURL_POD" -n curl -c curl -- curl -s -v http://httpbin.org/get

    期望输出显示来自 httpbin.org 的响应,表明出口流量已通过配置的网关进行路由。

    示例输出

    ...
    {
      "headers": {
        "Host": "httpbin.org",
        "User-Agent": "curl/8.15.0",
        "X-Envoy-Peer-Metadata-Id": "router~10.3.0.58~httpbin-egress-gateway-istio-7db8cbfc64-72g85.egress-gateway~egress-gateway.svc.cluster.local"
        ...
      },
      "url": "http://httpbin.org/get"
    }
    < HTTP/1.1 200 OK
    < server: envoy
    ...