How to Use Gateway API to Route Traffic in Kubernetes Clusters

Validated on 9 Feb 2026 • Last edited on 10 Feb 2026

DigitalOcean Kubernetes (DOKS) is a Kubernetes service with a fully managed control plane, high availability, and autoscaling. DOKS integrates with standard Kubernetes toolchains and DigitalOcean’s load balancers, volumes, CPU and GPU Droplets, API, and CLI.

Gateway API is a Kubernetes-native way to manage ingress traffic using standardized routing resources. It serves as an alternative to traditional ingress controllers like nginx and supports advanced routing features like header-based matching and traffic weighting.

DigitalOcean Kubernetes (DOKS) provides a managed Gateway API implementation using Cilium. The Gateway API is enabled by default on clusters with VPC-native networking running Kubernetes version 1.33 or later.

When you create a Gateway, DOKS automatically provisions a DigitalOcean Network Load Balancer to handle incoming traffic. Alternatively, you can provision an HTTP or internal load balancer.

Note
DOKS also supports third-party Gateway API implementations. To use a different controller, create a custom GatewayClass with your controller’s name and reference it in your Gateway manifest. See the Gateway API implementations list for available options.

Preserve Third-Party Gateway CRDs

DOKS installs and manages Gateway Custom Resource Definitions (CRDs) for Gateway, GatewayClass, HTTPRoute, TLSRoute, GRPCRoute, and ReferenceGrant by default. However, if you have Gateway CRDs from a third-party controller, then DOKS preserves those CRDs if one of the following conditions are met:

  • Manual opt-out: Gateway CRDs include the doks.digitalocean.com/install-policy: "external" annotation. To add the annotation, run the following command for each CRD, replacing <your-crd-name> with gateways, gatewayclasses, httproutes, tlsroutes, grpcroutes, and referencegrants:

    kubectl annotate crd <your-crd-name>.gateway.networking.k8s.io doks.digitalocean.com/install-policy="external"
  • Automatic detection: Gateway CRDs include a gateway.networking.k8s.io/bundle-version annotation with a version newer than the version bundled with DOKS.

Prerequisites

To use Gateway API on DOKS, you need:

  • A DOKS cluster with VPC-native networking running Kubernetes 1.33 or later.

    To confirm Gateway API is enabled on the cluster, run the following command:

    kubectl get gatewayclass cilium

    The output looks similar to the following:

    NAME     CONTROLLER                     ACCEPTED   AGE
    cilium   io.cilium/gateway-controller   True       7d

    If the cilium GatewayClass exists and shows ACCEPTED: True, Gateway API is enabled on your cluster.

  • kubectl connected to your cluster. See Connect to a DOKS Cluster.

  • A backend service running in your cluster that you want to route traffic to.

Create a Gateway

A Gateway resource defines an entry point for traffic into your cluster. When you create a Gateway, DOKS automatically provisions a DigitalOcean Load Balancer.

The following example creates a Gateway that listens for HTTP traffic on port 80. The gatewayClassName field must be set to cilium, the DOKS-provided GatewayClass:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: example-gateway
  namespace: default
spec:
  gatewayClassName: cilium
  listeners:
    - name: http
      protocol: HTTP
      port: 80

For HTTPS traffic, see Configure TLS Termination. You can also customize the load balancer type and settings using annotations.

Apply the manifest:

kubectl apply -f gateway.yaml

It typically takes 1-2 minutes for DOKS to provision the load balancer and assign an external IP address. To check the Gateway status, run the following command:

kubectl get gateway example-gateway

The output looks similar to the following:

NAME              CLASS    ADDRESS          PROGRAMMED   AGE
example-gateway   cilium   203.0.113.10     True         2m

The ADDRESS column shows the external IP address of the provisioned load balancer. The PROGRAMMED: True status indicates that the Gateway is ready to accept traffic.

You can also verify that the load balancer is created by checking for the associated Kubernetes service:

kubectl get svc -l io.cilium.gateway/owning-gateway=example-gateway

Next, define the HTTP traffic routing rule as described in the following section.

Define HTTP Traffic Routing

An HTTPRoute resource defines how HTTP traffic reaching the Gateway routes to your backend services. HTTPRoutes reference a parent Gateway and specify rules for matching and routing requests, and advanced routing rules such as path-based or header-based routing.

The following example creates an HTTPRoute that routes all traffic from the Gateway to a backend service named my-service on port 80:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: example-route
  namespace: default
spec:
  parentRefs:
    - name: example-gateway
  rules:
    - backendRefs:
        - name: my-service
          port: 80

Apply the manifest:

kubectl apply -f httproute.yaml

Route Traffic Based on Path or Headers

You can configure more advanced routing rules to direct traffic based on request properties. The following examples show path-based and header-based routing:

The following example routes requests to /api to one service and requests to /web to another:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: path-based-route
  namespace: default
spec:
  parentRefs:
    - name: example-gateway
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080
    - matches:
        - path:
            type: PathPrefix
            value: /web
      backendRefs:
        - name: web-service
          port: 80

The following example routes requests with a specific header to a different service:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: header-based-route
  namespace: default
