Microservices lieben Azure Container Apps
💝

Es war einmal ...

Projekte bei crossnative

  • Standardisierte Software Projekte
  • Fokus auf Anwendungen nicht Infrastruktur
  • Launchpad Stack mit Spring, Postgres, ...
  • Cloud Umgebung von Außen verfügbar
  • Container basiert und k8s nah
  • Pay-per-Use
Azure Container Apps ! 🚀

Azure Container Apps

  • verwaltete Serverless Container Plattform
  • flexibel Skalierbar (Zero to Hero)
  • "mini" k8s mit 1 Namespace
  • basiert auf Azure Kubernetes Plattform
  • Kubernetes ohne Server
  • KEDA Autoscaling, Replicas und Ingress von Kubernetes

Azure Container Apps
  bei crossnative

  • nutzen ACA seit 2 Jahren
  • erst nur für Test und Entwicklung
  • produktiver Betrieb mehrerer Anwendungen

Freddys BBQ
Basis Setup
🍖

Freddys BBQ _ Übersicht

Microservices mit Azure Container Apps

  1. ein gemeinsames Container App Environment
  2. eine Container App je Microservice
  3. App Insights und Log Analytics gemeinsam

Freddys BBQ _ Infrastruktur

Freddys BBQ _ Infrastruktur

Container App Environment

Freddys Container Apps

Shop Frontend Container App

Demo BBQ bestellen _ Teil 1 🚧

BBQ Bestellen Ablauf #1

BBQ Bestellen Ablauf #3

BBQ Bestellen Ablauf #4

Demo BBQ bestellen _ Teil 2 🚧

Infrastruktur mit Terraform

Container Apps Basis


            /* 1. ResourceGroup */
            resource "azurerm_resource_group" "freddy" {
              name     = "rg-freddy-dev-westeu"
              location = "West Europe"
            }
            
            /* 2. Log Analytics Workspace */
            resource "azurerm_log_analytics_workspace" "app_log_analytics" {
              name                = "log-freddy-dev-westeu"
              location            = azurerm_resource_group.freddy.location
              resource_group_name = azurerm_resource_group.freddy.name
              sku                 = "PerGB2018"
              retention_in_days   = 30
            }
            
            /* 3. Application Insights */
            resource "azurerm_application_insights" "freddy_appinsights" {
              name                = "appi-freddy-dev-westeu"
              location            = azurerm_resource_group.freddy.location
              resource_group_name = azurerm_resource_group.freddy.name
              workspace_id        = azurerm_log_analytics_workspace.app_log_analytics.id
              application_type    = "web"
            }
            
            /* 4. Container App Environment */
            resource "azurerm_container_app_environment" "cae" {
              name                       = "cae-freddy-dev-westeu"
              location                   = azurerm_resource_group.freddy.location
              resource_group_name        = azurerm_resource_group.freddy.name
              log_analytics_workspace_id = azurerm_log_analytics_workspace.app_log_analytics.id
            }
            

Container App Kitchen 👩‍🍳


            resource "azurerm_container_app" "kitchen" {
              name                         = "kitchen"
              container_app_environment_id = azurerm_container_app_environment.cae.id
              resource_group_name          = azurerm_resource_group.freddy.name
              revision_mode                = "Single"
            
              template {
                container {
                  name   = "kitchen"
                  image  = "ghcr.io/remast/kitchen-aca:0.1.0"
                  cpu    = 0.25
                  memory = "0.5Gi"
                }
                min_replicas = 0
                max_replicas = 1
              }

              ingress {
                target_port      = 8070
                traffic_weight {
                  latest_revision = true
                  percentage      = 100
                }
              }
            
            }
            

Container App Order 🤑


            resource "azurerm_container_app" "order" {
              name                         = "order"
              container_app_environment_id = azurerm_container_app_environment.cae.id
              resource_group_name          = azurerm_resource_group.freddy.name
              revision_mode                = "Single"
            
              template {
                container {
                  name   = "order"
                  image  = "ghcr.io/remast/order-aca:0.1.0"
                  cpu    = 0.5
                  memory = "1Gi"
                  env {
                    name  = "DELIVERY_SERVICE_URL"
                    value = "http://delivery"
                  }
                  env {
                    name  = "KITCHEN_SERVICE_URL"
                    value = "http://kitchen"
                  }
                }
                min_replicas = 0
                max_replicas = 1
              }
            
              ingress {
                target_port      = 8060
                traffic_weight {
                  latest_revision = true
                  percentage      = 100
                }
              }            
            }
            

Container App Shop Frontend 🏪


            resource "azurerm_container_app" "shop-frontend" {
              name                         = "shop-frontend"
              container_app_environment_id = azurerm_container_app_environment.cae.id
              resource_group_name          = azurerm_resource_group.freddy.name
              revision_mode                = "Single"
            
              template {
                container {
                  name   = "shop-frontend"
                  image  = "ghcr.io/remast/shop-frontend-aca:0.2.0"
                  cpu    = 0.25
                  memory = "0.5Gi"
                }
                min_replicas = 0
                max_replicas = 1
              }

              ingress {
                target_port      = 4200
                external_enabled = true
                traffic_weight {
                  latest_revision = true
                  percentage      = 100
                }
              }
            
            }

            output "shop_frontend_fqdn" {
              value = azurerm_container_app.shop-frontend.latest_revision_fqdn
            }
            

