Documentation

adrs/043-azure-infrastructure-architecture.md

ADR-043: Azure Infrastructure Architecture for Dynaplex

Status

Accepted

Context

Dynaplex deployments to Azure Container Apps require careful infrastructure design to support:

  1. IoT Device Connectivity: RFID readers and other IoT devices need reliable MQTT broker access
  2. Network Isolation: Container Apps should have explicit network boundaries for security
  3. Resource Organization: Azure resources should follow consistent naming conventions
  4. Identity Management: Services need secure access to Azure resources (blob storage, Key Vault, etc.)

Previous Architecture

The original deployment used:

  • Auto-generated resource names with cryptic suffixes (e.g., config-aszxig73dxx3m)
  • Per-component managed identities (complex RBAC management)
  • Direct TCP exposure for EMQX MQTT broker
  • Default Container Apps networking (no VNet)

Challenges

  1. Device Configuration Fragility: Changing EMQX infrastructure required reconfiguring all IoT devices
  2. Resource Identification: Cryptic names made Azure portal navigation difficult
  3. RBAC Complexity: Multiple managed identities required extensive role assignments
  4. Network Visibility: No explicit network boundaries or traffic control

Decision

Implement a structured Azure infrastructure architecture with:

1. Azure CAF Naming Conventions

Use Microsoft Cloud Adoption Framework abbreviations for consistent resource naming:

{abbreviation}-{groupId}-{purpose}

Examples:
- psql-elbbudev         (PostgreSQL server)
- cae-elbbudev          (Container Apps Environment)
- ca-elbbudev-identity  (Identity Container App)
- log-elbbudev          (Log Analytics Workspace)
- vnet-elbbudev         (Virtual Network)
- st{groupId}           (Storage Account - no hyphens)

Resource Abbreviations

Resource Type Abbreviation Example
Container App ca ca-elbbudev-catalog
Container Apps Environment cae cae-elbbudev
PostgreSQL psql psql-elbbudev
Log Analytics log log-elbbudev
Virtual Network vnet vnet-elbbudev
Subnet snet snet-elbbudev-infra
Storage Account st stelbbudev
App Configuration appcs appcs-elbbudev
User-Assigned Identity id id-elbbudev-app

2. VNet for Network Isolation

Deploy Container Apps Environment with a custom VNet:

Address Space: 10.0.0.0/16
Infrastructure Subnet: 10.0.0.0/23 (delegated to Microsoft.App/environments)

Benefits:

  • Explicit network boundaries between environments
  • Private inter-service communication within VNet
  • NSG rules for traffic control
  • Foundation for future VNet integration scenarios (e.g., VPN, ExpressRoute)

3. EMQX via Azure Front Door (WebSocket Architecture)

Route IoT device traffic through Azure Front Door using MQTT-over-WebSocket:

┌──────────────────┐         ┌─────────────────┐         ┌──────────────────┐
│  Zebra Readers   │  wss:// │  Azure Front    │  HTTP   │  EMQX Container  │
│  (IoT Devices)   │ ──────► │  Door           │ ──────► │  App (port 8083) │
└──────────────────┘         └─────────────────┘         └──────────────────┘

Key Points:

  • Devices connect via wss://acsisemqx-*.azurefd.net:443
  • Front Door routes to EMQX WebSocket listener (port 8083)
  • EMQX exposes HTTP ingress (not TCP) for Container Apps compatibility
  • Device configuration remains stable when infrastructure changes

EMQX Configuration:

  • WebSocket listener: 0.0.0.0:8083
  • Unlimited queue length (max_mqueue_len = infinity)
  • Unlimited session expiry (session_expiry_interval = infinity)
  • Session persistence via Azure Files mount
  • Environment variable configuration for all settings

4. Shared Managed Identity

Use a single user-assigned managed identity for all Container Apps:

builder.AddDynaplexAppIdentity();  // Creates: id-{groupId}-app

Benefits:

  • Single set of RBAC role assignments instead of per-component
  • Easier auditing and compliance tracking
  • Simpler rotation and lifecycle management
  • Consistent naming pattern

Implementation

DynaplexContext Extensions

// Naming helpers
context.ResourceName("ca", "identity")     // → "ca-elbbudev-identity"
context.ResourceName("psql")               // → "psql-elbbudev"
context.StorageAccountName()               // → "stelbbudev"

// Infrastructure methods
builder.AddDynaplexAppIdentity();          // Shared managed identity
builder.AddDynaplexDatabase();             // PostgreSQL with CAF naming
builder.AddDynaplexContainerAppEnvironment(); // VNet + Log Analytics
builder.AddDynaplexMqttBroker();           // EMQX with WebSocket
builder.AddDynaplexStorage();              // Storage + EMQX file share

Front Door Configuration

After azd provision, configure Front Door origin group:

  1. Create origin group for EMQX WebSocket traffic
  2. Add EMQX Container App as origin (port 8083)
  3. Configure health probe for / endpoint
  4. Route existing EMQX hostname to new origin

Consequences

Positive

  • Device Stability: IoT devices use Front Door URL, unaffected by backend changes
  • Clear Resource Naming: Easy to identify resources in Azure portal
  • Simplified RBAC: Single identity for all components
  • Network Control: VNet provides explicit traffic boundaries
  • Operational Visibility: Consistent naming aids troubleshooting

Negative

  • Front Door Dependency: WebSocket traffic routes through additional service
  • WebSocket Protocol: Requires MQTT-over-WebSocket capable devices (Zebra FX9600 supports this)
  • Migration Effort: Existing deployments need recreation with new naming

Neutral

  • VNet Overhead: Minimal additional cost for VNet resources
  • Naming Changes: One-time migration from old naming scheme

Configuration Reference

Required Parameters

Parameter Purpose Example
postgres-admin-user PostgreSQL admin username acsisadmin
postgres-admin-password PostgreSQL admin password (secret)
emqx-admin-password EMQX dashboard password (secret)
emqxStorageAccountName Storage account for EMQX stelbbudev
emqxStorageAccountKey Storage account key (secret)

Environment Variables for MQTT

{
  "Bbu__Mqtt__EnvironmentId": "elbbudev",
  "Iot__Mqtt__EnvironmentId": "elbbudev"
}

Implementation Files

  • strata/orchestration/src/Acsis.Dynaplex.Strata.Orchestration/DynaplexContext.cs - Naming helpers and context
  • strata/orchestration/src/Acsis.Dynaplex.Strata.Orchestration/DynaplexInfrastructureExtensions.cs - Infrastructure extension methods
  • projects/bbu-rfid/src/Acsis.Dynaplex.Projects.BbuRfid/AppHost.cs - Project orchestration

Date: 2025-12-09
Author: Architecture Team
Reviewers: Development Team