spec:
  parentRefs:
    - name: example-gateway
  rules:
    - matches:
        - headers:
            - type: Exact
              name: X-Version
              value: v2
      backendRefs:
        - name: api-v2-service
          port: 8080

For more advanced routing patterns like traffic splitting and request redirects, see the Gateway API HTTPRoute documentation.

Next, configure the TLS termination, as described in the following section.

Configure TLS Termination

You can terminate TLS at either the DigitalOcean Load Balancer or at the Gateway (Cilium) level. Choose the approach that best fits your needs:

  • Load Balancer termination: Uses DigitalOcean-managed certificates and offloads TLS processing from your cluster.
  • Gateway termination: Keeps TLS certificates within your cluster as Kubernetes Secrets.

If you need to terminate TLS at your backend pods, instead of the Gateway, you can use tls.mode: Passthrough in the Gateway manifest. See the Gateway API TLS documentation for details.

To terminate TLS at the load balancer, pass certificate annotations through the .spec.infrastructure.annotations field on the Gateway:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: https-gateway
  namespace: default
spec:
  gatewayClassName: cilium
  infrastructure:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-certificate-id: "your-certificate-id"
      service.beta.kubernetes.io/do-loadbalancer-protocol: "https"
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: example-cert

To use a Let’s Encrypt certificate by name instead of ID, use the do-loadbalancer-certificate-name annotation:

infrastructure:
  annotations:
    service.beta.kubernetes.io/do-loadbalancer-certificate-name: "your-certificate-name"
    service.beta.kubernetes.io/do-loadbalancer-protocol: "https"

For more information about SSL certificates on load balancers, see SSL Certificates.

To terminate TLS at the Gateway, configure the load balancer for TLS passthrough and specify the certificate in the Gateway’s TLS configuration:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: gateway-tls
  namespace: default
spec:
  gatewayClassName: cilium
  infrastructure:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-tls-passthrough: "true"
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: my-tls-secret
            kind: Secret

The TLS certificate must be stored in a Kubernetes Secret in the same namespace as the Gateway. To do this, add the following to your Secret config file:

apiVersion: v1
kind: Secret
metadata:
  name: my-tls-secret
  namespace: default
type: kubernetes.io/tls
data:
  tls.crt: <base64-encoded-certificate>
  tls.key: <base64-encoded-private-key>

Configure Load Balancer Settings

You can configure additional load balancer settings by adding annotations to the Gateway’s .spec.infrastructure.annotations field. These annotations are the same as the ones you can configure for Load Balancer service for your cluster.

The following example configures a load balancer with a custom name and health check settings:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: custom-lb-gateway
  namespace: default
spec:
  gatewayClassName: cilium
  infrastructure:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-name: "my-gateway-lb"
      service.beta.kubernetes.io/do-loadbalancer-healthcheck-path: "/health"
      service.beta.kubernetes.io/do-loadbalancer-healthcheck-protocol: "http"
  listeners:
    - name: http
      protocol: HTTP
      port: 80
Note
The Gateway API specification limits the .spec.infrastructure.annotations field to 8 annotations. If you need more annotations, use a Load Balancer service directly with an ingress controller instead of the Gateway API to manage ingress traffic.

Use HTTP or Internal Load Balancers

By default, Gateway API provisions network load balancers, which route TCP and UDP traffic at the network layer. You can provision HTTP load balancers or internal load balancers instead by setting the appropriate annotations in the Gateway manifest.

HTTP load balancers operate at the application layer and can perform HTTP-specific functions. To use an HTTP load balancer:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: http-lb-gateway
  namespace: default
spec:
  gatewayClassName: cilium
  infrastructure:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-type: "REGIONAL"
  listeners:
    - name: http
      protocol: HTTP
      port: 80

Internal load balancers are only accessible from within your VPC network. To use an internal load balancer:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: internal-gateway
  namespace: default
spec:
  gatewayClassName: cilium
  infrastructure:
    annotations:
      service.beta.kubernetes.io/do-loadbalancer-network: "INTERNAL"
  listeners:
    - name: http
      protocol: HTTP
      port: 80

For more information about load balancer types, see Load Balancer Type.

View Gateway Status

To view the status of your Gateways:

kubectl get gateways

The output looks similar to the following:

NAME              CLASS    ADDRESS        PROGRAMMED   AGE
example-gateway   cilium   203.0.113.10   True         5m

The True status of the PROGRAMMED: column indicates the Gateway is ready to route traffic. The ADDRESS column shows the load balancer’s external IP address. You can also use kubectl describe gateway <name> to view detailed information, or kubectl get httproutes to list routes.

Additional Resources

For more information about Gateway API, see:

Gateway API Documentation

Official Kubernetes Gateway API specification and guides.

gateway-api.sigs.k8s.io
Cilium Gateway API Documentation

Cilium’s implementation of the Gateway API.

docs.cilium.io
HTTPS Traffic Routing in Kubernetes using Gateway API and Cilium

Tutorial on setting up HTTPS routing with Gateway API.

digitalocean.com/community
Kubernetes Gateway API Tutorial

Tutorial on replacing Ingress with Cilium Gateway for HTTP traffic.

digitalocean.com/community

We can't find any results for your search.

Try using different keywords or simplifying your search terms.