apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: openshift-default
spec:
controllerName: openshift.io/gateway-controller/v1 (1)
OKD provides additional ways of configuring network traffic by using Gateway API with the Ingress Operator.
Gateway API does not support user-defined networks (UDN). |
Gateway API is an open source, community-managed, Kubernetes networking mechanism. It focuses on routing within the transport layer, L4, and the application layer, L7, for clusters. A variety of vendors offer many implementations of Gateway API.
The project is an effort to provide a standardized ecosystem by using a portable API with broad community support. By integrating Gateway API functionality into the Ingress Operator, it enables a networking solution that aligns with existing community and upstream development efforts.
Gateway API extends the functionality of the Ingress Operator to handle more granular cluster traffic and routing configurations. With these capabilities, you can create instances of Gateway APIs custom resource definitions (CRDs). For OKD clusters, the Ingress Operator creates the following resources:
This resource describes how traffic can be translated to services within the cluster. For example, a specific load balancer configuration.
This resource defines a set of Gateway
objects that share a common configuration and behavior. For example, two separate GatewayClass
objects might be created to distinguish a set of Gateway
resources used for public or private applications.
This resource specifies the routing behavior of HTTP requests from a Gateway to a service, and is especially useful for multiplexing HTTP or terminated HTTPS connections.
This resource specifies the routing behavior of gRPC requests.
This resource enables cross-namespace references. For example, it enables routes to forward traffic to backends that are in a different namespace.
In OKD, the implementation of Gateway API is based on gateway.networking.k8s.io/v1
, and all fields in this version are supported.
Gateway API provides the following benefits:
Portability: While OKD uses HAProxy to improve Ingress performance, Gateway API does not rely on vendor-specific annotations to provide certain behavior. To get comparable performance as HAProxy, the Gateway
objects need to be horizontally scaled or their associated nodes need to be vertically scaled.
Separation of concerns: Gateway API uses a role-based approach to its resources, and more neatly fits into how a large organization structures its responsibilities and teams. Platform engineers might focus on GatewayClass
resources, cluster admins might focus on configuring Gateway
resources, and application developers might focus on routing their services with HTTPRoute
resources.
Extensibility: Additional functionality is developed as a standardized CRD.
Gateway API has the following limitations:
Version incompatibilities: Gateway API ecosystem changes rapidly, and some implementations do not work with others because their featureset is based on differing versions of Gateway API.
Resource overhead: While more flexible, Gateway API uses multiple resource types to achieve an outcome. For smaller applications, the simplicity of traditional Ingress might be a better fit.
The Ingress Operator manages the lifecycle of Gateway API CRDs in a way that enables other vendor implementations to make use of CRDs defined in an OKD cluster.
In some situations, Gateway API provides one or more fields that a vendor implementation does not support, but that implementation is otherwise compatible in schema with the rest of the fields. These "dead fields" can result in disrupted Ingress workloads, improperly provisioned applications and services, and security related issues. Because OKD uses a specific version of Gateway API CRDs, any use of third-party implementations of Gateway API must conform to the OKD implementation to ensure that all fields work as expected.
Any CRDs created within an OKD 4.19 cluster are compatibly versioned and maintained by the Ingress Operator. If CRDs are already present but were not previously managed by the Ingress Operator, the Ingress Operator checks whether these configurations are compatible with Gateway API version supported by OKD, and creates an admin-gate that requires your acknowledgment of CRD succession.
If you are updating your cluster from a previous OKD version that contains Gateway API CRDs change those resources so that they exactly match the version supported by OKD. Otherwise, you cannot update your cluster because those CRDs were not managed by OKD, and could contain functionality that is unsupported by Red Hat. |
When you create a GatewayClass as shown in the first step, it configures Gateway API for use on your cluster.
Create a GatewayClass
object:
Create a YAML file, openshift-default.yaml
, that contains the following information:
GatewayClass
CRapiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: openshift-default
spec:
controllerName: openshift.io/gateway-controller/v1 (1)
1 | The controller name. |
The controller name must be exactly as shown for the Ingress Operator to manage it. If you set this field to anything else, the Ingress Operator ignores the |
Run the following command to create the GatewayClass
resource:
$ oc create -f openshift-default.yaml
gatewayclass.gateway.networking.k8s.io/openshift-default created
During the creation of the GatewayClass
resource, the Ingress Operator installs a lightweight version of Red Hat OpenShift Service Mesh, an Istio custom resource, and a new deployment in the openshift-ingress
namespace.
Optional: Verify that the new deployment, istiod-openshift-gateway
is ready and available:
$ oc get deployment -n openshift-ingress
NAME READY UP-TO-DATE AVAILABLE AGE
istiod-openshift-gateway 1/1 1 1 55s
router-default 2/2 2 2 6h4m
Create a secret by running the following command:
$ oc -n openshift-ingress create secret tls gwapi-wildcard --cert=wildcard.crt --key=wildcard.key
Get the domain of the Ingress Operator by running the following command:
$ DOMAIN=$(oc get ingresses.config/cluster -o jsonpath={.spec.domain})
Create a Gateway
object:
Create a YAML file, example-gateway.yaml
, that contains the following information:
Gateway
CRapiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: example-gateway
namespace: openshift-ingress (1)
spec:
gatewayClassName: openshift-default (2)
listeners:
- name: https (3)
hostname: "*.gwapi.${DOMAIN}" (4)
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: gwapi-wildcard (5)
allowedRoutes:
namespaces:
from: All
1 | The Gateway object must be created in the openshift-ingress namespace. |
2 | The Gateway object must reference the name of the previously created GatewayClass object. |
3 | The HTTPS listener listens for HTTPS requests that match a subdomain of the cluster domain. You use this listener to configure ingress to your applications by using Gateway API HTTPRoute resources. |
4 | The hostname must be a subdomain of the Ingress Operator domain. If you use a domain, the listener tries to serve all traffic in that domain. |
5 | The name of the previously created secret. |
Apply the resource by running the following command:
$ oc apply -f example-gateway.yaml
Optional: When you create a Gateway
object, Red Hat OpenShift Service Mesh automatically provisions a deployment and service with the same name. Verify this by running the following commands:
To verify the deployment, run the following command:
$ oc get deployment -n openshift-ingress example-gateway-openshift-default
NAME READY UP-TO-DATE AVAILABLE AGE
example-gateway-openshift-default 1/1 1 1 25s
To verify the service, run the following command:
$ oc get service -n openshift-ingress example-gateway-openshift-default
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-gateway-openshift-default LoadBalancer 10.1.2.3 <external_ipname> <port_info> 47s
Optional: The Ingress Operator automatically creates a DNSRecord
CR using the hostname from the listeners, and adds the label gateway.networking.k8s.io/gateway-name=example-gateway
. Verify the status of the DNS record by running the following command:
$ oc -n openshift-ingress get dnsrecord -l gateway.networking.k8s.io/gateway-name=example-gateway -o yaml
kind: DNSRecord
...
status:
...
zones:
- conditions:
- message: The DNS provider succeeded in ensuring the record
reason: ProviderSuccess
status: "True"
type: Published
dnsZone:
tags:
...
- conditions:
- message: The DNS provider succeeded in ensuring the record
reason: ProviderSuccess
status: "True"
type: Published
dnsZone:
id: ...
Create an HTTPRoute
resource that directs requests to your already-created namespace and application called example-app/example-app
:
Create a YAML file, example-route.yaml
, that contains the following information:
HTTPRoute
CRapiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: example-route
namespace: example-app-ns (1)
spec:
parentRefs: (2)
- name: example-gateway
namespace: openshift-ingress
hostnames: ["example.gwapi.${DOMAIN}"] (3)
rules:
- backendRefs: (4)
- name: example-app (5)
port: 8443
1 | The namespace you are deploying your application. |
2 | This field must point to the Gateway object you previously configured. |
3 | The hostname must match the one specified in the Gateway object. In this case, the listeners use a wildcard hostname. |
4 | This field specifies the backend references that point to your service. |
5 | The name of the Service for your application. |
Apply the resource by running the following command:
$ oc apply -f example-route.yaml
httproute.gateway.networking.k8s.io/example-route created
Verify that the Gateway
object is deployed and has the condition Programmed
by running the following command:
$ oc wait -n openshift-ingress --for=condition=Programmed gateways.gateway.networking.k8s.io example-gateway
gateway.gateway.networking.k8s.io/example-gateway condition met
Send a request to the configured HTTPRoute
object hostname:
$ curl -I --cacert <local cert file> https://example.gwapi.${DOMAIN}:443
Gateway API is designed to accomodate two topologies: shared gateways or dedicated gateways. Each topology has its own advantages and different security implications.
Routes and any load balancers or proxies are served from the same namespace. The Gateway
object restricts routes to a particular application namespace. This is the default topology when deploying a Gateway API resource in OKD.
Routes are served from multiple namespaces or with multiple hostnames. The Gateway
object filters allow routes from application namespaces by using the spec.listeners.allowedRoutes.namespaces
field.
The following example shows a dedicated Gateway
resource, fin-gateway
:
Gateway
resourceapiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: fin-gateway
namespace: openshift-ingress
spec:
listeners: (1)
- name: http
protocol: HTTP
port: 8080
hostname: "example.com"
1 | Creating a Gateway resource without setting spec.listeners[].allowedRoutes results in implicitly setting the namespaces.from field to have the value Same . |
The following example shows the associated HTTPRoute
resource, sales-db
, which attaches to the dedicated Gateway
object:
HTTPRoute
resourceapiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: sales-db
namespace: openshift-ingress
spec:
parentRefs:
- name: fin-gateway
hostnames:
- sales-db.example.com
rules:
- backendRefs:
- name: sales-db
¦ port: 8080
The HTTPRoute
resource must have the name of the Gateway
object as the value for its parentRefs
field in order to attach to the gateway. Implicitly, the route is assumed to be in the same namespace as the Gateway
object.
The following example shows a Gateway
resource, devops-gateway
, that has a spec.listeners.allowedRoutes.namespaces
label selector set to match any namespaces containing shared-gateway-access: "true"
:
Gateway
resourceapiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: devops-gateway
namespace: openshift-ingress
listeners:
- name: https
protocol: HTTPS
hostname: "example.com"
allowedRoutes:
namespaces:
from: Selector
selector:
¦ matchLabels:
¦ shared-gateway-access: "true"
The following examples show the allowed namespaces for the devops-gateway
resource:
Namespace
resourcesapiVersion: v1
kind: Namespace
metadata:
name: dev
labels:
shared-gateway-access: "true"
---
apiVersion: v1
kind: Namespace
metadata:
name: ops
labels:
shared-gateway-access: "true"
In this example, two HTTPRoute
resources, dev-portal
and ops-home
, are in different namespaces but are attached to the shared gateway:
apiVersion: v1
kind: HTTPRoute
metadata:
name: dev-portal
namespace: dev
spec:
parentRefs:
- name: devops-gateway
namespace: openshift-ingress
rules:
- backendRefs:
- name: dev-portal
port: 8080
---
apiVersion: v1
kind: HTTPRoute
metadata:
name: ops-home
namespace: ops
spec:
parentRefs:
- name: devops-gateway
namespace: openshift-ingress
rules:
- backendRefs:
- name: ops-home
port: 8080
With a shared gateway topology, the routes must specify the namespace of the Gateway
object it wants to attach to. Multiple Gateway
objects can be deployed and shared across namespaces. When there are multiple shared gateways, this topology becomes conceptually similar to Ingress Controller sharding.