Deploying Applications with Azure App Service
azure

Deploying Applications with Azure App Service

Learn how to deploy and manage web applications using Azure App Service. Covers deployment slots, scaling, monitoring, and continuous deployment.

March 3, 2024
Technical Writer
12 min read

Mastering Azure App Service for Production Deployments

TL;DR: Azure App Service is a fully managed Platform-as-a-Service (PaaS) offering for deploying and scaling web applications. This guide delves into advanced configurations, deployment strategies, and operational best practices essential for experienced engineers managing production workloads on App Service, covering topics from robust deployment pipelines and effective scaling to security hardening and cost optimization.


Introduction to Azure App Service

Azure App Service is a managed compute platform designed for hosting web applications, REST APIs, and mobile backends. It abstracts away the underlying infrastructure, allowing development teams to focus on application logic and delivery. This document targets engineers already familiar with the basic concepts of App Service and aims to provide detailed guidance on its advanced features and operational considerations for production environments.


Core Concepts and Configuration

App Service Plans: The Foundation of Hosting

An App Service plan defines a set of compute resources for your web apps. The SKU (Stock Keeping Unit) determines the pricing tier, performance, and features available.

  • Tiering: From
    Free
    /
    Shared
    for development/testing to
    Basic
    ,
    Standard
    ,
    Premium
    , and
    Isolated
    for production workloads, each tier offers distinct CPU, memory, storage, and feature sets (e.g., VNet integration, custom domains, SSL certificates).
  • Scaling: Plans can be scaled vertically (changing SKU) or horizontally (increasing instance count).

Example: Creating a Production-Ready Plan (Premium V3)

# Create a resource group if it doesn't exist az group create --name myProductionResourceGroup --location eastus # Create a Premium V3 App Service plan for higher performance and features az appservice plan create \ --name myPremiumAppServicePlan \ --resource-group myProductionResourceGroup \ --sku P1v3 \ --is-linux \ --number-of-workers 1 # Start with one instance, scale up as needed

Application Settings and Connection Strings

Application settings are environment variables accessible within your application. Connection strings are specifically formatted for database or other service credentials.

Best Practice: Do not hardcode secrets. Use Azure Key Vault references for sensitive information.

Example: Referencing Key Vault for a Database Connection String

Instead of storing the direct connection string:

{ "appSettings": [ { "name": "DATABASE_URL", "value": "your-secret-connection-string" } ] }

