In this guide, we will learn how to install Gateway API in Kubernetes with Istio as controller.
Traditional Kubernetes Ingress has limitations: it is vendor-specific, lacks standardization, and offers limited routing capabilities. Gateway API is a next-generation Kubernetes networking API designed to manage external traffic into a cluster. It is intended to replace and improve the traditional Kubernetes Ingress resource. It is role-based, extensible, and portable across any Kubernetes cluster.
Why to use Gateway API?
- Clear separation between infra and app teams
- Removes the dependency on vendor-specific annotations
- Advanced traffic splitting
- mTLS support
- Header-based routing
- Canary deployments
- Traffic redirection and URL rewriting
- Future-ready Kubernetes networking
Prerequisites
- Kubernetes v1.26+ (we are using k3s for simplicity)
- Basic kubectl knowledge
- Linux with sudo access
Quick k3s Setup
Installing k3s is simple. Just run this one-liner command on your Linux server or test environment:
curl -sfL https://get.k3s.io | sh -
k3s comes default with kubectl pre-packaged. All you have to do is set a bash shell alias for easier access to all kubectl commands.
alias kubectl="sudo k3s kubectl"
Now that everything is ready, let’s begin installing the Gateway API in Kubernetes. Please follow the steps below sequentially.
1) Install Gateway API CRDs
Custom Resource Definitions extend Kubernetes with new resource types like Gateway and HTTPRoute.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.1/standard-install.yaml
Verify installation:
kubectl get crds | grep gateway

Expected output:
gatewayclasses.gateway.networking.k8s.iogateways.gateway.networking.k8s.iohttproutes.gateway.networking.k8s.io
2) Install Istio
istioctl is the official tool for Istio installation and management. Download this tool using following curl command,
curl -L https://istio.io/downloadIstio | sh -

Adjust the PATH variable as shown in the screenshot for istioctl. Copy the export command and run it.
Generate Istio Manifest
Instead of direct installation (which can have permission issues with k3s), we generate the manifest using following command
istioctl manifest generate --set profile=minimal > istio-minimal.yaml
We can either go with istio minimal or the default profile. Deploy Istio, run
kubectl create ns istio-system kubectl apply -f istio-minimal.yaml
You might get an error when trying to apply istio-minimal.yaml. In order to resolve the error, you first need to create istio-system namespace.

Verify Istio is running:
kubectl get pods -n istio-system
All pods should show Running status.
Cloud providers give you LoadBalancers automatically. For bare metal/k3s, MetalLB provides external IPs. Run beneath kubectl command
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.14.5/config/manifests/metallb-native.yaml
Once metallb pods are in running status, configure IP pool.
kubectl get all -n metallb-system

Configure IP Pool
Replace 192.168.1.240-192.168.1.250 with IPs from your local network:
kubectl apply -f - <<EOF
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: default-pool
namespace: metallb-system
spec:
addresses:
- 192.168.1.240-192.168.1.250
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: default-l2
namespace: metallb-system
spec: {}
EOF
4) Create GatewayClass
GatewayClass tells Kubernetes which controller manages the Gateway. Think of it like a “driver” for traffic.
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: istio
spec:
controllerName: istio.io/gateway-controller
EOF
Verify:
kubectl get gatewayclass
5) Create Gateway (Traffic Entry Point)
Gateway is your cluster’s front door that defines what traffic enters and on which ports. Create the gateway with the name “ecommerce-gateway” using following command.
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: ecommerce-gateway
spec:
gatewayClassName: istio
listeners:
- name: http
protocol: HTTP
port: 80
EOF
Check Gateway status:
kubectl get gateway ecommerce-gateway
kubectl describe gateway ecommerce-gateway
Look for Programmed: True in the status. This confirms Istio is managing it.

192.168.1.240 is an EXTERNAL-IP provided by MetalLB.
6) Deploy Backend Application
Let’s deploy one sample backend application, we use use a simple HTTP echo server to test routing. Execute the following command.
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-deployment
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: hashicorp/http-echo
args:
- "-text=Hello from Backend API"
- "-listen=:80"
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: backend-service
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
EOF
7) Create HTTPRoute (Traffic Rules)
HTTPRoute connects your Gateway to backend services with routing rules (path-based, header-based, etc.).
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-route
spec:
parentRefs:
- name: ecommerce-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: backend-service
port: 80
EOF
It routes all traffic http://<gateway-ip>/api/* to our backend service.
Verify:
kubectl get httproute api-route
kubectl describe httproute api-route
Look for Accepted: True in parent refs.

8) Test End-to-End
Now, we can test the route with a simple curl request.

curl http://<GATEWAY-IP>/api
# This should return "Hello from Backend API"
Common Issues & Fixes
| Issue | Cause | Solution |
|---|---|---|
| Gateway stuck in Pending | MetalLB not configured | Check IP pool range matches your network |
404 on /api |
HTTPRoute not attached | Run kubectl describe httproute and check parent refs |
| Connection refused | Backend pod not running | Check kubectl get pods and logs |
| No EXTERNAL-IP | MetalLB not running | Verify kubectl get pods -n metallb-system |
Quick Command Reference
# View all Gateway API resources
kubectl get gateway,httproute,gatewayclass
# Check Istio health
kubectl get pods -n istio-system
# Test routing
curl http:
# Debug HTTPRoute
kubectl describe httproute api-route
# View Istio routing config
istioctl proxy-config routes deploy/ecommerce-gateway-istio
That concludes this guide. I hope you found it helpful and informative. If you have any questions or queries, please share them in the comments section below.
Source link
