DEV Community

Kohei Kawata
Kohei Kawata

Posted on

Deployment pipeline of Application Gateway with App Service

Summary

In this article, I would share problems I faced when deploying and configuring Azure Application Gateway and App Service. At this point, I have not solved problems of App Service redirection for HTTP protocol, but I was able to successfully build it for HTTPS. The sample code is here network-sample-app.

TOC

HTTP

Context

I was trying to build a sample template with Web App and Application Gateway using azure-quickstart-templates web-app-with-app-gateway-v2.

  • Public IP DNS: kawatawebapp-evrlkrxuhtnti.japaneast.cloudapp.azure.com
  • App Service endpoint: kawatawebapp-evrlkrxuhtnti.azurewebsites.net
  • Frontend protocol: HTTP
  • Backend protocol: HTTP
  • Backend inbound is through Service Endpoint from Virtual Network subnet to App Service

Image description

Problem

At first, it looks working well. I can see the default App Service view through a browser.

Before API code deployment
Image description

However, whe I deployed a sample .NET Web API with a GET request route api/travelplan, it does not work. The browser redirects the response and showed 403 Forbidden status code.

Request to .japaneast.cloudapp.azure.com/api/travelplan
Image description

Response from .azurewebsites.net/api/travelplan
Image description

Cause

The domain name of original request is .cloudapp.azure.com but a redirection of App Service sets .azurewebsites.net in the location header. This is what a Microsoft official documentation Troubleshoot App Service issues in Application Gateway explains.

Image description

Workaround failed

In the official documentation, I found two workarounds.

  • Rewrite the location header
  • Use a custom domain name

I do not have my own domain name, and I tried the first one that rewrites the location header. Application Gateway Rewrite configuration is added like below.

ARM template

"rewriteRuleSets": [
  {
    "name": "rewriteLocationHeader",
    "properties": {
      "rewriteRules": [
        {
          "ruleSequence": 100,
          "conditions": [
              {
                  "variable": "http_resp_Location",
                  "pattern": "(https?):\\/\\/.*azurewebsites\\.net(.*)$",
                  "ignoreCase": true
              }
          ],
          "name": "NewRewrite",
          "actionSet": {
              "responseHeaderConfigurations": [
                  {
                      "headerName": "Location",
                      "headerValue": "{http_resp_Location_1}://kawatawebapp-evrlkrxuhtnti.japaneast.cloudapp.azure.com{http_resp_Location_2}"
                  }
              ]
          }
        }
      ]
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

It keeps the original domain name .cloudapp.azure.com in the response header, but it does not respond and got request timeout.

Image description

HTTPS

Acutally, I have not found a solution for the issue above yet, but I tried SSL with Key Vault to see if it works. A self-signed certificate is stored in the Key Vault and Application Gateway retrieves it for SSL communication. The code is in thie respository network-sample-app.

Image description

Probe problem

This SSL configuration works, but sometimes I faced errors of 502 Bad Gateway or 404 Not Found. I looked through the problem and found this happens because of Application Gateway Probe configuration, probe path "/". In the beginning, I set up the configuration below.

ARM template

"probes": [
  {
    "Name": "BackendProbe",
    "properties": {
      "Protocol": "Https",
      "Path": "/",
      "Interval": 30,
      "Timeout": 10,
      "UnhealthyThreshold": 3,
      "MinServers": 0,
      "PickHostNameFromBackendHttpSettings": true
    }
  }
]
Enter fullscreen mode Exit fullscreen mode
  • Before code deploy

Image description

  • After code deploy

Image description

Probe cause

According to the Microsoft documentation Application Gateway health monitoring overview, Azure Application Gateway automatically removes any resource considered unhealthy from the pool. This sample API does not have the root path and showed errors.

Image description

Probe solution

So I put the code below so the custom probe works correctly with the path /api/travelplan after the code deployment.

"probes": [
  {
    "Name": "BackendProbe",
    "properties": {
      "Protocol": "Https",
      "Path": "/api/travelplan",
      "Interval": 30,
      "Timeout": 10,
      "UnhealthyThreshold": 3,
      "MinServers": 0,
      "PickHostNameFromBackendHttpSettings": true
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

Finally, it works.

Image description

Below is the pattern table what response you receive depending on probe path, code deployment, request route.

Code Not deployed Deployed Deployed
Request route / / /api/travelplan
Probe path "/" 200 502 502
Probe path "/api/travelplan" 502 404 200

In the code sample, I use "/health" route path for the custom probe. You need to change the code something like below.

Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddHealthChecks();
}
Enter fullscreen mode Exit fullscreen mode
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    ...

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapHealthChecks("/health");
    });
}
Enter fullscreen mode Exit fullscreen mode

ARM template

{
  "type": "Microsoft.Web/sites",

  ...

  "properties": {
    "siteConfig": {
      "healthCheckPath": "/health"
    }
  }
}
Enter fullscreen mode Exit fullscreen mode
"probes": [
  {
    "Name": "BackendProbe",
    "properties": {
      "Protocol": "Https",
      "Path": "/health",
      "Interval": 30,
      "Timeout": 10,
      "UnhealthyThreshold": 3,
      "MinServers": 0,
      "PickHostNameFromBackendHttpSettings": true
    }
  }
]
Enter fullscreen mode Exit fullscreen mode

Top comments (0)