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

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

前提条件

  • 已安装 Alauda Service Mesh v2 Operator。
  • 已部署 Istio 控制平面。
  • 请确认Linux 内核兼容性

操作步骤

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

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

    出口网关 CR 文件示例
    # 允许访问 httpbin.org 的 ServiceEntry
    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
      labels:
        # 指定 Istio 版本名称,默认为 'default'
        istio.io/rev: default
    spec:
      gatewayClassName: istio
      listeners:
        - name: http
          hostname: httpbin.org
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: All
    ---
    # 将流量从 sidecar 定向到出口网关的 HTTPRoute
    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
    ---
    # 将流量从出口网关转发到 httpbin.org 的 HTTPRoute
    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         68s
  4. 可选:将网关部署到 Infra Nodes

    点击展开
    前提条件

    需要 Alauda Container Platform 4.2.0 或更高版本,或将 Gateway API CRDs 升级到最新版本。

    a. 在计划部署 Gateway 的同一命名空间中创建名为 asm-kube-gateway-options 的 ConfigMap:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: asm-kube-gateway-options
      namespace: egress-gateway
    data:
      deployment: |
        spec:
          template:
            spec:
              nodeSelector:
                node-role.kubernetes.io/infra: ""
              tolerations:
                - effect: NoSchedule
                  key: node-role.kubernetes.io/infra
                  value: reserved
                  operator: Equal
    1. 指定 ConfigMap 的名称。
    2. 指定 ConfigMap 的命名空间,与网关相同。
    3. 设置节点选择器和容忍度,将网关 Pod 调度到 Infra Nodes。

    b. 在 Gateway 资源中通过添加 infrastructure.parametersRef 字段引用该 ConfigMap:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-egress-gateway
      namespace: egress-gateway
    spec:
      # 在 Gateway CR 中添加以下基础设施配置
      infrastructure:
        parametersRef:
          group: ""
          kind: ConfigMap
          name: asm-kube-gateway-options
      # ... 其余 Gateway 配置
    1. 指定网关名称。
    2. 指定网关命名空间。

验证

  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.28.3   47h
    2. 使用版本名称为命名空间打标签以启用 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}')
    echo "CURL_POD=$CURL_POD"
  5. 使用 curl 客户端确认可以通过出口网关访问 httpbin.org,执行以下命令:

    kubectl exec "$CURL_POD" -n curl -c curl -- curl -sS -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
    ...