The Gateway API is an official Kubernetes project that provides next-generation APIs for Kubernetes routing and load balancing. This topic describes how to use an Application Load Balancer (ALB) with the Gateway API to configure traffic rules and expose services outside a cluster.
Background information
The Gateway API is a collection of Kubernetes resources used to model service network traffic. Its goal is to provide an expressive, extensible, and role-oriented service network model.
ALB Ingress Controller versions 2.17.0 and later support the Gateway API. You must install the ALB Ingress Controller to expose services through an ALB using the Gateway API.
Prerequisites
An ACS cluster of version 1.31 or later is created.
The ALB Ingress Controller, version 2.17 or later, is installed in the cluster.
The Gateway API, version 1.3.0 or later, is installed in the cluster.
Two virtual switches that support ALB are created in the cluster's VPC.
Verify the environment
If your cluster meets the prerequisites, a GatewayClass resource named alb is automatically created. You can use one of the following methods to verify the resource.
Console
Log on to the ACS console. In the left-side navigation pane, click Clusters.
On the Clusters page, find the cluster that you want to manage and click its ID. In the left-side navigation pane of the cluster details page, choose Workloads > Custom Resources.
Click gateway.networking.k8s.io and view the GatewayClass resource 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.yaml file.
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
Create a gateway.yaml file.
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 path prefix matching - 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 routing rules.
kubectl apply -f gateway.yamlAfter about 2 minutes, 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
You can use the filter feature in HTTPRoute to 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.yaml file.
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 path prefix matching - 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 deployment, when you access the go-httpbin application using thefilter.ingress.topdomain name, themy-header: foorequest header is 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 weights
You can set weights for multiple backend services to split requests based on traffic.
Create an nginx.yaml file.
The preceding file deploys two NGINX applications. The
old-nginxservice returns the"old"string, and thenew-nginxservice returns the"new"string. The deployed resources are placed in thedefaultnamespace.Create an httproute-weight.yaml file.
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 path prefix matching - path: type: PathPrefix value: / backendRefs: # Set the backends and their corresponding weights. The weights are not percentages and do not need to sum 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 100In this routing rule, the
old-nginxandnew-nginxservices are assigned the same weight. Therefore, traffic is distributed to thenew-nginxandold-nginxservices at a 1:1 ratio.Deploy the application and 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 shows that traffic is distributed to 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 on the Gateway resource.
Create a self-signed certificate for the
ingress.tapdomain name.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.yaml file 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, 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 ---The output indicates that the certificate is configured and active.
NoteYou can run
curl -H "Host: demo.ingress.top" -k https://${ALB_DOMAIN}/versionto access the application. The expected output is the same as the output in the Test access to the application step.