URL Rewrite for Azure Application Gateway for Containers - Gateway API
Application Gateway for Containers allows you to rewrite the URL of a client request, including the requests' hostname and/or path. When Application Gateway for Containers initiates the request to the backend target, the request contains the newly rewritten URL to initiate the request.
Usage details
URL Rewrites take advantage of filters as defined by Kubernetes Gateway API.
Background
URL rewrite enables you to translate an incoming request to a different URL when initiated to a backend target.
The following figure illustrates an example of a request destined for contoso.com/shop being rewritten to contoso.com/ecommerce. The request is initiated to the backend target by Application Gateway for Containers:
Prerequisites
If following the BYO deployment strategy, ensure you set up your Application Gateway for Containers resources and ALB Controller.
If following the ALB managed deployment strategy, ensure you provision your ALB Controller and provision the Application Gateway for Containers resources via the ApplicationLoadBalancer custom resource.
Deploy sample HTTP application:
Apply the following deployment.yaml file on your cluster to create a sample web application to demonstrate traffic splitting / weighted round robin support.
kubectl apply -f https://raw.githubusercontent.com/MicrosoftDocs/azure-docs/refs/heads/main/articles/application-gateway/for-containers/examples/traffic-split-scenario/deployment.yaml
This command creates the following on your cluster:
- A namespace called
test-infra
- Two services called
backend-v1
andbackend-v2
in thetest-infra
namespace - Two deployments called
backend-v1
andbackend-v2
in thetest-infra
namespace
- A namespace called
Deploy the required Gateway API resources
Create a Gateway
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: gateway-01 namespace: test-infra annotations: alb.networking.azure.io/alb-namespace: alb-test-infra alb.networking.azure.io/alb-name: alb-test spec: gatewayClassName: azure-alb-external listeners: - name: http-listener port: 80 protocol: HTTP allowedRoutes: namespaces: from: Same EOF
Note
When the ALB Controller creates the Application Gateway for Containers resources in ARM, it'll use the following naming convention for a frontend resource: fe-<8 randomly generated characters>
If you would like to change the name of the frontend created in Azure, consider following the bring your own deployment strategy.
Once the gateway resource is created, ensure the status is valid, the listener is Programmed, and an address is assigned to the gateway.
kubectl get gateway gateway-01 -n test-infra -o yaml
Example output of successful gateway creation.
status:
addresses:
- type: Hostname
value: xxxx.yyyy.alb.azure.com
conditions:
- lastTransitionTime: "2023-06-19T21:04:55Z"
message: Valid Gateway
observedGeneration: 1
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: "2023-06-19T21:04:55Z"
message: Application Gateway For Containers resource has been successfully updated.
observedGeneration: 1
reason: Programmed
status: "True"
type: Programmed
listeners:
- attachedRoutes: 0
conditions:
- lastTransitionTime: "2023-06-19T21:04:55Z"
message: ""
observedGeneration: 1
reason: ResolvedRefs
status: "True"
type: ResolvedRefs
- lastTransitionTime: "2023-06-19T21:04:55Z"
message: Listener is accepted
observedGeneration: 1
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: "2023-06-19T21:04:55Z"
message: Application Gateway For Containers resource has been successfully updated.
observedGeneration: 1
reason: Programmed
status: "True"
type: Programmed
name: https-listener
supportedKinds:
- group: gateway.networking.k8s.io
kind: HTTPRoute
Once the gateway is created, create an HTTPRoute resource for contoso.com
. This example ensures traffic sent to contoso.com/shop
is initiated as contoso.com/ecommerce
to the backend target.
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: rewrite-example
namespace: test-infra
spec:
parentRefs:
- name: gateway-01
hostnames:
- "contoso.com"
rules:
- matches:
- path:
type: PathPrefix
value: /shop
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /ecommerce
backendRefs:
- name: backend-v1
port: 8080
- backendRefs:
- name: backend-v2
port: 8080
EOF
When the HTTPRoute resource is created, ensure the HTTPRoute resource shows Accepted and the Application Gateway for Containers resource is Programmed.
kubectl get httproute rewrite-example -n test-infra -o yaml
Verify the Application Gateway for Containers resource is successfully updated for each HTTPRoute.
status:
parents:
- conditions:
- lastTransitionTime: "2023-06-19T22:18:23Z"
message: ""
observedGeneration: 1
reason: ResolvedRefs
status: "True"
type: ResolvedRefs
- lastTransitionTime: "2023-06-19T22:18:23Z"
message: Route is Accepted
observedGeneration: 1
reason: Accepted
status: "True"
type: Accepted
- lastTransitionTime: "2023-06-19T22:18:23Z"
message: Application Gateway For Containers resource has been successfully updated.
observedGeneration: 1
reason: Programmed
status: "True"
type: Programmed
controllerName: alb.networking.azure.io/alb-controller
parentRef:
group: gateway.networking.k8s.io
kind: Gateway
name: gateway-01
namespace: test-infra
Test access to the application
Now we're ready to send some traffic to our sample application, via the FQDN assigned to the frontend. Use the following command to get the FQDN.
fqdn=$(kubectl get gateway gateway-01 -n test-infra -o jsonpath='{.status.addresses[0].value}')
When you specify the server name indicator using the curl command, contoso.com/shop
should return a response from the backend-v1 service with the requested path to the backend target showing contoso.com/ecommerce
.
fqdnIp=$(dig +short $fqdn)
curl -k --resolve contoso.com:80:$fqdnIp http://contoso.com/shop
Via the response we should see:
{
"path": "/ecommerce",
"host": "contoso.com",
"method": "GET",
"proto": "HTTP/1.1",
"headers": {
"Accept": [
"*/*"
],
"User-Agent": [
"curl/7.81.0"
],
"X-Forwarded-For": [
"xxx.xxx.xxx.xxx"
],
"X-Forwarded-Proto": [
"http"
],
"X-Request-Id": [
"dcd4bcad-ea43-4fb6-948e-a906380dcd6d"
]
},
"namespace": "test-infra",
"ingress": "",
"service": "",
"pod": "backend-v1-5b8fd96959-f59mm"
}
When you specify the server name indicator using the curl command, contoso.com
should return a response from the backend-v2 service.
fqdnIp=$(dig +short $fqdn)
curl -k --resolve contoso.com:80:$fqdnIp http://contoso.com
Via the response we should see:
{
"path": "/",
"host": "contoso.com",
"method": "GET",
"proto": "HTTP/1.1",
"headers": {
"Accept": [
"*/*"
],
"User-Agent": [
"curl/7.81.0"
],
"X-Forwarded-For": [
"xxx.xxx.xxx.xxx"
],
"X-Forwarded-Proto": [
"http"
],
"X-Request-Id": [
"adae8cc1-8030-4d95-9e05-237dd4e3941b"
]
},
"namespace": "test-infra",
"ingress": "",
"service": "",
"pod": "backend-v2-594bd59865-ppv9w"
}
Congratulations, you have installed ALB Controller and deployed a backend application that includes filtering to rewrite the client requested URL. The target on Application Gateway for Containers is ready to receive traffic.