Working with Envoy Gateway to implement Kubernetes Gateway API

Find out how to set up Envoy Gateway to support the Kubernetes Gateway API in clusters you create using Kubernetes Engine (OKE).

The Kubernetes Gateway API (Gateway API) is the next generation standard for managing ingress and network traffic in Kubernetes clusters, succeeding the Ingress API. For more information about the Gateway API, see Gateway API in the Kubernetes documentation, and the Gateway API documentation.

Envoy Gateway is an open-source implementation of the Gateway API that manages Envoy Proxy as the data plane. It provides a standard, compliant way to manage ingress traffic without relying on vendor-specific CRDs.

By deploying Envoy Gateway, you can use it as the underlying controller to manage Gateway, HTTPRoute, and other Gateway API resources.

The Envoy Gateway deployment includes several components that work together:

  • Gateway API CRDs extend the Kubernetes API with new resource types such as Gateway and HTTPRoute, allowing declarative management of ingress traffic.
  • Envoy Gateway controller acts as the control plane, watching for Gateway API resources and translating them into detailed configuration for the data plane.
  • Envoy Proxy pods form the data plane, handling network traffic in accordance with the policies and routes defined by Gateway resources.
  • OCI Network Load Balancer integration ensures that external traffic is properly routed to applications via Envoy Proxy nodes.

Prerequisites

Before setting up Envoy Gateway to support the Kubernetes Gateway API:

  • You must have kubectl access to the cluster created by Kubernetes Engine.
  • The machine from which you access the cluster must have Helm CLI (v3.0 or later) installed.
  • You must have cluster-admin privileges to install custom resource definitions (CRDs) and controllers.

Setting Up Envoy Gateway as a Gateway API Controller

High level steps to set up Envoy Gateway

At a high-level, the steps to set up Envoy Gateway to serve as the Gateway API controller are as follows:

Step 1: Install Gateway API CRDs

The Gateway API Custom Resource Definitions (CRDs) are not installed by default in clusters you create using Kubernetes Engine. Before using Envoy Gateway as a Gateway API controller, you must install the CRDs.

  1. Install the standard channel CRDs (v1.2.0) by entering:

    kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
    
  2. Verify that the CRD is installed by entering:

    kubectl get crd gateways.gateway.networking.k8s.io
    
  3. Confirm that the CRD is listed in the output.

Step 2: Install Envoy Gateway

Use Helm to install the Envoy Gateway controller.

  1. Install the chart into the envoy-gateway-system namespace by entering:

    helm install eg oci://docker.io/envoyproxy/gateway-helm --version v1.6.3 -n envoy-gateway-system --create-namespace
    
  2. Wait for the Envoy Gateway controller to be ready by entering:

    kubectl wait --namespace envoy-gateway-system \
      --for=condition=ready pod \
      --selector=control-plane=envoy-gateway \
      --timeout=90s
    

Step 3: Configure OCI Network Load Balancer integration

Create an EnvoyProxy custom resource to inject the necessary OCI annotations into the Service that Envoy Gateway creates.

  1. Create a file named oci-envoy-proxy.yaml with the following content:

    apiVersion: gateway.envoyproxy.io/v1alpha1
    kind: EnvoyProxy
    metadata:
      name: oci-flexible-proxy
      namespace: envoy-gateway-system
    spec:
      provider:
        type: Kubernetes
        kubernetes:
          envoyService:
            annotations:
              oci.oraclecloud.com/load-balancer-type: "nlb"
    
  2. Create the EnvoyProxy custom resource by entering:

    kubectl apply -f oci-envoy-proxy.yaml
    

Step 4: Create a GatewayClass

Create a GatewayClass that tells the controller to use the EnvoyProxy you created.

  1. Create a file named oci-gateway-class.yaml with the following content:

    apiVersion: gateway.networking.k8s.io/v1
    kind: GatewayClass
    metadata:
      name: oci-gateway-class
    spec:
      controllerName: gateway.envoyproxy.io/gatewayclass-controller
      parametersRef:
        group: gateway.envoyproxy.io
        kind: EnvoyProxy
        name: oci-flexible-proxy
        namespace: envoy-gateway-system
    
  2. Create the GatewayClass by entering:

    kubectl apply -f oci-gateway-class.yaml
    

Step 5: Create a Gateway

Create the Gateway resource, which triggers the creation of the OCI network load balancer.

  1. Create a file named my-gateway.yaml with the following content:

    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: my-envoy-gateway
      namespace: default
    spec:
      gatewayClassName: oci-gateway-class
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: Same
    
  2. Create the Gateway by entering:

    kubectl apply -f my-gateway.yaml
    
  3. Get the external IP address by entering:

    kubectl get gateway my-envoy-gateway -n default
    

    It might take a few minutes for OCI to provision the load balancer.

    Wait until the PROGRAMMED column contains True and an IP address appears in the ADDRESS column.

Step 6: Deploy a sample application

Test the gateway by deploying a simple echo service.

  1. Create a file named echo-app.yaml with the following content:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: echo-app
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: echo
      template:
        metadata:
          labels:
            app: echo
        spec:
          containers:
          - name: echo
            image: ealen/echo-server:latest
            ports:
            - containerPort: 80
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: echo-service
      namespace: default
    spec:
      selector:
        app: echo
      ports:
      - port: 80
        targetPort: 80
    
  2. Create the sample application by entering:

    kubectl apply -f echo-app.yaml
    

Step 7: Create an HTTPRoute

Create an HTTPRoute to direct traffic from the Gateway to the application.

  1. Create a file named echo-route.yaml with the following content:

    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: echo-route
      namespace: default
    spec:
      parentRefs:
      - name: my-envoy-gateway
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /
        backendRefs:
        - name: echo-service
          port: 80
    
  2. Create the HTTPRoute by entering:

    kubectl apply -f echo-route.yaml
    

Step 8: Verify connectivity

Verify connectivity by sending a request to the external IP address of the Gateway.

  1. Retrieve the public IP address of the gateway and save it as an environment variable by entering:

    export GATEWAY_IP=$(kubectl get gateway my-envoy-gateway -o jsonpath='{.status.addresses[0].value}')
  2. Use curl to send a request to the Gateway external IP address by entering:

    curl -i http://$GATEWAY_IP/
    
  3. Confirm that you receive a 200 OK response, along with a JSON body that shows details about the request (headers, host, and so on).

(Optional) Clean up

You can optionally remove the resources that you have created in this topic by entering:

kubectl delete -f echo-route.yaml
kubectl delete -f echo-app.yaml
kubectl delete -f my-gateway.yaml
kubectl delete -f oci-gateway-class.yaml
kubectl delete -f oci-envoy-proxy.yaml
helm uninstall eg -n envoy-gateway-system

If you no longer need the Gateway API on this cluster, you can remove the CRDs by entering:

kubectl delete -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml