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

本节介绍如何使用 Istio API,通过已安装网关注入的网关来路由出站 HTTP 流量。

目录

前提条件

操作步骤

  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. 创建名为 http-se.yaml 的 YAML 文件,用于将流量从网格导向外部服务。以下示例定义了针对特定 URL 的 ServiceEntry

    示例配置

    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: egress-se
      namespace: curl
    spec:
      hosts:
        - docs.alauda.io
      ports:
        - number: 80
          name: http-port
          protocol: HTTP
      location: MESH_EXTERNAL
      resolution: DNS
  6. 通过执行以下命令应用该 YAML 文件:

    kubectl apply -f http-se.yaml
  7. 确认 ServiceEntry 配置已成功应用。通过运行以下命令向上一步中指定的主机发送 HTTP 请求:

    kubectl exec "$CURL_POD" -n curl -c curl -- curl -sSL -o /dev/null -D - http://docs.alauda.io

    该命令应返回类似 302(重定向)或 200(成功)的 HTTP 状态码,确认连接正常。

  8. 创建名为 http-egress-gw.yaml 的 YAML 文件,建立一个出口 Gateway 并将流量从网格路由到为外部服务定义的主机。

    示例配置

    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
      name: egress-gw
      namespace: <gateway_namespace> # 出口网关部署的命名空间
    spec:
      selector:
        istio: <gateway_name> # 选择处理此流量的出口网关实例
      servers:
        - port:
            number: 80
            name: http
            protocol: HTTP
          hosts:
            - docs.alauda.io # 外部服务主机,不是完整 URL。
    ---
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: egress-dr
      namespace: <gateway_namespace> # 出口网关部署的命名空间
    spec:
      host: <gateway_name>.<gateway_namespace>.svc.cluster.local
      subsets:
        - name: alauda-docs
  9. 通过执行以下命令应用该 YAML 文件:

    kubectl apply -f http-egress-gw.yaml
  10. 创建名为 http-egress-vs.yaml 的 YAML 文件,配置一个 VirtualService,用于管理应用 sidecar 通过出口网关到外部主机的流量。

    示例配置

    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
      name: egress-vs
      namespace: curl # curl pod 所在的命名空间
    spec:
      hosts:
        - docs.alauda.io # 外部服务主机,不是完整 URL。
      gateways:
        - mesh
        - <gateway_namespace>/egress-gw # 上一步中定义的出口网关名称。
      http:
        - match:
            - gateways:
                - mesh
              port: 80
          route:
            - destination:
                host: <gateway_name>.<gateway_namespace>.svc.cluster.local
                subset: alauda-docs
                port:
                  number: 80
              weight: 100
        - match:
            - gateways:
                - <gateway_namespace>/egress-gw # 上一步中定义的出口网关名称。
              port: 80
          route:
            - destination:
                host: docs.alauda.io
                port:
                  number: 80
              weight: 100
  11. 通过运行以下命令应用该 YAML 文件:

    kubectl apply -f http-egress-vs.yaml
  12. 重新向该 URL 发送 HTTP 请求:

    kubectl exec "$CURL_POD" -n curl -c curl -- curl -sSL -o /dev/null -D - http://docs.alauda.io

    终端输出应类似如下所示:

    示例输出

    ...
    HTTP/1.1 302 Moved Permanently
    ...
    location: <example_url>
    ...
    
    HTTP/2 200
    Content-Type: text/html; charset=utf-8
  13. 通过运行以下命令确认请求是否通过网关路由:

    启用访问日志

    访问日志必须处于激活状态,此验证步骤才能正常工作。您可以通过创建以下 Telemetry 资源来启用访问日志。

    kubectl apply -f - <<EOF
    apiVersion: telemetry.istio.io/v1
    kind: Telemetry
    metadata:
      name: gateway-access-log
      namespace: <gateway_namespace>
    spec:
      selector:
        matchLabels:
          istio: <gateway_name>
      accessLogging:
        - providers:
            - name: envoy
    EOF
    kubectl logs deployment/<gateway_name> -n <gateway_namespace> | tail -1

    终端应显示类似如下信息:

    示例输出

    [2025-09-21T07:45:45.331Z] "GET / HTTP/2" 302 - via_upstream - "-" 0 137 107 105 "10.3.0.56" "curl/8.15.0" "1503bbf4-1571-4d16-9d2b-c9817355284e" "docs.alauda.io" "119.28.207.230:80" outbound|80||docs.alauda.io 10.3.0.41:55194 10.3.0.41:80 10.3.0.56:60876 - -