Migrate an Ingress to a Gateway

How to migration from an Ingress to a Gateway

The GatewayAPI resource is an alternative and replacement to Ingress resource. The Gateway resource provides functionality not available in the Ingress resource and offers the opportunity to simplify Kubernetes application access. The GatewayAPI provides a number of key benefits over the legacy Ingress/LoadBalancer model.

  1. Expands the Kubernetes API functionality to enable API Gateways. The Ingress API has very basic request routing functionality but lacks the key capabilities necessary in API gateway implementations such are header matching, URL rewrite and many others. Due to this limitations, most Ingress implementations use the proprietary configuration model created by the Ingress developer. The GatewayAPI offer the opportunity to move to a standard configuration model and syntax
  2. Includes functionality to Automate Networking. The ingress API was designed to be paired with a the loadBalancer functionality in the Service API. This separation makes an Ingress incomplete without a LoadBalancer and/or other manual configuration. The Cloud providers didn’t follow this model, making the Ingress a separate function further confusing users.
  3. Role Orientated. The API is composed of API resources which model organizational roles that use and configure Kubernetes service networking. This enables infrastructure and security engineers to define gateways that can be dynamically created by cluster users as they create and manage their applications.

This use-case does not cover the infrastructure design differences between an Ingress infrastructure and a Gateway infrastructure. It assumes that an existing, operational Ingress infrastructure is present and illustrates how to migration the Ingress resource to a Gateway Resource.

The Ingress Resource

The following Ingress resources is a simple fanout example taken directly from the Kubernetes documentation. It includes a host rule creating an initial filter based upon the URL and two prefix based paths backed by two different services.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: simple-fanout-example
spec:
  rules:
  - host: foo.bar.com
    http:
      paths:
      - path: /foo
        pathType: Prefix
        backend:
          service:
            name: service1
            port:
              number: 4200
      - path: /bar
        pathType: Prefix
        backend:
          service:
            name: service2
            port:
              number: 8080

The Gateway Resource

The Gateway resources are similar but has some important differences.

An Ingress is a predefined shared resource. How the resource is created depends of the environment and the specific Ingress implementation selected. A Gateway resource is defined differently. Gateways are created on demand, the reference used to create a gateway is defined using a gatewayClass. There can be many gatewayClasses all specifying different gateway configurations. How gateway infrastructure configuration are defined is implementation specific. In the EPIC implementation, a gatewayClass references a gatewayClassConfig which includes information used to create a Gateway in EPIC, and the gateway template, a the infrastructure blueprint for the Gateway that will be created.

Unlike an Ingress, a Gateway does not exist until its created with a gateway resources that references the gatewayclass. In the case of EPIC and other external gateway implementations, gateways are created on demand, and its possible to create as many gateways as required by applications in the cluster. By default gateways are not shared among namespaces.

In our example we assume that that their is a gatewayClass called example-gateway-class. The following creates a gateway resource. Note that the listeners are created on demand, this is different to the Ingress where the IP addresses and listeners are predefined during Ingress installation.


apiVersion: gateway.networking.k8s.io/v1alpha2
kind: Gateway
metadata:
  name: example-gateway
spec:
  gatewayClassName: example-gateway-class
  listeners:
  - name: http
    protocol: HTTP
    port: 80
$ kubectl get gtw
NAME              CLASS                   ADDRESS       READY   AGE
example-gateway   example-gateway-class   72.52.101.1   True    47d

Creating the gateway object instantiates the gateway, configuring the downstream listener, allocating IP addresses and optionally DNS names. The Gateway is now ready and routes can be added. The Gateway object is seperate from the Route object because the persistency of gateways and routes are probably different. A Gateway would be created so an application can be accessed, the structure of the application is defined in routes, these will probably change over time as new versions are tested and deployed.

The following example creates is the httpRoute object that provides the same functionality as the ingress object above.

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
  name: simple-fanout-example
spec:
  parentRefs:
  - name: example-gateway
  hostnames:
  - "foo.bar.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /foo
    backendRefs:
    - name: service1
      port: 4200
  - matches:
    - path:
      type: Prefix
      value: /bar
    backendRefs:
    - name: service2
      port: 8080

The httpRoute resource is very similar to the ingress resource in this example, however the value of the httpRoute resource is the ability to add additional functionality. Extending the example above to add a test version of service2 at the same url route accessed via a custom header “test-match: dev1” match would result in the following configuration

apiVersion: gateway.networking.k8s.io/v1alpha2
kind: HTTPRoute
metadata:
  name: simple-fanout-example
spec:
  parentRefs:
  - name: example-gateway
  hostnames:
  - "foo.bar.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /foo
    backendRefs:
    - name: service1
      port: 4200
  - matches:
    - path:
      type: Prefix
      value: /bar
    backendRefs:
    - name: service2
      port: 8080
  - matches: 
    - path:
      type: Prefix
      value: /bar
    - name: test-match
      type: Exact
      value: dev1
    backendRefs:
    - name: service2-test
      port: 8080

More Information

Additional information on using EPIC and its Gateway Controller

Information on the GatewayAPI httpRoute version used in this example