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

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

前提条件

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

操作步骤

  1. 使用以下命令创建名为 egress-gateway 的 namespace:

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

    出口网关 CR 文件示例
    # ServiceEntry to allow traffic to 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 for egress
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-egress-gateway
      annotations:
        networking.istio.io/service-type: ClusterIP
      labels:
        # Specify the Istio revision name; defaults to 'default'
        istio.io/rev: default
    spec:
      gatewayClassName: istio
      listeners:
        - name: http
          hostname: httpbin.org
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: All
    ---
    # HTTPRoute to direct traffic from sidecars to the egress gateway
    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 to forward traffic from the egress gateway to 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         68s
  4. 可选:将网关部署到 基础设施节点

    点击展开
    前提条件

    Alauda Container Platform 4.2.0 或更高版本,或者将 Gateway API CRD 升级到最新版本。

    a. 在计划部署 Gateway 的同一 namespace 中创建名为 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 的 namespace,与 gateway 相同。
    3. 设置 node selector 和 toleration,将 gateway pod 调度到基础设施节点。

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

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-egress-gateway
      namespace: egress-gateway
    spec:
      # Add the following infrastructure configuration to your Gateway CR
      infrastructure:
        parametersRef:
          group: ""
          kind: ConfigMap
          name: asm-kube-gateway-options
      # ... rest of your Gateway configuration
    1. 指定 gateway 的名称。
    2. 指定 gateway 的 namespace。

验证

  1. 使用以下命令创建名为 curl 的 namespace:

    kubectl create namespace curl
  2. 为该 namespace 启用 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.6   47h
    2. 使用 revision 名称为 namespace 添加标签,以启用 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
    ...