|
| 1 | +--- |
| 2 | +title: WebSocket protocol and Azure Application Gateway for Containers - Gateway API |
| 3 | +description: Learn how to send a WebSocket request to a backend target with Application Gateway for Containers. |
| 4 | +services: application gateway |
| 5 | +author: greg-lindsay |
| 6 | +ms.service: azure-appgw-for-containers |
| 7 | +ms.topic: conceptual |
| 8 | +ms.date: 1/13/2025 |
| 9 | +ms.author: greglin |
| 10 | +--- |
| 11 | + |
| 12 | +# WebSocket request for Azure Application Gateway for Containers - Gateway API |
| 13 | + |
| 14 | +Application Gateway for Containers allows you to leverage WebSocket protocol to connect to backend targets with Application Gateway for Containers. |
| 15 | + |
| 16 | +## Usage details |
| 17 | + |
| 18 | +WebSocket protocol has no specific implementation with Gateway API for configuration or enablement. However, you can use this how-to guide to understand the end-to-end configuration and proper health probe configuration. This ensures WebSocket requests are properly handled by a backend service. |
| 19 | + |
| 20 | +## Prerequisites |
| 21 | + |
| 22 | +1. If following the BYO deployment strategy, ensure you set up your Application Gateway for Containers resources and [ALB Controller](quickstart-deploy-application-gateway-for-containers-alb-controller.md). |
| 23 | +2. If following the ALB managed deployment strategy, ensure you provision your [ALB Controller](quickstart-deploy-application-gateway-for-containers-alb-controller.md) and provision the Application Gateway for Containers resources via the [ApplicationLoadBalancer custom resource](quickstart-create-application-gateway-for-containers-managed-by-alb-controller.md). |
| 24 | +3. Deploy sample HTTP and WebSocket application: |
| 25 | + |
| 26 | + Apply the following deployment.yaml file on your cluster to create a sample web application to demonstrate WebSocket support. |
| 27 | + |
| 28 | + ```bash |
| 29 | + kubectl apply -f https://learn.microsoft.com/azure/application-gateway/for-containers/examples/websocket-scenario/deployment.yaml |
| 30 | + ``` |
| 31 | + |
| 32 | + This command creates the following on your cluster: |
| 33 | + |
| 34 | + - A namespace called `test-infra` |
| 35 | + - One service called `websocket-backend` in the `test-infra` namespace |
| 36 | + - One deployment called `websocket-backend` in the `test-infra` namespace |
| 37 | + |
| 38 | +## Deploy the required Gateway API resources |
| 39 | + |
| 40 | +# [ALB managed deployment](#tab/alb-managed) |
| 41 | + |
| 42 | +1. Create a Gateway |
| 43 | + |
| 44 | + ```bash |
| 45 | + kubectl apply -f - <<EOF |
| 46 | + apiVersion: gateway.networking.k8s.io/v1 |
| 47 | + kind: Gateway |
| 48 | + metadata: |
| 49 | + name: gateway-01 |
| 50 | + namespace: test-infra |
| 51 | + annotations: |
| 52 | + alb.networking.azure.io/alb-namespace: alb-test-infra |
| 53 | + alb.networking.azure.io/alb-name: alb-test |
| 54 | + spec: |
| 55 | + gatewayClassName: azure-alb-external |
| 56 | + listeners: |
| 57 | + - name: http-listener |
| 58 | + port: 80 |
| 59 | + protocol: HTTP |
| 60 | + allowedRoutes: |
| 61 | + namespaces: |
| 62 | + from: Same |
| 63 | + EOF |
| 64 | + ``` |
| 65 | +
|
| 66 | +[!INCLUDE [application-gateway-for-containers-frontend-naming](../../../includes/application-gateway-for-containers-frontend-naming.md)] |
| 67 | +
|
| 68 | +# [Bring your own (BYO) deployment](#tab/byo) |
| 69 | +
|
| 70 | +1. Set the following environment variables |
| 71 | +
|
| 72 | + ```bash |
| 73 | + RESOURCE_GROUP='<resource group name of the Application Gateway For Containers resource>' |
| 74 | + RESOURCE_NAME='alb-test' |
| 75 | +
|
| 76 | + RESOURCE_ID=$(az network alb show --resource-group $RESOURCE_GROUP --name $RESOURCE_NAME --query id -o tsv) |
| 77 | + FRONTEND_NAME='frontend' |
| 78 | + ``` |
| 79 | +
|
| 80 | +2. Create a Gateway |
| 81 | +
|
| 82 | + ```bash |
| 83 | + kubectl apply -f - <<EOF |
| 84 | + apiVersion: gateway.networking.k8s.io/v1 |
| 85 | + kind: Gateway |
| 86 | + metadata: |
| 87 | + name: gateway-01 |
| 88 | + namespace: test-infra |
| 89 | + annotations: |
| 90 | + alb.networking.azure.io/alb-id: $RESOURCE_ID |
| 91 | + spec: |
| 92 | + gatewayClassName: azure-alb-external |
| 93 | + listeners: |
| 94 | + - name: http-listener |
| 95 | + port: 80 |
| 96 | + protocol: HTTP |
| 97 | + allowedRoutes: |
| 98 | + namespaces: |
| 99 | + from: Same |
| 100 | + addresses: |
| 101 | + - type: alb.networking.azure.io/alb-frontend |
| 102 | + value: $FRONTEND_NAME |
| 103 | + EOF |
| 104 | + ``` |
| 105 | +
|
| 106 | +--- |
| 107 | +
|
| 108 | +Once the gateway resource is created, ensure the status is valid, the listener is _Programmed_, and an address is assigned to the gateway. |
| 109 | +
|
| 110 | +```bash |
| 111 | +kubectl get gateway gateway-01 -n test-infra -o yaml |
| 112 | +``` |
| 113 | +
|
| 114 | +Example output of successful gateway creation. |
| 115 | +
|
| 116 | +```yaml |
| 117 | +status: |
| 118 | + addresses: |
| 119 | + - type: Hostname |
| 120 | + value: xxxx.yyyy.alb.azure.com |
| 121 | + conditions: |
| 122 | + - lastTransitionTime: "2023-06-19T21:04:55Z" |
| 123 | + message: Valid Gateway |
| 124 | + observedGeneration: 1 |
| 125 | + reason: Accepted |
| 126 | + status: "True" |
| 127 | + type: Accepted |
| 128 | + - lastTransitionTime: "2023-06-19T21:04:55Z" |
| 129 | + message: Application Gateway For Containers resource has been successfully updated. |
| 130 | + observedGeneration: 1 |
| 131 | + reason: Programmed |
| 132 | + status: "True" |
| 133 | + type: Programmed |
| 134 | + listeners: |
| 135 | + - attachedRoutes: 0 |
| 136 | + conditions: |
| 137 | + - lastTransitionTime: "2023-06-19T21:04:55Z" |
| 138 | + message: "" |
| 139 | + observedGeneration: 1 |
| 140 | + reason: ResolvedRefs |
| 141 | + status: "True" |
| 142 | + type: ResolvedRefs |
| 143 | + - lastTransitionTime: "2023-06-19T21:04:55Z" |
| 144 | + message: Listener is accepted |
| 145 | + observedGeneration: 1 |
| 146 | + reason: Accepted |
| 147 | + status: "True" |
| 148 | + type: Accepted |
| 149 | + - lastTransitionTime: "2023-06-19T21:04:55Z" |
| 150 | + message: Application Gateway For Containers resource has been successfully updated. |
| 151 | + observedGeneration: 1 |
| 152 | + reason: Programmed |
| 153 | + status: "True" |
| 154 | + type: Programmed |
| 155 | + name: https-listener |
| 156 | + supportedKinds: |
| 157 | + - group: gateway.networking.k8s.io |
| 158 | + kind: HTTPRoute |
| 159 | +``` |
| 160 | +
|
| 161 | +Once the gateway is created, create an HTTPRoute resource for `contoso.com`. |
| 162 | +
|
| 163 | +```bash |
| 164 | +kubectl apply -f - <<EOF |
| 165 | +apiVersion: gateway.networking.k8s.io/v1 |
| 166 | +kind: HTTPRoute |
| 167 | +metadata: |
| 168 | + name: websocket-example |
| 169 | + namespace: test-infra |
| 170 | +spec: |
| 171 | + parentRefs: |
| 172 | + - name: gateway-01 |
| 173 | + hostnames: |
| 174 | + - "contoso.com" |
| 175 | + rules: |
| 176 | + - backendRefs: |
| 177 | + - name: websocket-backend |
| 178 | + port: 8080 |
| 179 | +EOF |
| 180 | +``` |
| 181 | + |
| 182 | +When the HTTPRoute resource is created, ensure the HTTPRoute resource shows _Accepted_ and the Application Gateway for Containers resource is _Programmed_. |
| 183 | + |
| 184 | +```bash |
| 185 | +kubectl get httproute websocket-example -n test-infra -o yaml |
| 186 | +``` |
| 187 | + |
| 188 | +Verify the Application Gateway for Containers resource is successfully updated for the HTTPRoute. |
| 189 | + |
| 190 | +```yaml |
| 191 | +status: |
| 192 | + parents: |
| 193 | + - conditions: |
| 194 | + - lastTransitionTime: "2023-06-19T22:18:23Z" |
| 195 | + message: "" |
| 196 | + observedGeneration: 1 |
| 197 | + reason: ResolvedRefs |
| 198 | + status: "True" |
| 199 | + type: ResolvedRefs |
| 200 | + - lastTransitionTime: "2023-06-19T22:18:23Z" |
| 201 | + message: Route is Accepted |
| 202 | + observedGeneration: 1 |
| 203 | + reason: Accepted |
| 204 | + status: "True" |
| 205 | + type: Accepted |
| 206 | + - lastTransitionTime: "2023-06-19T22:18:23Z" |
| 207 | + message: Application Gateway For Containers resource has been successfully updated. |
| 208 | + observedGeneration: 1 |
| 209 | + reason: Programmed |
| 210 | + status: "True" |
| 211 | + type: Programmed |
| 212 | + controllerName: alb.networking.azure.io/alb-controller |
| 213 | + parentRef: |
| 214 | + group: gateway.networking.k8s.io |
| 215 | + kind: Gateway |
| 216 | + name: gateway-01 |
| 217 | + namespace: test-infra |
| 218 | + ``` |
| 219 | + |
| 220 | +For this example, health checks are exposed on the path `/health`. To ensure Application Gateway for Containers can validate the health of this application, define a HealthCheckPolicy resource for the HTTP path of `/health`. |
| 221 | + |
| 222 | +```bash |
| 223 | +kubectl apply -f - <<EOF |
| 224 | +apiVersion: alb.networking.azure.io/v1 |
| 225 | +kind: HealthCheckPolicy |
| 226 | +metadata: |
| 227 | + name: websockets-backend-health-check-policy |
| 228 | + namespace: test-infra |
| 229 | +spec: |
| 230 | + targetRef: |
| 231 | + group: "" |
| 232 | + kind: Service |
| 233 | + name: websocket-backend |
| 234 | + namespace: test-infra |
| 235 | + default: |
| 236 | + interval: 5s |
| 237 | + timeout: 3s |
| 238 | + healthyThreshold: 1 |
| 239 | + unhealthyThreshold: 1 |
| 240 | + http: |
| 241 | + path: /health |
| 242 | +EOF |
| 243 | +``` |
| 244 | + |
| 245 | +When the HealthCheckPolicy resource is created, ensure the HealthCheckPolicy resource shows _Accepted_ and the Application Gateway for Containers resource is _Programmed_. |
| 246 | + |
| 247 | +```bash |
| 248 | +kubectl get httproute websocket-example -n test-infra -o yaml |
| 249 | +``` |
| 250 | + |
| 251 | +Verify the Application Gateway for Containers HealthCheckPolicy is successfully updated. |
| 252 | + |
| 253 | +```yaml |
| 254 | + status: |
| 255 | + conditions: |
| 256 | + - lastTransitionTime: "2024-10-29T16:40:34Z" |
| 257 | + message: Valid HealthCheckPolicy |
| 258 | + observedGeneration: 1 |
| 259 | + reason: Accepted |
| 260 | + status: "True" |
| 261 | + type: Accepted |
| 262 | + ``` |
| 263 | + |
| 264 | +## Test access to the application |
| 265 | + |
| 266 | +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 and resolve its IP address. |
| 267 | +
|
| 268 | +```bash |
| 269 | +fqdn=$(kubectl get gateway gateway-01 -n test-infra -o jsonpath='{.status.addresses[0].value}') |
| 270 | +fqdnIp=$(dig +short $fqdn) |
| 271 | +``` |
| 272 | +
|
| 273 | +Obtain the websocket utility to make a websocket request. For example purposes, the latest version of the utility is downloaded and marked as executable in a linux home directory instead of installed locally on the machine. This enables you to use the utility via Cloud Shell. |
| 274 | +
|
| 275 | +```bash |
| 276 | +wget -O ~/websocat https://github.com/vi/websocat/releases/latest/download/websocat.x86_64-unknown-linux-musl |
| 277 | +chmod a+x ~/websocat |
| 278 | +``` |
| 279 | +
|
| 280 | +Call the websocket utility to make a websocket request. In this example, a chat application is exposed on the path `/chat`, where the application responds back with the text sent. |
| 281 | +
|
| 282 | +```bash |
| 283 | +./websocat -t - --ws-c-uri=ws://contoso.com/chat ws-c:tcp:$fqdnIp:80 |
| 284 | +``` |
| 285 | +
|
| 286 | +Once connected, type `Hello world!!!` |
| 287 | +
|
| 288 | +Via the response we should see the same response: |
| 289 | +
|
| 290 | +``` |
| 291 | +Hello world!!! |
| 292 | +``` |
| 293 | +
|
| 294 | +Use the keystroke combination Control + C to break out of the websocat utility. |
| 295 | +
|
| 296 | +Congratulations, you have installed ALB Controller, deployed a backend application and used the WebSocket protocol to establish a connection to a backend target on Application Gateway for Containers. |
0 commit comments