The Gateway API is an official Kubernetes project and the next-generation API for Kubernetes routing and load balancing that lets you configure traffic rules. This topic describes how to use the Gateway API to expose a service to traffic from outside a cluster using an Application Load Balancer (ALB) instance.
Background information
The Gateway API is a collection of Kubernetes resources used to model service network traffic. The goal of the Gateway API is to provide an expressive, extensible, and role-oriented model for service networking.
The ALB Ingress Controller has supported the Gateway API since version 2.17.0. You can install the ALB Ingress Controller and use the Gateway API to expose services through an ALB instance.
Prerequisites
An ACK managed cluster that runs Kubernetes 1.24 or later is created.
The ALB Ingress Controller of version 2.17.0 or later is installed in the cluster.
The Gateway API of version 1.1.0 or later is installed in the cluster.
Two virtual switches that support ALB are created in the VPC where the cluster is deployed.
Verify the environment
If your cluster meets the prerequisites, a GatewayClass resource named alb is automatically created. You can verify this in the following ways.
Console
Log on to the ACK console. In the left navigation pane, click Clusters.
On the Clusters page, find the target cluster and click its name. In the navigation pane on the left, choose .
Click gateway.networking.k8s.io and view the GatewayClass under v1.

kubectl
kubectl get gatewayclassExpected output:
NAME CONTROLLER ACCEPTED AGE
alb gateways.alibabacloud.com/alb/v1 True 1mDeploy a sample application
Create an
httpbin.yamlfile.NoteIn this topic, the Service for the application uses
ClusterIPby default. If your cluster uses the Flannel network plug-in, change thespec.typeof the Service toNodePort.apiVersion: apps/v1 kind: Deployment metadata: name: go-httpbin namespace: default spec: replicas: 1 selector: matchLabels: app: go-httpbin template: metadata: labels: app: go-httpbin version: v1 spec: containers: - image: registry.cn-hangzhou.aliyuncs.com/mse/go-httpbin args: - "--port=8090" - "--version=v1" imagePullPolicy: Always name: go-httpbin ports: - containerPort: 8090 --- apiVersion: v1 kind: Service metadata: name: go-httpbin namespace: default spec: type: ClusterIP ports: - port: 80 targetPort: 8090 protocol: TCP selector: app: go-httpbinDeploy the application.
kubectl apply -f httpbin.yaml
Deploy the Gateway and route
This operation creates an ALB instance and incurs fees. ALB instances that are created by a Gateway are not automatically deleted when you delete the cluster. To avoid unexpected charges, delete the Gateway resource before you delete the cluster.
Create a
gateway.yamlfile.apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: alb namespace: default spec: gatewayClassName: alb listeners: - name: http protocol: HTTP port: 80 hostname: "*.ingress.top" allowedRoutes: namespaces: from: Same --- apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: demo-route spec: parentRefs: # Reference the Gateway resource - group: gateway.networking.k8s.io kind: Gateway name: alb hostnames: - demo.ingress.top # Set the host to demo.domain.ingress.top rules: - matches: # The matching rule is a prefix match for the path - path: type: PathPrefix value: / backendRefs: # The backend is a Service named go-httpbin on port 80 - kind: Service name: go-httpbin port: 80Deploy the Gateway and the routing rule.
kubectl apply -f gateway.yamlWait for about 2 minutes and then check the creation status of the Gateway.
kubectl get gateway albExpected output:
NAME CLASS ADDRESS PROGRAMMED AGE alb alb alb-0mwhq4ck6xxxxxxxxx.cn-hangzhou.alb.aliyuncsslb.com True 2m12sThe output indicates that the Gateway is created.
Check the creation status of the route.
kubectl describe httproute demo-route|grep Status -A 20Expected output:
Status: Parents: Conditions: Last Transition Time: 2025-05-23T08:21:25Z Message: Route is accepted. Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2025-05-23T08:21:25Z Message: Route is resolved. Observed Generation: 1 Reason: ResolvedRefs Status: True Type: ResolvedRefs Controller Name: gateways.alibabacloud.com/alb/v1 Parent Ref: Group: gateway.networking.k8s.io Kind: Gateway Name: albTest access to the application.
Obtain the Gateway address.
export ALB_DOMAIN=$(kubectl get gateway alb -n default -o jsonpath='{.status.addresses[?(@.type=="Hostname")].value}')Access the application.
curl -H "Host: demo.ingress.top" http://${ALB_DOMAIN}/versionExpected output:
version: v1 hostname: go-httpbin-547xxxxxf6-xxxxx
Scenarios
Scenario 1: Use a filter to modify request headers
The filter feature of HTTPRoute lets you perform additional processing during the request or response phase. The following example shows how to use a filter to add a request header to requests that are sent to the backend.
Create an
httproute-filter.yamlfile.apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: demo-filter spec: parentRefs: # Reference the Gateway resource - group: gateway.networking.k8s.io kind: Gateway name: alb hostnames: - filter.ingress.top # Set the host to filter.ingress.top rules: - matches: # The matching rule is a prefix match for the path - path: type: PathPrefix value: / filters: - type: RequestHeaderModifier # Add the request header my-header: foo requestHeaderModifier: add: - name: my-header value: foo backendRefs: # The backend is a Service named go-httpbin on port 80 - kind: Service name: go-httpbin port: 80This file creates an HTTPRoute resource named
demo-filter. After you deploy the resource, when you access the go-httpbin application using the domain namefilter.ingress.top, the request headermy-header: foois automatically added to the request.Deploy the routing rule.
kubectl apply -f httproute-filter.yamlAccess the application.
curl -H "Host: filter.ingress.top" http://${ALB_DOMAIN}/headerExpected output:
headers: { "Accept": [ "*/*" ], "Connection": [ "close" ], "Host": [ "filter.ingress.top" ], "My-Header": [ "foo" ], "Path": [ "/header" ], "Protocol": [ "HTTP/1.1" ], "Remoteip": [ "118.xx.xx.91" ], "URL": [ "/header" ], "User-Agent": [ "curl/8.9.1" ] } query param: , hostname: go-httpbin-547xxxxxf6-xxxxx
Scenario 2: Split traffic based on weight
You can set weights for multiple backend services to split request traffic.
Create an
nginx.yamlfile.The preceding file deploys two NGINX applications. The
old-nginxservice returns theoldstring, and thenew-nginxservice returns thenewstring. The deployed resources are in thedefaultnamespace.Create an
httproute-weight.yamlfile.apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: demo-weight spec: parentRefs: # Reference the Gateway resource - group: gateway.networking.k8s.io kind: Gateway name: alb hostnames: - weight.ingress.top # Set the host to weight.ingress.top rules: - matches: # The matching rule is a prefix match for the path - path: type: PathPrefix value: / backendRefs: # Set the backend and its corresponding weight. The weight is not a percentage and does not need to add up to 100. - kind: Service name: old-nginx port: 80 weight: 100 # Set the weight of old-nginx to 100 - kind: Service name: new-nginx port: 80 weight: 100 # Set the weight of new-nginx to 100This routing rule sets the same weight for the
old-nginxandnew-nginxservices. Therefore, when you access the application, traffic is distributed between thenew-nginxandold-nginxservices at a 1:1 ratio.Deploy the applications and the routing rule.
kubectl apply -f nginx.yaml kubectl apply -f httproute-weight.yamlAccess the application 10 times.
for i in {1..10}; do curl -H "Host: weight.ingress.top" http://${ALB_DOMAIN}/; doneExpected output:
old new new old new old old new new oldThe output indicates that traffic is distributed between the
new-nginxandold-nginxservices at a 1:1 ratio.
Related operations
Configure a certificate for the application
You can configure a TLS certificate for the application in the Gateway resource.
Create a self-signed certificate for the domain name
ingress.tap.openssl req -subj '/CN=ingress.top' -new -newkey rsa:2048 -sha256 \ -days 365 -nodes -x509 -keyout server.key -out server.crt \ -addext "subjectAltName = DNS:ingress.top" \ -addext "keyUsage = digitalSignature" \ -addext "extendedKeyUsage = serverAuth" 2> /dev/null; openssl x509 -in server.crt -subject -nooutCreate a TLS Secret.
kubectl create secret tls ingress.top --key server.key --cert server.crtCreate a
gateway-tls.yamlfile to update the Gateway.apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: alb namespace: default spec: gatewayClassName: alb listeners: - name: http protocol: HTTP port: 80 hostname: "*.ingress.top" allowedRoutes: namespaces: from: Same - name: https protocol: HTTPS port: 443 hostname: "*.ingress.top" allowedRoutes: namespaces: from: Same tls: # Configure TLS mode: Terminate certificateRefs: # Reference the created secret - kind: Secret name: ingress.topUpdate the Gateway.
gateway.gateway.networking.k8s.io/alb configuredAfter the Programmed status of the Gateway changes to True, you can verify the certificate configuration.
openssl s_client -servername ingress.top -connect ${ALB_DOMAIN}:443Expected output:
CONNECTED(00000003) depth=0 CN = ingress.top verify error:num=18:self-signed certificate verify return:1 depth=0 CN = ingress.top verify return:1 --- Certificate chain 0 s:CN = ingress.top i:CN = ingress.top a:PKEY: rsaEncryption, 2048 (bit); sigalg: RSA-SHA256 v:NotBefore: Jun 24 10:49:39 2025 GMT; NotAfter: Jun 24 10:49:39 2026 GMT --- Server certificate -----BEGIN CERTIFICATE----- ... ... ... -----END CERTIFICATE----- subject=CN = ingress.top issuer=CN = ingress.top --- No client certificate CA names sent Peer signing digest: SHA256 Peer signature type: RSA-PSS Server Temp Key: X25519, 253 bits --- SSL handshake has read 1506 bytes and written 410 bytes Verification error: self-signed certificate --- New, TLSv1.2, Cipher is ECDHE-RSA-AES128-GCM-SHA256 Server public key is 2048 bit Secure Renegotiation IS supported Compression: NONE Expansion: NONE No ALPN negotiated SSL-Session: Protocol : TLSv1.2 Cipher : ECDHE-RSA-AES128-GCM-SHA256 Session-ID: xxxxxxxxxxxxxxxxxxxxxxxxx Session-ID-ctx: Master-Key: xxxxxxxxxxxxxxxxxxxxxxxxxxx PSK identity: None PSK identity hint: None SRP username: None TLS session ticket lifetime hint: 300 (seconds) TLS session ticket: ... ... ... Start Time: 1750820008 Timeout : 7200 (sec) Verify return code: 18 (self-signed certificate) Extended master secret: yes ---If an output similar to the preceding one is returned, the certificate is valid.
NoteYou can run
curl -H "Host: demo.ingress.top" -k https://${ALB_DOMAIN}/versionto access the application. The expected output is the same as that in Test access to the application.