在 ambient 模式下通过 Kubernetes Gateway API 暴露服务

在 Istio ambient 模式下,Kubernetes Gateway API 是配置入口流量路由的推荐方法。您可以创建 GatewayHTTPRoute 资源来部署 gateway,使外部流量能够访问 mesh 内部服务。

用于 Layer 7 路由的 waypoint proxy

要强制执行 Layer 7 (L7) 路由策略(包括基于路径的路由和标头匹配),请在包含目标服务的 namespace 中部署 waypoint proxy。waypoint proxy 负责处理 L7 流量,并应用通过 HTTPRouteGRPCRoute 资源定义的路由规则。

WARNING

在 ambient 模式下,VirtualService 资源的兼容性有限,不应与 Gateway API 配置结合使用。在 ambient 模式下,请使用 Kubernetes Gateway API 资源作为流量路由的标准方法。

前提条件

  • 已安装 Alauda Service Mesh v2 Operator。
  • 已使用 ambient profile 配置 IstioIstioCNI 资源。
  • 已创建 Ztunnel 资源。
  • 已安装 Gateway API CRD。
  • 确认 Linux kernel 兼容性
  • 您的 Kubernetes 集群支持外部负载均衡器(即类型为 LoadBalancer 的 Service)。

操作步骤

  1. 创建名为 httpbin 的 namespace:

    kubectl create namespace httpbin
    kubectl label namespace httpbin pod-security.kubernetes.io/enforce=restricted --overwrite
  2. httpbin namespace 添加 istio-discovery=enabled 标签:

    kubectl label namespace httpbin istio-discovery=enabled
  3. 通过应用 dataplane mode 标签为该 namespace 启用 ambient 模式:

    kubectl label namespace httpbin istio.io/dataplane-mode=ambient
  4. 部署 httpbin 示例服务:

    kubectl apply -n httpbin -f https://raw.githubusercontent.com/alauda-mesh/istio/refs/heads/istio-1.30/samples/httpbin/httpbin.yaml
  5. istioistio-waypoint gateway class overlay 添加到 Istio 资源,以便将 gateway 和 waypoint pod 准入 Restricted httpbin namespace:

    kubectl patch istio default --type=merge -p '{"spec":{"values":{"gatewayClasses":{"istio":{"deployment":{"spec":{"template":{"spec":{"securityContext":{"seccompProfile":{"type":"RuntimeDefault"}}}}}}},"istio-waypoint":{"deployment":{"spec":{"template":{"spec":{"securityContext":{"seccompProfile":{"type":"RuntimeDefault"}}}}}}}}}}}'

    有关详细信息,请参阅 Pod Security Admission

  6. 创建名为 httpbin-waypoint.yaml 的文件以定义 waypoint proxy。此 Gateway 资源使用 istio-waypoint gateway class 处理 namespace 中服务的 L7 流量。

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-waypoint
      namespace: httpbin
      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 gateway class,该 class 部署 waypoint proxy,而不是标准 ingress gateway。
  7. 应用 waypoint proxy 配置:

    kubectl apply -f httpbin-waypoint.yaml
  8. httpbin service 添加标签,使入口流量通过 waypoint proxy:

    kubectl label service httpbin -n httpbin istio.io/ingress-use-waypoint=true
    NOTE

    istio.io/ingress-use-waypoint=true 标签确保从 ingress gateway 到达的流量经过 waypoint proxy,从而在流量到达 httpbin service 之前,强制执行在 waypoint 上配置的 L7 策略。

  9. 通过为 namespace 添加标签,将 namespace 中的所有服务与 waypoint proxy 关联:

    kubectl label ns httpbin istio.io/use-waypoint=httpbin-waypoint
  10. 创建名为 httpbin-gw.yaml 的文件,该文件定义 Kubernetes Gateway 资源。此配置使 gateway proxy 接受端口 80 上、面向主机 httpbin.example.com 的 HTTP 流量。

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      annotations:
        networking.istio.io/service-type: ClusterIP
      name: httpbin-gateway
      namespace: httpbin
    spec:
      gatewayClassName: istio
      listeners:
        - name: default
          hostname: "httpbin.example.com"
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: All
    1. 指定 gateway 的 Service 类型;默认为 LoadBalancer
    2. 指定客户端通过此端口访问 mesh 服务时使用的虚拟主机名。
  11. 应用 gateway 配置:

    kubectl apply -f httpbin-gw.yaml
  12. 创建名为 httpbin-ingress-hr.yaml 的文件,该文件为 ingress gateway 定义 HTTPRoute 资源。此资源指定如何将流量从 gateway proxy 路由到 httpbin service。

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-ingress
      namespace: httpbin
    spec:
      parentRefs:
        - name: httpbin-gateway
          namespace: httpbin
      hostnames:
        - "httpbin.example.com"
      rules:
        - backendRefs:
            - name: httpbin
              port: 8000
    1. 将此 HTTPRoute 绑定到上一步创建的 Kubernetes Gateway
    2. 将匹配的流量路由到端口 8000 上的 httpbin service。
  13. 应用 ingress HTTPRoute:

    kubectl apply -f httpbin-ingress-hr.yaml
  14. 创建名为 httpbin-waypoint-hr.yaml 的文件,该文件为 waypoint proxy 定义 HTTPRoute 资源。此资源配置由 waypoint 强制执行的基于路径的路由规则。

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-waypoint-route
      namespace: httpbin
    spec:
      parentRefs:
        - group: ""
          kind: Service
          name: httpbin
          namespace: httpbin
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /status
            - path:
                type: PathPrefix
                value: /headers
          backendRefs:
            - name: httpbin
              port: 8000
    1. 将此 HTTPRoute 绑定到 httpbin service。结合 istio.io/ingress-use-waypoint=true 标签,这会配置 waypoint proxy 为发往该服务的流量强制执行的 L7 路由规则。
    2. 将匹配的流量转发到端口 8000 上的 httpbin service。
  15. 应用 waypoint HTTPRoute:

    kubectl apply -f httpbin-waypoint-hr.yaml
    NOTE

    在此配置中,由于 service 上的 istio.io/ingress-use-waypoint=true 标签,来自 ingress gateway 的流量会经过 waypoint proxy。随后,waypoint HTTPRoute 会在流量到达 httpbin service 之前应用基于路径的路由策略。

  16. 等待 waypoint proxy 就绪:

    kubectl wait --for=condition=programmed gtw httpbin-waypoint -n httpbin
  17. 可选:将 gateway 部署到 Infra Nodes

    单击以展开
    前提条件

    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: httpbin
    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. 指定与 gateway 相同的 configmap namespace。
    3. 设置节点选择器和容忍度,以便将 gateway pod 调度到 Infra Nodes。

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

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: httpbin-gateway
      namespace: httpbin
    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 client 创建 namespace:

    kubectl create namespace curl
    kubectl label namespace curl pod-security.kubernetes.io/enforce=restricted --overwrite
  2. 部署 curl client:

    kubectl apply -n curl -f https://raw.githubusercontent.com/alauda-mesh/istio/refs/heads/istio-1.30/samples/curl/curl.yaml
  3. curl namespace 添加 istio-discovery=enabled 标签:

    kubectl label namespace curl istio-discovery=enabled
  4. curl namespace 启用 ambient 模式:

    kubectl label namespace curl istio.io/dataplane-mode=ambient
  5. curl pod 的名称存储在变量中:

    export CURL_POD=$(kubectl get pods -n curl -l app=curl -o jsonpath='{.items[*].metadata.name}')
    echo "CURL_POD=$CURL_POD"
  6. curl client 向 httpbin application 的 /headers endpoint 发送请求,并通过 ingress gateway Service。将 Host header 设置为 httpbin.example.com,以匹配 Kubernetes GatewayHTTPRoute 资源中指定的主机:

    kubectl exec $CURL_POD -n curl -- \
      curl -sS -I \
        -H Host:httpbin.example.com \
        httpbin-gateway-istio.httpbin.svc.cluster.local/headers

    响应应返回 HTTP/1.1 200 OK 状态,表示请求已成功处理。

    示例输出

    HTTP/1.1 200 OK
    ...
    server: istio-envoy
    ...
  7. 向 waypoint HTTPRoute 中 URI 前缀不匹配的 endpoint 发送请求:

    kubectl exec $CURL_POD -n curl -- \
      curl -sS -I \
        -H Host:httpbin.example.com \
        httpbin-gateway-istio.httpbin.svc.cluster.local/get

    响应返回 HTTP/1.1 404 Not Found,这是预期结果,因为 /get 路径没有在 waypoint HTTPRoute 中定义对应的前缀匹配。

    示例输出

    HTTP/1.1 404 Not Found
    ...
    server: istio-envoy
    ...
  8. Service 类型更改为默认的 LoadBalancer,使 gateway proxy 暴露给集群外部的流量:

    kubectl -n httpbin annotate gtw httpbin-gateway networking.istio.io/service-type-
  9. 使用 gateway Service 的外部主机名或 IP 地址,确认可从集群外部访问 httpbin service。根据您的集群环境设置 INGRESS_HOST 变量。

    a. 设置 INGRESS_HOST 变量:

    export INGRESS_HOST=$(kubectl get gtw httpbin-gateway -n httpbin -o jsonpath='{.status.addresses[0].value}')
    echo "INGRESS_HOST=$INGRESS_HOST"

    b. 设置 INGRESS_PORT 变量:

    export INGRESS_PORT=$(kubectl get gtw httpbin-gateway -n httpbin -o jsonpath='{.spec.listeners[?(@.name=="default")].port}')
    echo "INGRESS_PORT=$INGRESS_PORT"

    c. 使用 gateway host 向 httpbin service 发送 curl 请求:

    INFO

    如果 $INGRESS_HOST 是 IPv6 地址,构造 URL 时请将其括在方括号中。例如:

    curl -sS -g -I -H Host:httpbin.example.com http://[$INGRESS_HOST]:$INGRESS_PORT/headers
    curl -sS -g -I -H Host:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
  10. 确认响应包含 HTTP/1.1 200 OK 状态,表示请求成功。

    示例输出

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

清理

移除在此操作步骤中创建的资源:

# Remove the namespaces from the ambient data plane
kubectl label namespace curl istio.io/dataplane-mode-
kubectl label namespace httpbin istio.io/dataplane-mode-
# Remove the namespaces
kubectl delete namespace curl
kubectl delete namespace httpbin