skip to Main Content

Hi I am currently trying to build https://learn.microsoft.com/en-us/azure/architecture/web-apps/app-service/architectures/baseline-zone-redundant in terraform but i keep running on this problem where the application gateway can’t resolve the private dns name of the private endpoint.
the nsgs are not the problem since the I opened all there ports for debugging purposes.

I tried creating a private dns a record or adding a dns resolver but it didn’t work

#* Network
resource "azurerm_virtual_network" "the_network" {
  name                = module.naming.virtual_network.name
  location            = local.location
  resource_group_name = azurerm_resource_group.the_group.name
  address_space       = [local.vnet_prefixe]
  
  tags = {
    environment = "${terraform.workspace}"
  }
}
#* Subnets
resource "azurerm_subnet" "Application_Gateway_Subnet" {
  name                 = "Application_Gateway_Subnet"
  resource_group_name  = azurerm_resource_group.the_group.name
  virtual_network_name = azurerm_virtual_network.the_network.name
  address_prefixes     = [local.gateway_subnet_prefix]
}

resource "azurerm_subnet" "app_service_integration_subnet" {
  name                 = "app_service_integration_subnet"
  resource_group_name  = azurerm_resource_group.the_group.name
  virtual_network_name = azurerm_virtual_network.the_network.name
  address_prefixes     = [local.app_service_integration_subnet_prefix]
  delegation {
    name = "webapp"

    service_delegation {
      name    = "Microsoft.Web/serverFarms"
      actions = ["Microsoft.Network/virtualNetworks/subnets/action"]
    }
  }
}

resource "azurerm_subnet" "private_endpoints_subnet" {
  name                                      = "private_endpoints_subnet"
  resource_group_name                       = azurerm_resource_group.the_group.name
  virtual_network_name                      = azurerm_virtual_network.the_network.name
  address_prefixes                          = [local.private_endpoints_subnet_prefix]
  service_endpoints = ["Microsoft.Web"]
}
resource "azurerm_application_gateway" "network" {
  name                = module.naming.application_gateway.name
  resource_group_name = azurerm_resource_group.the_group.name
  location            = local.location

  sku {
    name     = "Standard_v2"
    tier     = "Standard_v2"
    capacity = 2
  }

  gateway_ip_configuration {
    name      = "my-gateway-ip-configuration"
    subnet_id = azurerm_subnet.Application_Gateway_Subnet.id
  }

  frontend_port {
    name = local.frontend_port_name
    port = 80
  }

  frontend_ip_configuration {
    name                 = local.frontend_ip_configuration_name
    public_ip_address_id = azurerm_public_ip.the_public_ip.id
  }

  backend_address_pool {
    name         = local.backend_address_pool_name
    fqdns = [module.the_web_app.endpoint_fqdn]
  }

  backend_http_settings {
    name                  = local.http_setting_name
    cookie_based_affinity = "Disabled"
    path                  = "/*"
    port                  = 80
    protocol              = "Http"
    request_timeout       = 60
  }

  http_listener {
    name                           = local.listener_name
    frontend_ip_configuration_name = local.frontend_ip_configuration_name
    frontend_port_name             = local.frontend_port_name
    protocol                       = "Http"
  }

  request_routing_rule {
    name                       = local.request_routing_rule_name
    priority                   = 9
    rule_type                  = "Basic"
    http_listener_name         = local.listener_name
    backend_address_pool_name  = local.backend_address_pool_name
    backend_http_settings_name = local.http_setting_name
  }
}
resource "azurerm_service_plan" "the_plan" {
  name                = module.naming.app_service_plan.name
  resource_group_name = var.resource_group_name
  location            = var.location
  os_type             = "Linux"
  sku_name            = "P1v2"
}

resource "azurerm_linux_web_app" "the_app" {
  name                          = module.naming.app_service.name_unique
  resource_group_name           = var.resource_group_name
  location                      = var.location
  service_plan_id               = azurerm_service_plan.the_plan.id
  public_network_access_enabled = false

  site_config {
    application_stack {
      dotnet_version = "6.0"
    }
  }
}

# private endpoints
resource "azurerm_private_dns_zone" "dnsprivatezone" {
  name                = "privatelink.azurewebsites.net"
  resource_group_name = var.resource_group_name
}

resource "azurerm_private_dns_zone_virtual_network_link" "dnszonelink" {
  name                  = "dnszonelink"
  resource_group_name   = var.resource_group_name
  private_dns_zone_name = azurerm_private_dns_zone.dnsprivatezone.name
  virtual_network_id    = var.vnet_id
}

resource "azurerm_private_endpoint" "privateendpoint" {
  name                = "${module.naming.private_endpoint.name}-webapp"
  location            = var.location
  resource_group_name = var.resource_group_name
  subnet_id           = var.private_endpoints_subnet_id

  private_service_connection {
    name                           = "privateendpointconnection"
    private_connection_resource_id = azurerm_linux_web_app.the_app.id
    subresource_names              = ["sites"]
    is_manual_connection           = false
  }

  private_dns_zone_group {
    name                 = "web-app-dns-zone-group"
    private_dns_zone_ids = [azurerm_private_dns_zone.dnsprivatezone.id]
  }
}

update: using a vm in the vnet i can resolve the private endpoint dns using the wireserver but can’t do the same using the application gateway.

2

