The short version. Do not try to apply or upgrade
the Gateway API CRDs on OpenShift. The cluster Ingress Operator owns
them. agentgateway supports Gateway API 1.3 through 1.5,
and OpenShift 4.21 ships 1.3.0 and 4.22 ships
1.4.1, both inside that range. So you skip the Gateway
API CRD step in the install and let agentgateway run against the
CRDs OpenShift already manages.
4.21.20
cluster on AWS (Gateway API 1.3.0). agentgateway installed
and served traffic against the cluster-managed CRDs with no CRD
changes, ran alongside OpenShift's own gateway, and a live app was
migrated from the OpenShift gateway to agentgateway with zero dropped
requests. The runnable scripts, manifests and the monitor evidence are
in the lab alongside this guide. See
what held and what bit below.
What you'll learn
How to install agentgateway on OpenShift against the Gateway API CRDs
the cluster already owns: why the Ingress Operator blocks the CRD
apply step, why you do not disable OpenShift's own gateway controller,
how to check the cluster's Gateway API version against agentgateway's
1.3 to 1.5 range, and the exact install
sequence with the CRD step skipped. Plus what held and what bit on a
live OpenShift 4.21.20 cluster, and why kgateway hits the
same constraint.
A question from customers about OpenShift migration
A team installs agentgateway on OpenShift and gets stuck on the step that applies the Kubernetes Gateway API CRDs. OpenShift already has those CRDs installed, at a version the cluster controls, and it will not let you replace or upgrade them. So the question is: when the Gateway API version OpenShift provides does not match the version agentgateway installs by default, what is the right thing to do?
The answer is that you do not need them to match exactly. You need the cluster's version to be inside the range agentgateway supports, and on current OpenShift releases it is.
Why OpenShift blocks the CRD step
From OpenShift 4.20 onwards the cluster Ingress Operator installs and
manages the gateway.networking.k8s.io CRDs itself, and a
validating admission policy allows only the Ingress Operator's service
account to create or modify CRDs in that group. The Ingress Operator
also pins those CRDs to one Gateway API version per OpenShift release.
If third-party Gateway API CRDs at a different version are forced in,
the Ingress Operator goes Degraded, and incompatible
Gateway API CRDs are documented to block cluster upgrades. Red Hat
tracks this directly in
a support solution on upgrades blocked by incompatible Gateway API CRDs.
So the rule on OpenShift is simple: leave the Gateway API CRDs to the
Ingress Operator and do not apply your own.
Do you need to disable OpenShift's gateway controller?
No. Gateway API is built for several implementations to run on one cluster, and each controller only acts on the GatewayClasses that name it. The two implementations sit side by side, they do not compete for the same Gateways.
agentgateway installs its own GatewayClass,
enterprise-agentgateway, with the controller name
solo.io/enterprise-agentgateway. The agentgateway
controller reconciles only the Gateways whose
gatewayClassName resolves to that class, and it ignores
everything else. OpenShift's built-in implementation answers to a
different controller name, openshift.io/gateway-controller,
and its Istio-based data plane is only created when you create a
GatewayClass with that name. If you never point a Gateway at the
OpenShift class, that path is never instantiated, so there is nothing
to turn off.
This is by design. Red Hat extended the Ingress Operator specifically
to let
multiple third-party Gateway API implementations run alongside the built-in one,
each selected by its controllerName. So on OpenShift you
add agentgateway's GatewayClass and route your agent, MCP and LLM
traffic through Gateways that reference it. OpenShift keeps serving its
own ingress Gateways, if you use them, with no contention. The only
thing OpenShift owns exclusively is the Gateway API CRDs, which is the
versioning point below, not the controllers.
Which Gateway API version your cluster has
The Gateway API version is set by the OpenShift release. These are the versions OpenShift's own cluster Ingress Operator pins:
| OpenShift release | Gateway API version | In agentgateway's 1.3 to 1.5 range |
|---|---|---|
| 4.19 | 1.2.1 | Below floor |
| 4.20 | 1.2.1 | Below floor (ran in our test, unsupported) |
| 4.21 | 1.3.0 | Yes |
| 4.22 | 1.4.1 | Yes |
1.2.1, which is
below the supported range, so check the actual cluster before you plan
the install. The forward path for those clusters is an OpenShift
upgrade, covered at the end.
agentgateway supports Gateway API 1.3 through 1.5
agentgateway installs Gateway API 1.5 by default when it manages the
CRDs itself, but it runs against the 1.3, 1.4 and 1.5
lines, as listed in the
agentgateway supported versions reference.
That is the detail that unlocks OpenShift: the cluster's
1.3.0 on 4.21 and 1.4.1 on 4.22 are both
supported, so you do not need to push the CRDs to 1.5. You install
agentgateway against whatever supported version the cluster already
has.
The approach: install against the cluster's CRDs
A normal agentgateway install has three CRD and chart steps: apply the
upstream Gateway API CRDs, install agentgateway's own CRDs, then
install the control plane. Only the first one touches
gateway.networking.k8s.io, and that is the step you skip
on OpenShift. Nothing in the Helm charts installs the Gateway API
CRDs, so the rest of the install is unchanged.
1. Confirm the cluster's Gateway API version is in range
kubectl get crd gateways.gateway.networking.k8s.io \
-o jsonpath='{.metadata.annotations.gateway\.networking\.k8s\.io/bundle-version}{"\n"}'
You want a version in the 1.3 to 1.5 range. OpenShift 4.21 reports
1.3.0. If the annotation is empty the CRDs are still
present and managed by OpenShift, which is fine. Do not try to upgrade
or replace them.
2. Set the license key
export AGENTGATEWAY_LICENSE_KEY=<your-license-key>
3. Skip the Gateway API CRD apply
This is the step you do not run on OpenShift. For reference, on a normal cluster it would be:
# DO NOT RUN ON OPENSHIFT, the cluster Ingress Operator already manages these.
# kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/standard-install.yaml
OpenShift already provides these CRDs. Applying them yourself
conflicts with the Ingress Operator, which goes
Degraded and can block cluster upgrades.
4. Install agentgateway's own CRDs
This chart installs only the agentgateway, ExtAuth and rate-limit
CRDs. It does not touch gateway.networking.k8s.io, so
there is no conflict with OpenShift.
helm upgrade -i enterprise-agentgateway-crds \
oci://us-docker.pkg.dev/solo-public/enterprise-agentgateway/charts/enterprise-agentgateway-crds \
--create-namespace \
--namespace agentgateway-system \
--version v2026.6.1
5. Install the control plane
helm upgrade -i enterprise-agentgateway \
oci://us-docker.pkg.dev/solo-public/enterprise-agentgateway/charts/enterprise-agentgateway \
-n agentgateway-system \
--version v2026.6.1 \
--set-string licensing.licenseKey=${AGENTGATEWAY_LICENSE_KEY}
Pin v2026.6.1 to whichever agentgateway version you are
standardising on. The OpenShift handling is identical regardless of
the version you install.
6. Verify the control plane is running
kubectl get pods -n agentgateway-system
NAME READY STATUS RESTARTS AGE
enterprise-agentgateway-5495d98459-46dpk 1/1 Running 0 19s
The data plane pods, including the proxy, ext-auth and rate-limiter, are created only after you deploy a Gateway resource.
7. Deploy a Gateway to confirm it binds to the cluster CRDs
kubectl apply -f - <<'EOF'
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: agentgateway
namespace: agentgateway-system
spec:
gatewayClassName: enterprise-agentgateway
listeners:
- name: http
protocol: HTTP
port: 8080
allowedRoutes:
namespaces:
from: All
EOF
kubectl get gateway agentgateway -n agentgateway-system
kubectl get pods -n agentgateway-system -l app.kubernetes.io/name=agentgateway
A PROGRAMMED=True Gateway and a running proxy pod confirm
agentgateway is working against the OpenShift-managed Gateway API
CRDs.
What held and what bit when we ran it
We provisioned a fresh OpenShift 4.21.20 cluster on AWS,
put a sample app behind OpenShift's own gateway, installed agentgateway
against the cluster's 1.3.0 CRDs, and migrated the app to
agentgateway with a continuous availability monitor running throughout.
The monitor logged 103 of 103 requests at 200,
zero failures across the DNS cutover, because both gateways
served the app at once and the old one stayed up while DNS moved. The
approach above works as written. These are the OpenShift specifics that
are worth knowing before you start, each one fails quietly.
-
The GatewayClass controllerName needs the
/v1suffix. OpenShift's controller isopenshift.io/gateway-controller/v1. Create the class withopenshift.io/gateway-controllerand the Ingress Operator silently ignores it: no Istio install, no error, the class sitsAccepted=Unknown. With the right name it creates an OLM subscription and installs OpenShift Service Mesh automatically. -
OpenShift's gateway only programs Gateways in
openshift-ingress. AGatewayfor theopenshift-defaultclass in an app namespace staysPendingwith no diagnostic and no proxy or load balancer. Put the Gateway inopenshift-ingress; theHTTPRoutecan stay with the app and attach across namespaces. agentgateway has no such restriction. -
agentgateway's proxy needs an SCC. The control plane
runs fine under
restricted-v2, but the proxy pod runs as a fixed UID thatrestricted-v2rejects, so the proxy never schedules (and you get connection failures with no obvious cause). Grant the gateway's service accountanyuid(oc adm policy add-scc-to-user anyuid -z <sa> -n <ns>), or a tailored custom SCC, then roll the proxy. -
Enable cross-zone load balancing for a clean test.
With workers in two AZs but the load balancer spanning three, the
empty-AZ node blackholes a share of connections and looks exactly
like intermittent downtime. The
aws-load-balancer-cross-zone-load-balancing-enabledannotation on the gateway Service clears it. -
Both gateways coexist, nothing is disabled. After
installing agentgateway,
openshift-defaultandenterprise-agentgatewayare bothAcceptedGatewayClasses, each owning only the Gateways that name its controller. That is what makes the side-by-side migration possible.
One install note specific to AWS: IPI's default credentials mode needs long-lived AWS credentials, so temporary SSO/STS credentials are rejected. Use a dedicated installer IAM user with a static access key and delete it at teardown.
What about clusters below the floor (1.2.1)?
We also stood up OpenShift 4.20.25, which pins Gateway API
1.2.1, below agentgateway's documented 1.3
floor. agentgateway still installed and served end to end there: the
control plane came up, the Gateway went Programmed, the
HTTPRoute attached, and the proxy served clean 200s (the
same anyuid SCC step applied). So for core
Gateway and HTTPRoute, agentgateway
functionally runs on 1.2.1.
Two caveats keep this honest. It runs, but 1.2.1 is below the
supported range, so it is unsupported even though it works,
and we exercised only the core routing path. Anything that needs a CRD
field or kind newer than 1.2.1, or ListenerSet, is not
there. The takeaway for the field: OpenShift is not a hard wall even on
1.2.1, but the supported guidance is still to be on 1.3 or
higher, which means OpenShift 4.21 or later.
kgateway hits the same constraint
This is not unique to agentgateway. Any Gateway API implementation on
OpenShift faces the same CRD ownership, and kgateway is in the same
position. Each kgateway release targets a Gateway API version:
kgateway 2.0 on 1.2.x, 2.1 on 1.4.x, and 2.2
on 1.5.x. The same approach applies: check the
kgateway supported versions reference
against the cluster's Gateway API version, skip the upstream Gateway
API CRD apply, and install kgateway against the CRDs OpenShift
manages.
Forward path: upgrade OpenShift
For a cluster below the supported range, an OpenShift upgrade is the clean fix, and it gets better with each recent release:
-
OpenShift 4.21 ships Gateway API
1.3.0, which is supported today. No CRD work needed, install against it. -
OpenShift 4.22 ships Gateway API
1.4.1and also lifts the restriction that blocked self-managed Gateway API CRDs, so from 4.22 you can manage the CRDs up to 1.5 yourself if you ever need a newer Gateway API feature.
So for hosted clusters still on an early release, the guidance is to plan the upgrade to 4.21 or later. Once there, the install is the skip-the-CRD-step sequence above.
ListenerSet on OpenShift.
agentgateway's controller does support the upstream Gateway API
ListenerSet, so the feature is not missing. The blocker is
the CRD's release channel: upstream ListenerSet is in the
experimental channel for Gateway API 1.3 and 1.4 and only
reaches the standard channel in 1.5. OpenShift installs the
standard channel and blocks you adding CRDs yourself, so the
ListenerSet CRD is not present on current OpenShift,
neither 4.21 (1.3.0) nor 4.22 (1.4.1 standard) has it; you would need
an OpenShift release on Gateway API 1.5. Solo's
EnterpriseListenerSet, a CRD in Solo's own
enterprise.solo.io group that sidesteps the channel
problem, ships in kgateway enterprise today but is
not yet in the released agentgateway chart (verified
on v2026.6.1: not installed,
installEnterpriseListenerSetCRD is a no-op there). So for
ListenerSet on agentgateway on OpenShift today there is no
path yet, use kgateway, or wait for the agentgateway
EnterpriseListenerSet release or an OpenShift release on
Gateway API 1.5. For the core LLM, MCP and agent routing and policy
surface you do not need it, 1.3.0, and even 1.2.1 in our test, is
enough.
Checklist
agentgateway on OpenShift, the short version
- Do not apply or upgrade the Gateway API CRDs. OpenShift's Ingress Operator owns them, and forcing your own degrades the operator and can block cluster upgrades.
- No OpenShift controller to disable. agentgateway brings its own GatewayClass (
solo.io/enterprise-agentgateway) and only owns Gateways that reference it, so it runs alongside OpenShift's built-in implementation. - Check the cluster's Gateway API version. It needs to be in agentgateway's
1.3to1.5range. OpenShift 4.21 is1.3.0, 4.22 is1.4.1. - Skip the
standard-install.yamlstep in the install. Install the agentgateway CRD chart and the control plane as normal. - agentgateway runs against the cluster's existing CRDs. You do not need to push them to 1.5.
- For clusters below 1.3, including older ARO and ROSA, plan an OpenShift upgrade. 4.21 gives a supported version, 4.22 also lets you self-manage the CRDs.
- Confirm whether any feature needs a CRD newer than the cluster has, such as
ListenerSetfrom 1.4. - Same constraint and same approach apply to kgateway on OpenShift.