Expose services using Gateway API

更新时间:
复制 MD 格式

Gateway API is the next-generation service networking API from the Kubernetes community. Cloud-native API Gateway supports the Kubernetes Gateway API standard, which allows you to use declarative Gateway and HTTPRoute resources to configure gateway routes and expose services in your cluster to external users.

Background

Gateway API is the next-generation service networking API from the Kubernetes community. It provides more expressive, extensible, and role-oriented routing and load balancing interfaces than the traditional Ingress API. Gateway API introduces a clearer resource model hierarchy, including GatewayClass, Gateway, and HTTPRoute, and supports richer traffic management capabilities.

Prerequisites

  • You have a Cloud-native API Gateway instance with engine version 2.1.16 or later. If your instance is running an earlier version, upgrade it first.

  • You have a Kubernetes cluster (ACK cluster) running version 1.24 or later.

  • You have installed the Gateway API CRDs, version v1.3.0 or earlier. The current gateway supports the Gateway API protocol up to v1.3.0, so we recommend installing v1.3.0. If you use an Alibaba Cloud ACK cluster, we recommend that you install the Gateway API CRDs using component management. On the ACK console, go to Applications > Helm, select gateway-api, and click Update to change the version.

Configure Gateway API listening

Enable Gateway API listening

  1. Log on to the Cloud-native API Gateway console, select the target gateway instance, go to the API page, and click Create API.

  2. Under HTTP API, click Import Gateway API.

  3. In the creation panel, enter an API name and description, and select the source ACK cluster. In the Custom Configuration area, configure the namespace and GatewayClass to monitor. By default, the gateway listens for Gateway API resources in all namespaces in the cluster. After you complete the configuration, click OK.

  4. Select the newly created API. If Gateway API resources already exist in the ACK cluster and are within the configured listening scope, the corresponding route entries appear in the route list, indicating that the gateway is successfully monitoring Gateway API resources.

Note

For compatibility with open-source Higress, Cloud-native API Gateway listens by default for resources whose GatewayClass is higress, regardless of the filter configurations.

Modify Gateway API listening

  1. Log on to the Cloud-native API Gateway console, select the target gateway instance, go to the API page, and then click the Gateway API that you want to modify.

  2. In the upper-right corner, click Edit. Adjust the monitored GatewayClass and namespace, and then click Confirm. The configuration takes effect immediately. If you leave a configuration field empty, all resources of that type are monitored.

Example

After meeting the prerequisites and configuring listening for Gateway API, you can follow this example to route services using Gateway API resources.

Deploy a sample application

  1. Create a file named httpbin.yaml with the following content:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin
      template:
        metadata:
          labels:
            app: httpbin
            version: v1
        spec:
          containers:
            - image: registry.cn-hangzhou.aliyuncs.com/mse-ingress/go-httpbin
              args:
                - "--port=8080"
                - "--version=v1"
              imagePullPolicy: Always
              name: httpbin
              ports:
                - containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin
      namespace: default
    spec:
      type: ClusterIP
      ports:
        - port: 80
          targetPort: 8080
          protocol: TCP
      selector:
        app: httpbin
  2. Deploy the application:

    kubectl apply -f httpbin.yaml
  3. Verify that the application is running:

    kubectl get pods -l app=httpbin

    Expected output:

    NAME                       READY   STATUS    RESTARTS   AGE
    httpbin-5d4f8b6c7f-xxxxx   1/1     Running   0          30s

Deploy a gateway and routes

Once listening is enabled, Cloud-native API Gateway creates a GatewayClass named higress by default. You can also create your own GatewayClass resource as needed.

  1. (Optional) To use a custom GatewayClass, create a file named gatewayclass.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: GatewayClass
    metadata:
      name: apig  # You can customize the name.
    spec:
      controllerName: higress.io/gateway-controller
    kubectl apply -f gatewayclass.yaml
  2. Create a file named gateway.yaml with the following content:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: apig-gateway
      namespace: default
    spec:
      gatewayClassName: apig
      listeners:
        - name: http
          protocol: HTTP
          port: 80
          hostname: "*.example.com"
          allowedRoutes:
            namespaces:
              from: Same
    ---
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-route
      namespace: default
    spec:
      parentRefs:
        - name: apig-gateway
      hostnames:
        - "demo.example.com"
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          backendRefs:
            - kind: Service
              name: httpbin
              port: 80
  3. Deploy the Gateway and routing rules:

    kubectl apply -f gateway.yaml
  4. Verify that the Gateway is ready. Wait about 2 minutes, and then run the following command:

    kubectl get gateway apig-gateway

    Expected output:

    NAME           CLASS   ADDRESS       PROGRAMMED   AGE
    apig-gateway   apig    nlb-xxxx      True         2m

    The Gateway is ready when the PROGRAMMED status is True.

  5. Verify that the route is monitored correctly. Log on to the Cloud-native API Gateway console, go to the target gateway instance, click API, find the API of type Gateway API, and then click it to view the route list. If the Gateway API route created in the cluster appears in the list, the route is monitored correctly.

Test application access

  1. Log on to the Cloud-native API Gateway console, select the target gateway instance, and on the Overview > Basic Information page, find the gateway endpoint address.

  2. Access the application. Replace <gateway-endpoint-address> with the address that you obtained in the previous step.

    curl -H "Host: demo.example.com" http://<gateway-endpoint-address>/version

    Expected output:

    version: v1
    hostname: httpbin-5d4f8b6c7f-xxxxx