Answers


  1. It appears you are facing challenges with Microsoft Azure Application Gateway not resolving the private DNS name of a private endpoint in your Terraform deployment. To address this:

    1. DNS Configuration: Verify the private DNS zone settings and ensure correct registration of the private endpoint.

    2. Network Security Groups (NSGs): Confirm that NSGs allow necessary traffic between the Application Gateway and private endpoint subnets.

    3. Diagnostic Logs: Enable detailed diagnostic logs for the Application Gateway to identify potential issues.

    4. Azure DNS: Ensure your virtual network is configured to use Azure DNS for name resolution.

    For precise assistance, consult Azure documentation or consider seeking support from Azure experts.

    Login or Signup to reply.
  2. Implementing a Highly Available, Zone-Redundant Azure Web Application Architecture with Private Endpoint DNS Resolution using Terraform

    To achieve DNS resolution for your Azure App Service with an Application Gateway in a Terraform-managed infrastructure, you need to focus on setting up the private endpoint of the App Service correctly through the Application Gateway. This example will show you how to create the required Azure resources such as the Application Gateway, Virtual Network, Private DNS Zone, and App Service, and how to link them properly for DNS resolution.

    My configuration:

    provider "azurerm" {
      features {}
    }
    
    data "azurerm_resource_group" "example" {
      name     = "VkProject-test-rg"
    }
    
    resource "azurerm_virtual_network" "example" {
      name                = "testvk-vnet"
      address_space       = ["10.0.0.0/16"]
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
    }
    
    resource "azurerm_subnet" "example_gateway" {
      name                 = "testvkGatewaySubnet"
      resource_group_name  = data.azurerm_resource_group.example.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.1.0/24"]
    }
    
    resource "azurerm_subnet" "example_appservice" {
      name                 = "testvkAppServiceSubnet"
      resource_group_name  = data.azurerm_resource_group.example.name
      virtual_network_name = azurerm_virtual_network.example.name
      address_prefixes     = ["10.0.2.0/24"]
      service_endpoints    = ["Microsoft.Web"]
    }
    
    
    resource "azurerm_public_ip" "example" {
      name                = "testvkPublicIP"
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
      allocation_method   = "Static"
      sku                 = "Standard"
    }
    
    resource "azurerm_application_gateway" "example" {
      name                = "testvkAppGateway"
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
      sku {
        name     = "Standard_v2"
        tier     = "Standard_v2"
        capacity = 2
      }
    
      gateway_ip_configuration {
        name      = "gatewayIpConfig"
        subnet_id = azurerm_subnet.example_gateway.id
      }
    
      frontend_port {
        name = "httpPort"
        port = 80
      }
    
      frontend_ip_configuration {
        name                 = "frontendIpConfig"
        public_ip_address_id = azurerm_public_ip.example.id
      }
    
      backend_address_pool {
        name = "backendPool"
      }
    
      http_listener {
        name                           = "listener"
        frontend_ip_configuration_name = "frontendIpConfig"
        frontend_port_name             = "httpPort"
        protocol                       = "Http"
      }
    
      request_routing_rule {
        name                       = "rule1"
        rule_type                  = "Basic"
        http_listener_name         = "listener"
        backend_address_pool_name  = "backendPool"
        backend_http_settings_name = "httpSettings"
        priority = 100
      }
    
      backend_http_settings {
        name                  = "httpSettings"
        cookie_based_affinity = "Disabled"
        port                  = 80
        protocol              = "Http"
        request_timeout       = 20
      }
    }
    
    resource "azurerm_private_dns_zone" "example" {
      name                = "privatelink.azurewebsites.net"
      resource_group_name = data.azurerm_resource_group.example.name
    }
    
    resource "azurerm_private_dns_zone_virtual_network_link" "example" {
      name                  = "testvk-dns-zone-link"
      resource_group_name   = data.azurerm_resource_group.example.name
      private_dns_zone_name = azurerm_private_dns_zone.example.name
      virtual_network_id    = azurerm_virtual_network.example.id
    }
    
    
    resource "azurerm_service_plan" "example" {
      name                = "testvkAppServicePlan"
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
      os_type             = "Linux"
      sku_name            = "P1v2"
    }
    
    resource "azurerm_app_service" "example" {
      name                = "testvkeAppService"
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
      app_service_plan_id = azurerm_service_plan.example.id
    
      site_config {
        dotnet_framework_version = "v4.0"
      }
    }
    
    
    resource "azurerm_private_endpoint" "example" {
      name                = "testvkAppServicePrivateEndpoint"
      location            = data.azurerm_resource_group.example.location
      resource_group_name = data.azurerm_resource_group.example.name
      subnet_id           = azurerm_subnet.example_appservice.id
    
      private_service_connection {
        name                           = "testvkConnection"
        private_connection_resource_id = azurerm_app_service.example.id
        is_manual_connection           = false
        subresource_names              = ["sites"]
      }
    
      private_dns_zone_group {
        name                 = "testvkPdzg"
        private_dns_zone_ids = [azurerm_private_dns_zone.example.id]
      }
    }
    

    Deployment succeeded:

    enter image description here

    enter image description here

    enter image description here

    enter image description here

    This setup allows the Application Gateway to securely send traffic to the Azure App Service over a private connection, solving the main problem of DNS resolution error for the private endpoint inside the Application Gateway. By connecting the private DNS zone to the virtual network and creating a private endpoint for the App Service, DNS queries for the App Service are properly resolved, enabling the Application Gateway to access the App Service without making it publicly available.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search