Terraform ausführen


            >_ terraform apply

            azurerm_resource_group.freddy: Refreshing state...
            azurerm_container_app_environment.cae: Refreshing state...
            azurerm_container_app.delivery: Refreshing state...
            azurerm_container_app.kitchen: Refreshing state...
            azurerm_container_app.shop-frontend: Refreshing state...
            azurerm_container_app.order: Refreshing state...
            
            Terraform will perform the following actions:
            
              # azurerm_container_app.order will be updated in-place
              ~ resource "azurerm_container_app" "order" {
                  ~ template {
                      ~ container {
                          ~ memory = "0.5Gi" -> "1Gi"
                        }
                    }
                }
            
            Plan: 0 to add, 1 to change, 0 to destroy.
            
            azurerm_container_app.order: Modifying...
            azurerm_container_app.order: Modifications complete after 17s
            Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
            
            Outputs:
            shop_frontend_fqdn = "shop-frontend-03.victorious-3fb.westeurope.azurecontainerapps.io"            
          

Demo Terraform 🚧

Freddys BBQ
in Produktion
🍖

In Produktion

  • Probes für Health und Startup 👨‍⚕️
  • Blue/Green Deployments mit Revisionen 🚦
  • Passwörter aus Secrets 🔐
  • Metriken (CPU, Speicher) und Logs ⏱️
  • Workload Profile 🏃‍♂️

Probes für Health und Startup 👨‍⚕️


            resource "azurerm_container_app" "kitchen" {
              template {
                container {
                  name   = "kitchen"
                  image  = "ghcr.io/remast/kitchen-aca:0.1.0"
                  cpu    = 0.25
                  memory = "0.5Gi"

                  startup_probe {
                    interval_seconds        = 5
                    failure_count_threshold = 3
                    port                    = 8070
                    path                    = "/health/readiness"
                    transport               = "HTTP"
                  }
                  readiness_probe {
                    port      = 8070
                    path      = "/health/readiness"
                    transport = "HTTP"
                  }
                  liveness_probe {
                    port      = 8070
                    path      = "/health/liveness"
                    transport = "HTTP"
                  }
                }
              }
            }
            

Blue/Green Deployments 🚦

  • Revisionen werden immer Blue/Green deployt
  • Traffic Splitting zwischen Revisionen möglich

Passwörter aus Secrets 🔐


            resource "azurerm_container_app" "order" {
              name = "order"
            
              secret {
                name  = "secret-api-key"
                value = "***shush***"
              }
            
              template {
                container {
                  name   = "order"
                  image  = "ghcr.io/remast/order-aca:0.1.0"
                  cpu    = 0.5
                  memory = "1Gi"

                  env {
                    name  = "DELIVERY_SERVICE_URL"
                    value = "http://delivery"
                  }
                  env {
                    name  = "KITCHEN_SERVICE_URL"
                    value = "http://kitchen"
                  }
                  env {
                    name        = "SECRET_API_KEY"
                    secret_name = "secret-api-key"
                  }
                }
              }
            }
            

Metriken und Logs ⏱️

Metriken

  • Application Insights für Metriken
  • Metriken aller Apps zentral verfügbar
  • Standard Metriken für CPU, Speicher, Replica

Logs

  • Logs aller Apps zentral verfügbar
  • Anwendungs Logs in ContainerAppConsoleLogs_CL
  • Infrastruktur Logs in ContainerAppSystemLogs_CL

Anwendungs Logs ⏱️

Infrastruktur Logs ⏱️

Workload Profile 🏃‍♂️

  • regeln verfügbare CPU und Speicher Limits
  • hängen am Container App Environment
  • Standard ist Consumption, alternative Dedicated
  • Dedicated Profile nutzt Instanzen
    (ähnlich k8s Nodes)
  • Speicher- und GPU optimierte Instanzen möglich

Workload Profile 🏃‍♂️

Workload Profile vCPU Memory
Consumption 4 8 Gi Standard
Dedicated-D4 4 16 Gi Allgemeine Nutzung
Dedicated-E4 4 32Gi Speicher optimiert

Was ACA noch kann

Was ACA noch kann

  • Container App Jobs
    (einmalig, CRON-Schedule, Event getrieben)
  • Init Container
  • Skalieren mit KEDA
  • Authentifizierung
  • SSL Zertifikate und mTLS
  • Dapr Integration

Microserves lieben Azure Container Apps

Freddys Basis Setup

  1. Freddys Container Apps
    • BBQ Architektur
    • ACA Infrastruktur
  2. Terraform Infrastruktur
    • ACA Setup
    • Ausführen und Ändern

ACA in Produktion

  • Probes für Health und Startup 👨‍⚕️
  • Blue/Green Deployments mit Revisionen 🚦
  • Passwörter aus Secrets 🔐
  • Metriken (CPU, Speicher) und Logs ⏱️
  • Workload Profile 🏃‍♂️

3 Gründe für
Azure Container Apps

  1. 🏃 Schnell
  2. ☯️ Einfach
  3. 🚂 Mächtig

👉 Mehr auf LinkedIn Learning

Microservices lieben
Azure Container Apps