Deploy a Gateway API controller
The Gateway API is the next-generation Kubernetes API for managing service networking. A Gateway API controller processes traffic from outside a cluster to internal services according to rules defined in resources such as Gateway and HTTPRoute. For more information, see the official Kubernetes Gateway API documentation. This guide explains how to configure and deploy a Gateway API controller in a cluster.
This guide uses NGINX Gateway Fabric, validated with version 2.3.0, as an example implementation of a Gateway API controller.
Kubernetes Engine does not provide or manage a Gateway API controller. You are responsible for selecting, deploying, and operating the controller. Deployment manifests and Helm chart options may differ in other versions, so also refer to the official documentation for the version you use.
Compare Ingress and Gateway API
Ingress uses a single resource model that defines the host, path, TLS, and backend in one resource. Gateway API separates these responsibilities into three layers—GatewayClass → Gateway → HTTPRoute—so infrastructure administrators and application developers can independently manage their respective concerns.
| Category | Ingress | Gateway API |
|---|---|---|
| Routing definition | One Ingress resource | Separate Gateway and HTTPRoute resources |
| TLS configuration | spec.tls | Gateway listeners[].tls |
| Path matching | spec.rules[].http.paths | HTTPRoute spec.rules[].matches |
| Host matching | spec.rules[].host | HTTPRoute spec.hostnames |
| Backend | backend.service.name / port | backendRefs[].name / port |
| Controller selection | ingressClassName | gatewayClassName |
| Cross-namespace routing | Not supported | Supported with ReferenceGrant |
| Header-based routing | Annotations (non-standard) | matches[].headers (standard) |
| Traffic splitting | Not supported | backendRefs[].weight |
For instructions on migrating an existing Ingress to Gateway API, see Migrate from Ingress to Gateway API.
Step 1. Prerequisites
Complete the following prerequisites before configuring and deploying a Gateway API controller.
-
Create a cluster where you will deploy the Gateway API controller.
-
Configure kubectl control so that you can send deployment commands to the cluster.
-
Install the Gateway API CRDs (Custom Resource Definitions) in the cluster.
Install Gateway API CRDskubectl --kubeconfig=$KUBE_CONFIG kustomize "https://github.com/nginx/nginx-gateway-fabric/config/crd/gateway-api/standard?ref=v2.3.0" | kubectl --kubeconfig=$KUBE_CONFIG apply -f -Verify the installationkubectl --kubeconfig=$KUBE_CONFIG get crd | grep gatewayOutputbackendtlspolicies.gateway.networking.k8s.io 2026-03-19T02:59:09Z
gatewayclasses.gateway.networking.k8s.io 2026-03-19T02:59:09Z
gateways.gateway.networking.k8s.io 2026-03-19T02:59:10Z
grpcroutes.gateway.networking.k8s.io 2026-03-19T02:59:10Z
httproutes.gateway.networking.k8s.io 2026-03-19T02:59:10Z
referencegrants.gateway.networking.k8s.io 2026-03-19T02:59:10Z
Step 2. Deploy the Gateway API controller
Deploy a Gateway API controller based on the open-source NGINX Gateway Fabric.
Kubernetes Engine currently does not support Admission Webhooks. To deploy a service configured with an Admission Webhook, set hostNetwork: true.
Deploy using YAML files
The deployment can fail if the target namespace does not exist. Create the namespace first.
kubectl --kubeconfig=$KUBE_CONFIG create namespace nginx-gateway
Run the following commands to deploy the NGINX Gateway Fabric CRDs and controller in the cluster. The required services, GatewayClass, and other resources are deployed together.
kubectl --kubeconfig=$KUBE_CONFIG apply --server-side -f https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/v2.3.0/deploy/crds.yaml
kubectl --kubeconfig=$KUBE_CONFIG apply -f https://raw.githubusercontent.com/nginx/nginx-gateway-fabric/v2.3.0/deploy/default/deploy.yaml
Deploy using Helm
Deploy the Gateway API controller using Helm, the Kubernetes package manager.
-
Install the Helm client before installing the Gateway API controller. For operating-system-specific instructions, see Installing Helm.
-
Run the following command to deploy NGINX Gateway Fabric in the cluster. NGINX Gateway Fabric provides its Helm chart through an OCI registry, so you do not need to run
helm repo add.Deploy NGINX Gateway Fabrichelm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--version 2.3.0 \
--namespace nginx-gateway --create-namespaceOutputPulled: ghcr.io/nginx/charts/nginx-gateway-fabric:2.3.0
Digest: sha256:96910ca9172f8e29c7fbfff9915403eff899653c8d2c9b2703f6e2976744591f
NAME: ngf
LAST DEPLOYED: Thu Mar 19 13:17:49 2026
NAMESPACE: nginx-gateway
STATUS: deployed
REVISION: 1
TEST SUITE: NoneIf NGINX Gateway Fabric is already deployed with Helm, upgrade the existing release.
Upgrade an existing NGINX Gateway Fabric releasehelm upgrade ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
--version 2.3.0 \
--namespace nginx-gateway
Step 3. Verify the controller deployment
-
Run the following command and observe the Pod status to verify that the Gateway API controller was deployed successfully. Confirm that the
nginx-gatewayPod is running.-
When the
nginx-gatewayPod reaches theRunningstate, press Ctrl+C to stop watching.Verify that the Pod is runningkubectl --kubeconfig=$KUBE_CONFIG get pods -n nginx-gateway --watchOutputNAME READY STATUS RESTARTS AGE
nginx-gateway-cd9c6c4f5-jhbbx 1/1 Running 0 41s
nginx-gateway-cert-generator-rgp26 0/1 Completed 0 41s
-
-
Verify that the GatewayClass resource was created successfully.
Verify GatewayClasskubectl --kubeconfig=$KUBE_CONFIG get gatewayclassOutputNAME CONTROLLER ACCEPTED AGE
nginx gateway.nginx.org/nginx-gateway-controller True 60s
Step 4. Create a Gateway resource
After deploying the Gateway API controller, create a Gateway resource to configure listeners. Creating the Gateway resource also provisions a load balancer.
-
Create a Gateway resource using the following YAML file.
gateway.yamlapiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx-gateway
namespace: nginx-gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
allowedRoutes:
namespaces:
from: All
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: nginx-tls-secret
allowedRoutes:
namespaces:
from: AllCreate the Gateway resourcekubectl --kubeconfig=$KUBE_CONFIG apply -f gateway.yaml -
Verify that the Gateway resource was created successfully.
Verify the Gateway resourcekubectl --kubeconfig=$KUBE_CONFIG get gateway -n nginx-gatewayOutputNAME CLASS ADDRESS PROGRAMMED AGE
nginx-gateway nginx k8s-nginxga-nginxga-xxxxxxxxxx-xxxxxx.ke.kr-central-2.kakaocloud.com True 3m47s -
Check the Gateway
ADDRESSin the output.ADDRESSis the load balancer domain and becomes the endpoint for services exposed through HTTPRoute.
Step 5. Route traffic using HTTPRoute
Use an HTTPRoute resource to route incoming Gateway traffic to backend services.
The following example assumes that the demo-app-v1 and demo-app-v2 Services are already deployed in the demo-apps namespace.
If your Service names or ports differ, update backendRefs for your environment.
-
Create an HTTPRoute resource using the following YAML file.
httproute.yamlapiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: demo-route
namespace: demo-apps
spec:
parentRefs:
- name: nginx-gateway
namespace: nginx-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /v1
backendRefs:
- name: demo-app-v1
port: 80
- matches:
- path:
type: PathPrefix
value: /v2
backendRefs:
- name: demo-app-v2
port: 80Create the HTTPRoute resourcekubectl --kubeconfig=$KUBE_CONFIG apply -f httproute.yaml -
Verify that the HTTPRoute resource was created successfully.
Verify the HTTPRoute resourcekubectl --kubeconfig=$KUBE_CONFIG get httproute -n demo-appsOutputNAME HOSTNAMES AGE
demo-route 7s
Configure a public IP for the Gateway load balancer
-
If the load balancer created by the Gateway needs external connectivity, you can configure whether it uses a public IP.
- Run the following command to find the Service of type LoadBalancer created by the Gateway deployment.
Find the Service of type LoadBalancerkubectl --kubeconfig=$KUBE_CONFIG get svc -n nginx-gateway -
Set the
service.beta.kubernetes.io/openstack-internal-load-balancervalue undermetadata.annotationson the Service of type LoadBalancer.- Set it to
trueto create a load balancer with a private IP. This is the default. - Set it to
falseto create a load balancer with a public IP.
- Set it to
For details about load balancer options, see Create and delete load balancer > Appendix: Configure detailed load balancer options.
- Depending on the value of
service.beta.kubernetes.io/openstack-internal-load-balancer, a new public IP is created and associated with the load balancer, or the existing public IP is disassociated. If a public IP was used when the value wasfalse, changing the value totrueonly disassociates that public IP. The disassociated public IP remains billable until it is deleted. - To delete a public IP used by a Kubernetes Engine load balancer, go to KakaoCloud console > VPC > Public IP. For details, see Create and manage public IP.