Use cases

The following examples are based on the official Gateway API documentation. For more scenarios, see the Gateway API official user guide.

Use case 1: Modify request headers with a filter

HTTPRoute filters allow you to apply additional processing during the request or response phase. The following example shows how to use a filter to add a custom request header to requests that are sent to the backend.

  1. Create a file named httproute-filter.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: demo-filter
    spec:
      parentRefs:
        - name: apig-gateway
      hostnames:
        - "filter.example.com"
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          filters:
            - type: RequestHeaderModifier
              requestHeaderModifier:
                add:
                  - name: my-header
                    value: foo
          backendRefs:
            - kind: Service
              name: httpbin
              port: 80

    This configuration creates an HTTPRoute resource named demo-filter. After deployment, the request header my-header: foo is automatically added to requests that access the filter.example.com domain.

  2. Deploy the routing rule:

    kubectl apply -f httproute-filter.yaml
  3. Access the application:

    curl -H "Host: filter.example.com" http://<gateway-endpoint-address>/header

    The output includes the automatically added request header:

    headers: {
        ...
        "My-Header": [
          "foo"
        ],
        ...
    }

Use case 2: Weight-based traffic splitting

By setting weights for multiple backend services, you can distribute requests proportionally. This is a common practice for canary releases.

  1. Create a file named nginx.yaml to deploy two NGINX applications. The old-nginx service returns the string old, and the new-nginx service returns the string new.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: old-nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: old-nginx
      template:
        metadata:
          labels:
            run: old-nginx
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/old-nginx
            imagePullPolicy: Always
            name: old-nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: old-nginx
    spec:
      type: ClusterIP
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: old-nginx
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: new-nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          run: new-nginx
      template:
        metadata:
          labels:
            run: new-nginx
        spec:
          containers:
          - image: registry.cn-hangzhou.aliyuncs.com/acs-sample/new-nginx
            imagePullPolicy: Always
            name: new-nginx
            ports:
            - containerPort: 80
              protocol: TCP
          restartPolicy: Always
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: new-nginx
    spec:
      type: ClusterIP
      ports:
      - port: 80
        protocol: TCP
        targetPort: 80
      selector:
        run: new-nginx
  2. Create a file named httproute-weight.yaml:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: demo-weight
    spec:
      parentRefs:
        - name: apig-gateway
      hostnames:
        - "weight.example.com"
      rules:
        - matches:
            - path:
                type: PathPrefix
                value: /
          backendRefs:
            - kind: Service
              name: old-nginx
              port: 80
              weight: 90
            - kind: Service
              name: new-nginx
              port: 80
              weight: 10
    Note

    The weight field is a relative value and does not need to sum to 100. In this configuration, the 90:10 ratio means that approximately 90% of the traffic is routed to old-nginx and 10% is routed to new-nginx.

  3. Deploy the applications and routing rules:

    kubectl apply -f nginx.yaml
    kubectl apply -f httproute-weight.yaml
  4. Access the application multiple times to verify the traffic distribution:

    for i in {1..10}; do curl -s -H "Host: weight.example.com" http://<gateway-endpoint-address>/; echo; done

    In the expected output, most responses return old and a few return new, at a ratio of approximately 9:1.

Use case 3: Header-based canary routing

By using header-matching rules, you can route traffic with a specific request header to a canary service, while routing all other traffic to a stable version. This method is often used to verify a canary version without affecting production users.

  1. Based on the previous example, deploy a canary version of the httpbin service. Create a file named httpbin-canary.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: httpbin-canary
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: httpbin-canary
      template:
        metadata:
          labels:
            app: httpbin-canary
            version: v2
        spec:
          containers:
            - image: registry.cn-hangzhou.aliyuncs.com/mse-ingress/go-httpbin
              args:
                - "--port=8080"
                - "--version=v2"
              imagePullPolicy: Always
              name: httpbin
              ports:
                - containerPort: 8080
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: httpbin-canary
      namespace: default
    spec:
      type: ClusterIP
      ports:
        - port: 80
          targetPort: 8080
          protocol: TCP
      selector:
        app: httpbin-canary
    kubectl apply -f httpbin-canary.yaml
  2. Create a file named httproute-canary.yaml to configure header-based canary routing rules:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: demo-canary
    spec:
      parentRefs:
        - name: apig-gateway
      hostnames:
        - "canary.example.com"
      rules:
        - matches:
            - headers:
                - type: Exact
                  name: env
                  value: canary
          backendRefs:
            - kind: Service
              name: httpbin-canary
              port: 80
        - backendRefs:
            - kind: Service
              name: httpbin
              port: 80

    This configuration defines two routing rules: traffic with the request header env: canary is routed to the canary service httpbin-canary, while all other traffic is routed to the stable version httpbin.

  3. Deploy the routing rule:

    kubectl apply -f httproute-canary.yaml
  4. Verify the canary route by accessing the stable version without the header:

    curl -H "Host: canary.example.com" http://<gateway-endpoint-address>/version

    Expected output:

    version: v1
    hostname: httpbin-f4c58d59c-xxxxx
  5. Access the canary version with the env: canary request header:

    curl -H "Host: canary.example.com" -H "env: canary" http://<gateway-endpoint-address>/version

    Expected output:

    version: v2
    hostname: httpbin-canary-585859f9b6-xxxxx