Migrate Ingress to Gateway API

This page shows you how to migrate your traffic management on Google Kubernetes Engine (GKE) from the Ingress API to Gateway API. Gateway API provides a fully-managed, Google Cloud solution for handling your application traffic.

To minimize downtime and mitigate risk, the most effective approach to migrate to Gateway API is to run both your existing Ingress API and the new Gateway API configurations simultaneously. This method allows for thorough testing of the new Gateway configuration in a live environment without impacting your current services. After you validate the new Gateway configuration, you can perform a quick DNS cutover to redirect traffic to Gateway API, and help ensure a smooth and low-risk transition.

At a high level, the migration strategy involves the following phases:

  1. Configure the new load balancer.
  2. Define rules for handling incoming traffic.
  3. Deploy the new configuration and test traffic flow to the new Gateway IP address.
  4. Switch over production traffic to Gateway API.
  5. Clean up remaining Ingress resources.

Configure the new load balancer

In this phase, you deploy a Kubernetes Gateway resource to load balance traffic to your GKE cluster. When you deploy a Gateway resource, GKE configures a Layer 7 Application Load Balancer to expose HTTP(S) traffic to applications that run in the cluster. You deploy one Gateway resource for every cluster or for every load balancer that you require.

In the following example, you configure a Global external Application Load Balancer. To create a Gateway, save the following manifest as gateway.yaml:

kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: external-http-gateway
spec:
  gatewayClassName: gke-l7-global-external-managed # GKE's managed external Application Load Balancer
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same # Only allow HTTPRoutes from the same namespace

The preceding manifest describes a Gateway that includes the following fields:

  • gatewayClassName: gke-l7-global-external-managed: specifies the GatewayClass for this Gateway. This Gateway class uses a global external Application Load Balancer.
  • protocol: HTTP and port: 80: specify that the Gateway exposes port 80 for HTTP traffic.

Define traffic rules for incoming traffic

Route resources define protocol-specific rules for mapping traffic from a Gateway to backend Services.

In this phase, you translate your Ingress manifest into an HTTPRoute resource. To convert the Ingress manifest, follow the steps in the ingress2gateway tool.

This example assumes that you have the following Ingress resource:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: cafe-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: cafe.example.com
    http:
      paths:
      - path: /tea
        pathType: Prefix
        backend:
          service:
            name: tea-svc
            port:
              number: 80
      - path: /coffee
        pathType: Prefix
        backend:
          service:
            name: coffee-svc
            port:
              number: 80

After you convert the manifest by using the ingress2gateway tool, the output is the translated HTTPRoute manifest.

Save the following sample manifest as httproute.yaml:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: cafe-route
spec:
  # This route attaches to our new Gateway
  parentRefs:
  - name: external-http-gateway
  # The hostname is the same as before
  hostnames:
  - "cafe.example.com"
  # The routing rules are now more explicit
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /tea
    backendRefs:
    - name: tea-svc
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /coffee
    backendRefs:
    - name: coffee-svc
      port: 80

Note that the rules field in the HTTPRoute manifest directly corresponds to the routing rules defined in the original Ingress manifest.

Deploy and test the new configuration

In this phase, you apply the Gateway and HTTPRoute manifests that you created in the preceding two phases and test that traffic flows to the new IP address of the Gateway.

  1. Apply the Gateway and HTTPRoute manifests:

    kubectl apply -f gateway.yaml
    kubectl apply -f httproute.yaml
    
  2. Get the IP address of the Gateway. It might take a few minutes to allocate the IP address:

    kubectl get gateway external-http-gateway -o=jsonpath="{.status.addresses[0].value}" --watch
    

    The output is the external IP address of the Gateway, for example, 203.0.113.90.

  3. Test the new Gateway IP address. Use the following curl command to send a request to the IP address and specify the cafe.example.com hostname. For example:

    curl --resolve cafe.example.com:80:203.0.113.90 http://cafe.example.com/tea
    curl --resolve cafe.example.com:80:203.0.113.90 http://cafe.example.com/coffee
    

    Replace 203.0.113.90 with the external IP address that you obtained from the preceding step. The output confirms that the new Gateway IP address correctly routes traffic for cafe.example.com without performing a DNS lookup.

Direct traffic to the new Gateway IP address

In this phase, you cut over live traffic from your previous Ingress to the new Gateway by updating your DNS records to point to the new Gateway IP address. The exact steps to update DNS records vary depending on your DNS provider.

For example, if you configured cafe.example.com in Ingress, you would locate the A record for cafe.example.com with your DNS provider and change the value of the old Ingress IP address to 34.56.78.90, which is the new Gateway IP address.

After you update the DNS record, traffic begins to shift from Ingress to Gateway, but the cutover does not occur immediately for all clients. DNS resolvers that have the previous record cached wait for the record's time to live (TTL) value to expire before they query for the record again and receive the updated IP address. Because of this, you should continue to run your existing Ingress and new Gateway in tandem until you verify that traffic to the Ingress has ceased, which indicates that DNS propagation is complete and clients are no longer being directed to the old IP address. You can verify this by monitoring traffic on your load balancer or Ingress controller. For more information, see Checking DNS propagation.

If you use Cloud DNS, you can use target weights to incrementally shift traffic from the old IP address to the new IP address. For more information, see Configure DNS routing policies and health checks.

Clean up remaining Ingress resources

After you confirm that your new Gateway runs successfully, clean up the old Ingress resources.

  1. Delete the Ingress resource:

    kubectl delete ingress cafe-ingress
    
  2. Uninstall the ingress-nginx controller. For example, if you used Helm to install the controller, run the following command:

    helm uninstall ingress-nginx -n ingress-nginx
    

Feature comparison between Ingress NGINX and GKE Gateway

Gateway API provides a more standardized way to configure ingress, and has feature parity for most common features like routing, headers, and traffic splitting.

The following table compares the annotations that are used for common features in the Ingress controller and Gateway API.

Feature Annotation in Ingress Annotation in GKE Gateway Parity
URL rewrites nginx.ingress.kubernetes.io/rewrite-target HTTPRoute with a urlRewrite filter. Partial parity. GKE Gateway supports only prefix replacements.
Header manipulation nginx.ingress.kubernetes.io/proxy-set-headers or add-headers HTTPRoute with a requestHeaderModifier modifier or responseHeaderModifier filter. Full parity.
Path-based routing spec.rules.http.paths in the Ingress object. rules.matches.path in the HTTPRoute object. Full parity.
Host-based routing spec.rules.host in the Ingress object. hostnames in the HTTPRoute object. Full parity.
Traffic splitting nginx.ingress.kubernetes.io/canary annotations. HTTPRoute with weighted backendRefs. Full parity. In addition, you can split traffic with fine-grained control.
Authentication nginx.ingress.kubernetes.io/auth-url for external authentication.
  • Identity-Aware Proxy (IAP): BackendPolicy CRD.
  • Other: Requires a more custom approach, possibly with service mesh or custom filters.
Partial parity. Identity-Aware Proxy is the recommended way to secure your Gateway and is configured on the backend.

What's next