Integrating .NET 8 with Azure Container Apps for Scalable Event‑Driven Workers

Mahmut Sarıkaya 4 dk okuma 5 Görüntülenme 0
Integrating .NET 8 with Azure Container Apps for Scalable Event‑Driven Workers

Conclusion

By marrying .NET 8’s performance, Dapr’s portable pub/sub abstraction, and Azure Container Apps’ serverless scaling, you can build event‑driven workers that handle millions of messages a day with minimal operational overhead. The stack lets developers focus on business logic while the platform automatically provisions compute, balances load, and retries failures.

Start with a local Dapr run, push a container to ACR, and let Azure’s built‑in KEDA scaler do the heavy lifting. The result is a resilient, cost‑effective pipeline ready for any spike in traffic.

Author: Mahmut Sarıkaya — sarikayadev.com

Sources

  • Microsoft Docs – Azure Container Apps overview
  • Dapr Documentation – Pub/Sub building blocks
  • .NET 8 release notes – Performance improvements

Observability: Metrics, Traces, and Logs

When you move from a local Dapr sandbox to Azure Container Apps, visibility into the worker’s health becomes a critical factor. Azure Monitor integrates natively with Container Apps, exposing both platform metrics (CPU, memory, replica count) and custom application metrics emitted through Dapr sidecars. By instrumenting your .NET 8 worker with OpenTelemetry, you can push traces and metrics directly to Azure Monitor or to a dedicated Azure Log Analytics workspace.

Start by adding the OpenTelemetry SDK to your project:

<ItemGroup>
    <PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.6.0" />
    <PackageReference Include="OpenTelemetry.Exporter.AzureMonitor" Version="1.2.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.5.0" />
    <PackageReference Include="OpenTelemetry.Instrumentation.Http" Version="1.5.0" />
</ItemGroup>

In Program.cs, register the exporter and enable activity propagation across the Dapr sidecar:

builder.Services.AddOpenTelemetry()
    .WithTracing(traceBuilder =>
    {
        traceBuilder
            .AddAspNetCoreInstrumentation()
            .AddHttpClientInstrumentation()
            .AddDaprInstrumentation() // provided by Dapr SDK
            .AddAzureMonitorTraceExporter(o =>
            {
                o.ConnectionString = Environment.GetEnvironmentVariable("AZURE_MONITOR_CONNECTION_STRING");
            });
    })
    .WithMetrics(metricBuilder =>
    {
        metricBuilder
            .AddRuntimeInstrumentation()
            .AddHttpClientInstrumentation()
            .AddDaprInstrumentation()
            .AddAzureMonitorMetricExporter(o =>
            {
                o.ConnectionString = Environment.GetEnvironmentVariable("AZURE_MONITOR_CONNECTION_STRING");
            });
    });

Once deployed, you can create Azure Dashboard tiles that display the number of processed messages per second, latency distribution, and error rates. The Dapr sidecar also emits its own health metrics (e.g., dapr_runtime_up), which you can query to detect mis‑configurations before they affect the business flow. Coupled with Azure Application Insights alerts, you get a full‑stack observability solution that works across scaling events, whether KEDA adds or removes replicas.

CI/CD Automation with GitHub Actions and Azure Container Apps

Manual container pushes are fine for experiments, but production workloads benefit from a repeatable pipeline. GitHub Actions provides a seamless way to build, test, push the image to Azure Container Registry (ACR), and finally update the Container Apps revision. The workflow below demonstrates a three‑stage pipeline: build, security scan, and deploy.

name: CI/CD for .NET 8 Worker

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Set up .NET
        uses: actions/setup-dotnet@v3
        with:
          dotnet-version: '8.0.x'
      - name: Restore and build
        run: |
          dotnet restore
          dotnet test --no-build --verbosity normal
          dotnet publish -c Release -o out
      - name: Build Docker image
        run: |
          docker build -t ${{ secrets.ACR_NAME }}.azurecr.io/worker:${{ github.sha }} .
      - name: Log in to ACR
        uses: azure/docker-login@v1
        with:
          login-server: ${{ secrets.ACR_NAME }}.azurecr.io
          username: ${{ secrets.ACR_USERNAME }}
          password: ${{ secrets.ACR_PASSWORD }}
      - name: Push image
        run: |
          docker push ${{ secrets.ACR_NAME }}.azurecr.io/worker:${{ github.sha }}

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Azure login
        uses: azure/login@v1
        with:
          creds: ${{ secrets.AZURE_CREDENTIALS }}
      - name: Deploy to Azure Container Apps
        run: |
          az containerapp update \
            --name my-worker \
            --resource-group ${{ secrets.AZURE_RG }} \
            --image ${{ secrets.ACR_NAME }}.azurecr.io/worker:${{ github.sha }} \
            --cpu 0.5 --memory 1Gi

This pipeline guarantees that every commit that passes unit tests ends up as a new revision of the worker. Because Azure Container Apps supports zero‑downtime rollouts, the new replica set is warmed up while the previous one continues to process messages. If health probes (exposed by Dapr on /healthz) fail, the platform automatically rolls back, preserving message integrity.

Beyond the basic flow, you can extend the workflow with Trivy for container vulnerability scanning, or add a step that runs dapr run locally to perform integration tests against a real pub/sub component before pushing. By codifying these practices, your team reduces the risk of configuration drift and ensures that scaling, observability, and security are baked into every deployment.

Etiketler: #dotnet 8 #azure container apps #dapr #pub/sub messaging #event-driven architecture
Paylaş:
M

Yazar

Mahmut Sarıkaya

yazılım Geliştirici

Yorumlar

Henüz yorum yok. İlk yorumu siz yapın!

Yorum Bırakın

9 + 6 =