Use a Key Vault reference:

  1. Store Secret in Key Vault:

    • Create a Key Vault.
    • Add your connection string as a secret.
  2. Grant App Service Managed Identity Access:

    • Enable System-assigned Managed Identity for your App Service.
    • Grant the managed identity
      Get
      and
      List
      permissions on the Key Vault secret.
  3. Configure App Setting in App Service:

    • Add an App Setting in your App Service's configuration:
      • Name:
        DATABASE_URL
      • Value:
        @Microsoft.KeyVault(SecretUri=https://your-key-vault-name.vault.azure.net/secrets/your-secret-name/your-secret-version)

    This configuration injects the secret directly into the environment variable at runtime.


Advanced Deployment Strategies

Deployment Slots for Zero-Downtime Deployments

Deployment slots are live environments that can host application versions. They are invaluable for phased rollouts and rollback capabilities.

  • Staging Slot: Deploy new code to a non-production slot (e.g.,
    staging
    ).
  • Testing: Perform smoke tests, integration tests, and UAT in the
    staging
    slot.
  • Swap: Once validated, perform a "swap" operation. This is an instantaneous, zero-downtime process where the
    staging
    slot's content replaces the production slot's content. The previous production slot then becomes the new
    staging
    slot, ready for the next deployment.

Example: Managing Slots and Auto-Swap

# Ensure your web app exists (replace with your app name and resource group) WEB_APP_NAME="myWebApp" RESOURCE_GROUP="myProductionResourceGroup" PLAN_NAME="myPremiumAppServicePlan" # Create a staging slot az webapp deployment slot create \ --name $WEB_APP_NAME \ --resource-group $RESOURCE_GROUP \ --slot staging # Configure auto-swap from staging to production # This automatically swaps the slot whenever new code is deployed to 'staging' az webapp deployment slot auto-swap \ --name $WEB_APP_NAME \ --resource-group $RESOURCE_GROUP \ --slot staging \ --target-slot production # Manual swap if auto-swap is not desired # az webapp deployment slot swap \ # --name $WEB_APP_NAME \ # --resource-group $RESOURCE_GROUP \ # --slot staging \ # --target-slot production

Slot Settings: Certain settings (like connection strings for databases not being deployed) should remain fixed to the production slot during a swap. These are configured as "sticky" settings.

{ "slotConfigNames": { "connectionStringSettings": [ "MyDatabaseConnectionString" ], "appSettingNames": [ "LOGGING_LEVEL", "FEATURE_FLAG_NEW_UI" ] } }

To apply these, use

az webapp config slot set --slot staging --connection-string-names "MyDatabaseConnectionString" --app-setting-names "LOGGING_LEVEL" "FEATURE_FLAG_NEW_UI"
and then when you swap, these settings will remain on production.


Scalability and Performance Tuning

Auto-Scaling: Reactive and Scheduled

App Service offers both reactive (metric-driven) and scheduled auto-scaling.

  • Metric-Driven Scaling: Scales based on real-time performance metrics like CPU, memory, HTTP queue length.
  • Scheduled Scaling: Adjusts instance count based on predictable traffic patterns (e.g., scale up during business hours, scale down at night).

Example: Rule-Based Scaling for High Load

This example scales up when CPU usage averages over 80% for 15 minutes, and scales down after 30 minutes of lower usage.

{ "properties": { "enabled": true, "scalingRules": [ { "name": "ScaleUpOnCpu", "description": "Scale up when CPU is high", "action": { "type": "ScaleOut", "value": "1", "cooldown": "PT15M" }, "condition": { "dataSource": "Microsoft.Azure.Monitoring.PastMetric", "metricName": "CpuPercentage", "metricNamespace": "", "aggregationType": "Average", "timeGrain": "PT1M", "timeWindow": "PT15M", "operator": "GreaterThan", "threshold": 80 } }, { "name": "ScaleDownOnLowCpu", "description": "Scale down when CPU is consistently low", "action": { "type": "ScaleIn", "value": "1", "cooldown": "PT30M" }, "condition": { "dataSource": "Microsoft.Azure.Monitoring.PastMetric", "metricName": "CpuPercentage", "metricNamespace": "", "aggregationType": "Average", "timeGrain": "PT1M", "timeWindow": "PT30M", "operator": "LessThan", "threshold": 20 } } ], "targetResourceUri": "[resourceId('Microsoft.Web/serverfarms', 'myPremiumAppServicePlan')]", "defaultScale": { "defaultCapacity": { "minimum": 1, "maximum": 10 }, "defaultScaleOutEngine": { "capacity": { "minimum": 1, "maximum": 10 }, "interval": "PT5M" } } } }

This JSON would be applied via the Azure CLI:

az monitor autoscale create \ --resource-group myProductionResourceGroup \ --resource-name myPremiumAppServicePlan \ --min-count 1 \ --max-count 10 \ --count 1 \ --scale-percentage-cpu-add 1 80 15 \ --scale-percentage-cpu-remove 1 20 30

Application Performance Management (APM)

Integrate with Azure Application Insights for deep insights into application behavior, performance bottlenecks, and exceptions.

Example: Enabling Application Insights and Configuring Diagnostic Settings

# Get the Instrumentation Key for your existing Application Insights resource APPINSIGHTS_INSTRUMENTATION_KEY=$(az resource show --name my-app-insights-resource --resource-group myResourceGroup --resource-type "Microsoft.Insights/components" --query "properties.instrumentationKey" -o tsv) # Set the Application Insights instrumentation key as an App Setting az webapp config appsettings set \ --name $WEB_APP_NAME \ --resource-group $RESOURCE_GROUP \ --settings APPINSIGHTS_INSTRUMENTATIONKEY=$APPINSIGHTS_INSTRUMENTATION_KEY # Configure diagnostic settings to send logs and metrics to a Log Analytics Workspace # Assuming you have a Log Analytics Workspace named 'myLogAnalyticsWorkspace' in 'myProductionResourceGroup' LOG_ANALYTICS_WORKSPACE_ID=$(az monitor log-analytics workspace show \ --name myLogAnalyticsWorkspace \ --resource-group myProductionResourceGroup \ --query "id" -o tsv) az monitor diagnostic-settings create \ --name myWebAppDiagnostics \ --resource $WEB_APP_NAME \ --resource-group $RESOURCE_GROUP \ --workspace $LOG_ANALYTICS_WORKSPACE_ID \ --logs '[{"category": "AppServiceHTTPLogs", "enabled": true}, {"category": "AppServiceAppLogs", "enabled": true}]' \ --metrics '[{"category": "AllMetrics", "enabled": true}]'

Security Hardening and Best Practices

Network Security

  • VNet Integration: For backend access to Azure services or on-premises resources securely.
  • Private Endpoints: For secure, private access to your App Service from your VNet.
  • IP Restrictions: Control inbound access by allowing/denying specific IP addresses or ranges.
  • Access Restrictions: For App Service management plane access.

Authentication and Authorization

  • App Service Authentication: Integrate with Azure AD, Microsoft Accounts, social providers (e.g., Google, Facebook) to secure your application's front-end.
  • Managed Identities: Use system-assigned or user-assigned managed identities for your App Service to authenticate to other Azure services (Key Vault, Storage, SQL Database) without managing credentials.
  • RBAC: Apply the principle of least privilege for managing App Service resources themselves.

SSL/TLS Configuration

  • HTTPS Only: Enforce HTTPS by setting
    HTTPSOnly = true
    in the App Service configuration.
  • TLS Versions: Configure the minimum TLS version to
    1.2
    for modern security standards.
  • Managed Certificates: Utilize Azure's free managed certificates for custom domains.

Continuous Integration and Continuous Deployment (CI/CD)

Advanced Deployment Options

  • Azure DevOps Pipelines: Comprehensive CI/CD solution with robust build, test, and release capabilities.
  • GitHub Actions: Tightly integrated with GitHub repositories, offering a declarative way to define workflows.
  • Container Registry Integration: Deploy containerized applications directly from Azure Container Registry (ACR) or Docker Hub.
  • Web Deploy/Zip Deploy: Traditional deployment methods for code-based applications.
  • Kudu API: For advanced scripting and deployment automation.

Example: GitHub Actions Workflow for Deployment to a Slot

This example deploys to the

staging
slot first, then manually swaps to production after a successful build and test.

name: Deploy to Azure App Service (with Slot Swap) on: push: branches: - main env: AZURE_WEBAPP_NAME: 'myWebApp' # Replace with your app name AZURE_RESOURCE_GROUP: 'myProductionResourceGroup' # Replace with your resource group AZURE_WEBAPP_PACKAGE_PATH: '.' # Path to app artifacts, '.' for root NODE_VERSION: '18.x' # Specify your Node.js version jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' - name: Install dependencies run: npm ci - name: Build application run: npm run build - name: Run unit tests run: npm test # Add your testing commands here. If tests fail, the job will stop. # Consider deploying to staging and running integration tests in a separate job. - name: Upload build artifacts uses: actions/upload-artifact@v4 with: name: webapp-package path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }} deploy-to-staging: runs-on: ubuntu-latest needs: build-and-test steps: - name: Download build artifacts uses: actions/download-artifact@v4 with: name: webapp-package path: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }} - name: Deploy to Azure Web App staging slot uses: azure/webapps-deploy@v2 with: app-name: ${{ env.AZURE_WEBAPP_NAME }} resource-group: ${{ env.AZURE_RESOURCE_GROUP }} slot-name: 'staging' # Deploy to staging slot package: ${{ env.AZURE_WEBAPP_PACKAGE_PATH }} publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }} manual-swap-to-production: runs-on: ubuntu-latest needs: deploy-to-staging # This job requires manual approval before executing. # You can add environments and approvals in GitHub Actions. steps: - name: Swap staging slot to production uses: azure/powershell@v1 with: azcliversion: 2.53.0 # Or latest inline: | az webapp deployment slot swap --name ${{ env.AZURE_WEBAPP_NAME }} --resource-group ${{ env.AZURE_RESOURCE_GROUP }} --slot staging --target-slot production --action swap

Note: Replace placeholders and ensure

AZURE_WEBAPP_PUBLISH_PROFILE
is set as a GitHub secret. Manual approval steps can be integrated into more complex workflows.


Operational Management and Troubleshooting

Monitoring and Alerting

  • Metrics: Utilize Azure Monitor for key metrics (CPU, Memory, Request Count, Response Time, HTTP Errors).
  • Logs: Collect application logs, HTTP logs, and diagnostic dumps. Send them to a Log Analytics workspace for advanced querying and analysis.
  • Alerts: Configure Azure Monitor Alerts based on thresholds of metrics or log query results to proactively notify engineering teams of issues.

Troubleshooting Common Issues

  • Application Crashes: Check
    Dumps
    tab in App Service diagnostics, review Application Insights exceptions, and analyze application logs.
  • Slow Performance: Analyze traces in Application Insights, check CPU/Memory usage in Azure Monitor, examine slow query logs for database interactions.
  • Deployment Failures: Review build and deployment logs in your CI/CD system, verify dependencies and configuration consistency between slots.
  • Configuration Errors: Ensure application settings and connection strings are correctly applied, especially after slot swaps.

Cost Management

  • Right-Sizing: Regularly review the App Service Plan SKU and instance count. Scale down during off-peak hours or when demand is low.
  • Auto-Shutdown: For non-production environments, configure auto-shutdown.
  • Reserved Instances: For significant, long-term commitments, consider Azure Reserved Virtual Machine Instances for App Service plans to reduce costs.
  • Tier Selection: Choose the lowest SKU that meets performance and feature requirements.
    Standard
    or
    Premium
    tiers are generally recommended for production.

Example: Scaling Down During Off-Peak Hours (Scheduled)

This is typically configured via a scheduled auto-scale rule or a separate script/automation that modifies the

numberOfWorkers
or SKU.

# Example using CLI to manually scale down (can be automated) az webapp scale \ --resource-group myProductionResourceGroup \ --name myWebApp \ --count 1 # Scale down to 1 instance

When Not to Use Azure App Service

While powerful, App Service might not be the ideal choice if:

  • Full Control Over OS is Required: You need to install custom agents, perform low-level OS tuning, or have root/administrator access to the underlying servers. Consider Azure Virtual Machines or Azure Kubernetes Service (AKS).
  • Highly Specialized Workloads: Your application has very specific runtime requirements or dependencies that are difficult to package or configure within the App Service environment (e.g., specific HPC workloads, legacy applications requiring deep OS integration).
  • Cost Sensitivity for Very Low Throughput: For extremely low-traffic applications where even the smallest
    Basic
    or
    Standard
    tier is too expensive, consider alternatives like Azure Functions (for event-driven or bursty workloads) or static web hosting for static content.
  • Complex Orchestration Needs: While App Service supports containers, managing complex microservice orchestration, service discovery, and inter-service communication at scale might be more efficiently handled by AKS.

Decision Checklist

  • Application Type: Is it a web app, API, or mobile backend?
  • Runtime Requirements: What programming languages, frameworks, and dependencies are needed?
  • Scalability Needs: What are the expected traffic patterns? Are there peak loads?
  • Downtime Tolerance: Is zero-downtime deployment critical?
  • Security Requirements: Are VNet integration, private endpoints, or specific authentication methods required?
  • CI/CD Maturity: Does an existing CI/CD pipeline need integration?
  • Monitoring and Logging Strategy: What level of observability is needed?
  • Budget Constraints: What is the acceptable cost range?
  • Team Expertise: What is the team's familiarity with Azure PaaS offerings?

By carefully considering these points, engineers can effectively leverage Azure App Service for robust, scalable, and secure application deployments.

azure
app-service
web-apps
paas