Trust is earned, not given

A different perspective

2022-03-15 · Projects

DevOps on Azure, part 5: Pipelines and observability — Azure DevOps and App Insights

Part 5from the DevOps on Azure series · 6 parts in all

Part 5: the two loops. Azure gives you a choice of delivery system — Azure DevOps Pipelines (the enterprise workhorse) or GitHub Actions (the same engine we used on AWS) — and one observability product that remains the most integrated in the industry: Application Insights.

The delivery loop, in Azure DevOps

MapleCart's pipeline: build → test → push to Container Registry → deploy to the staging slot → smoke-test → swap. Declarative YAML:

# azure-pipelines.yml (abridged)
trigger: [ main ]
pool: { vmImage: ubuntu-latest }

stages:
- stage: build
  jobs:
  - job: build
    steps:
    - task: Docker@2
      inputs: { command: build, repository: maplecart/web, tags: $(Build.SourceVersion) }
    - task: Docker@2
      inputs: { command: push, containerRegistry: maplecart-acr }   # service connection = identity
    - task: Bash@3
      inputs: { targetType: inline, script: docker run --rm maplecart/web:$(Build.SourceVersion) npm test }

- stage: deploy
  jobs:
  - deployment: staging
    environment: maplecart-staging          # approval gates live here
    strategy:
      runOnce:
        deploy:
          steps:
          - task: AzureWebAppContainer@1
            inputs:
              appName: maplecart-web
              slotName: staging              # deploy to staging first
              imageName: maplecart.azurecr.io/web:$(Build.SourceVersion)
          - task: AzureAppServiceManage@0   # smoke tests passed:
            inputs: { action: 'Swap Slots', webAppName: maplecart-web,
                      sourceSlot: staging }   # warm swap to production

The environment: concept is Azure DevOps' quietly great feature: approvals, branch checks, and deployment history attach to the environment, not the pipeline — compliance gets an audit trail per environment for free.

The feedback loop: Application Insights

One SDK, and your app gets distributed tracing, dependency mapping (which SQL calls, which HTTP calls, how slow), live metrics, and log analytics. The "golden four" come wired:

# ASP.NET Core: two lines at startup, and every HTTP request, SQL query,
# and outbound call is traced end-to-end automatically.
builder.Services.AddApplicationInsightsTelemetry();
# Custom business events are one call away and belong in every feature:
telemetry.TrackEvent("RmaResolved", new Dictionary<string,string> {
    ["device_model"] = model, ["duration_s"] = secs.ToString() });
# Alerts on symptoms, as always - and they land in the same product:
az monitor metrics alert create -g maplecart-rg -n web-5xx \
  --scopes <app-insights-resource-id> \
  --condition "count requests/failed > 10" --window-size 5m --evaluation-frequency 1m \
  --action <action-group-id>

The AWS series made the point that teams install observability backwards (dashboards before alerts, alerts before logs). Azure's counter-argument is that App Insights makes the correct order cheap: traces and dependencies arrive automatically, so the interesting work — the alarms on user-visible symptoms — starts on day one. Availability tests (the canaries) are also built in: a URL test from five Azure regions every five minutes, no Lambda required.

Next: the finale — MapleCart's entire stack in one Terraform configuration, with the App Service slots, private endpoints, identity, and Key Vault from this series all wired together.