通过 Kubernetes Gateway API 暴露服务

您可以使用 Kubernetes Gateway API 创建 GatewayHTTPRoute 资源来部署网关。这些资源配置网关,使网格内的服务可以被外部流量访问。然后,您可以将网关的 Service 类型更改为 LoadBalancer,以便将其暴露给集群外部的流量。

目录

前提条件

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

操作步骤

  1. 使用以下命令创建一个名为 httpbin 的新命名空间:

    kubectl create namespace httpbin
  2. 使用以下命令部署 httpbin 示例服务:

    kubectl apply -n httpbin -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/httpbin/httpbin.yaml
  3. 创建一个名为 httpbin-k8s-gw.yaml 的文件,定义一个 Kubernetes Gateway 资源。该资源将配置网关代理,暴露端口 80(HTTP)用于 httpbin.example.com 主机。

    自动部署

    默认情况下,每个 Gateway 会自动创建一个 ServiceDeployment。它们的名称格式为 <Gateway name>-<GatewayClass name>istio-waypoint GatewayClass 除外,该类不会添加后缀)。如果 Gateway 发生更改(例如添加新端口),这些配置会自动更新。

    示例网关资源文件

    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: http
          hostname: "httpbin.example.com"
          port: 80
          protocol: HTTP
          allowedRoutes:
            namespaces:
              from: All
    1. 指定网关的 Service 类型;默认为 LoadBalancer
    2. 指定网关的名称。
    3. 指定网关的命名空间。
    4. 指定客户端访问此端口时使用的虚拟主机名。
  4. 使用以下命令应用该 YAML 文件:

    kubectl apply -f httpbin-k8s-gw.yaml
  5. 创建一个名为 httpbin-hr.yaml 的 YAML 文件,定义一个 HTTPRoute 资源。该资源指定了从网关代理到 httpbin 服务的流量路由规则。

    示例 HTTPRoute 文件

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin
      namespace: httpbin
    spec:
      parentRefs:
      - name: httpbin-gateway
        namespace: httpbin
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /status
        - path:
            type: PathPrefix
            value: /headers
        backendRefs:
        - name: httpbin
          port: 8000
    1. 通过将网关名称添加到网关列表,将 HTTPRoute 资源关联到之前创建的 Kubernetes Gateway
    2. 通过定义包含 httpbin 服务名称和端口的 backendRefs 条目,将匹配的流量定向到 httpbin 服务。
  6. 执行以下命令应用该 YAML 文件:

    kubectl apply -f httpbin-hr.yaml
  7. 通过运行以下命令确认 Gateway API 服务已就绪并分配了地址:

    kubectl wait --for=condition=programmed gtw httpbin-gateway -n httpbin

验证

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

    kubectl create namespace curl
  2. 使用以下命令部署 curl 客户端:

    kubectl apply -n curl -f https://raw.githubusercontent.com/istio/istio/refs/heads/master/samples/curl/curl.yaml
  3. 使用以下命令将 curl pod 的名称赋值给变量 CURL_POD

    CURL_POD=$(kubectl get pods -n curl -l app=curl -o jsonpath='{.items[*].metadata.name}')
  4. curl 客户端发送请求到 httpbin 应用的 /headers 端点,通过入口网关 Service。将 Host 头设置为 httpbin.example.com,以匹配 Kubernetes GatewayHTTPROUTE 资源中指定的主机。运行以下 curl 命令:

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

    响应应显示 200 OK HTTP 状态,表示请求成功。

    示例输出

    HTTP/1.1 200 OK
    server: istio-envoy
    ...
  5. 发送一个请求到 httpbin HTTPROUTE 中没有匹配 URI 前缀的端点,运行以下命令:

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

    响应将是 404 Not Found 状态。这是预期行为,因为 /get 端点在 httpbin HTTPROUTE 资源中没有定义匹配的 URI 前缀。

    示例输出

    HTTP/1.1 404 Not Found
    server: istio-envoy
    ...
  6. 通过将网关代理的 Service 类型设置为默认的 LoadBalancer,将其暴露给外部流量。运行以下命令:

    kubectl -n httpbin annotate gtw httpbin-gateway networking.istio.io/service-type-
  7. 使用网关 Service 的外部主机名或 IP 地址验证 httpbin 服务是否可从集群外部访问。确保根据您的集群环境正确设置 INGRESS_HOST 变量。

    a. 通过运行以下命令设置 INGRESS_HOST 变量:

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

    b. 通过运行以下命令设置 INGRESS_PORT 变量:

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

    c. 使用网关主机,发送 curl 请求到 httpbin 服务,运行以下命令:

    curl -s -I -H Host:httpbin.example.com http://$INGRESS_HOST:$INGRESS_PORT/headers
  8. 验证响应显示 HTTP/1.1 200 OK 状态,确认请求成功。