PAUL'S BLOG

Learn. Build. Share. Repeat.

Autoscaling Azure Container Apps

2022-09-11 6 min read Architecture

So, what makes Azure Container Apps “serverless”?

Today we are going to focus on what makes Azure Container Apps (ACA) a “serverless” offering. But what does the term “serverless” really mean? As much as we’d like to think there aren’t any servers involved, that is certainly not the case. In general, “serverless” means that most (if not all) server maintenance has been abstracted away from you.

With serverless, you don’t spend any time managing and patching servers. This concern is offloaded to Azure and you simply focus on adding business value through application delivery. In addition to operational efficiency, cost efficiency can be achieved with serverless on-demand pricing models. Your workload horizontally scales out based on need and you only pay for what you use. To me, this is serverless, and my teammate @StevenMurawski said it best… “being able to scale to zero is what gives ACA it’s serverless magic.”

Continue reading

Microservices Communications with Azure Container Apps

2022-09-10 7 min read Architecture

Introduction

In yesterday’s #ServerlessSeptember post, we learned what the Azure Container Apps (ACA) service is and the problems it aims to solve. It is considered to be a Container-as-a-Service platform since much of the complex implementation details of running a Kubernetes cluster is managed for you.

Some of the use cases for ACA include event-driven processing jobs and background tasks, but this article will focus on hosting microservices, and how they can communicate with each other within the ACA service. At the end of this article, you will have a solid understanding of how networking and communication is handled and will leave you with a few tutorials to try.

Continue reading

Monitoring Azure Container Apps With Azure Managed Grafana

2022-09-09 10 min read Tutorial

The Azure Monitor team has announced the general availability of the Azure Managed Grafana (AMG) service. As part of the announcement, they also announced the availability of curated Grafana dashboards for various Azure services including Azure Container Apps 🎉

Grafana is very popular within the Cloud Native community and it seems natural to use it for Azure Container Apps (ACA) observability.

In this post, I will walk you through provisioning the ACA and AMG resources using the Terraform AzAPI provider and show you how easy it is to import the ACA dashboards into your AMG instance.

Continue reading

Terraform: Azure Container Apps with Azure Managed Grafana using the AzAPI provider

2022-09-09 3 min read Code Snippets

Code snippet for the Monitoring Azure Container Apps With Azure Managed Grafana article.

main.tf

terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">=3.0.0"
    }

    azapi = {
      source  = "azure/azapi"
      version = ">=0.5.0"
    }
  }
}

provider "azurerm" {
  features {
    resource_group {
      prevent_deletion_if_contains_resources = false
    }

    key_vault {
      purge_soft_delete_on_destroy = false
    }
  }
}

resource "random_pet" "aca" {
  length    = 2
  separator = ""
}

resource "random_integer" "aca" {
  min = 000
  max = 999
}

resource "random_string" "aca" {
  length  = 5
  lower   = true
  upper   = false
  numeric = true
  special = false

  keepers = {
    # Generate a new random_string on every run to avoid a conflict with the previous revision
    none = timestamp()
  }
}

locals {
  resource_name        = format("%s", random_pet.aca.id)
  resource_name_unique = format("%s%s", random_pet.aca.id, random_integer.aca.result)
  location             = "eastus"
}

resource "azurerm_resource_group" "aca" {
  name     = "rg-${local.resource_name}"
  location = local.location
}

resource "azurerm_log_analytics_workspace" "aca" {
  name                = "law-${local.resource_name_unique}"
  resource_group_name = azurerm_resource_group.aca.name
  location            = azurerm_resource_group.aca.location
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

# https://docs.microsoft.com//azure/templates/microsoft.app/2022-03-01/managedenvironments?tabs=bicep&pivots=deployment-language-terraform
resource "azapi_resource" "env" {
  type      = "Microsoft.App/managedEnvironments@2022-03-01"
  name      = "env-${local.resource_name}"
  parent_id = azurerm_resource_group.aca.id
  location  = azurerm_resource_group.aca.location

  body = jsonencode({
    properties = {
      appLogsConfiguration = {
        destination = "log-analytics"
        logAnalyticsConfiguration = {
          customerId = azurerm_log_analytics_workspace.aca.workspace_id
          sharedKey  = azurerm_log_analytics_workspace.aca.primary_shared_key
        }
      }
    }
  })
}

resource "azapi_resource" "helloworld" {
  type      = "Microsoft.App/containerApps@2022-03-01"
  name      = "helloworld"
  parent_id = azurerm_resource_group.aca.id
  location  = azurerm_resource_group.aca.location

  body = jsonencode({
    properties = {
      managedEnvironmentId = azapi_resource.env.id
      configuration = {
        ingress = {
          allowInsecure = false
          external      = true
          targetPort    = 80
          traffic = [
            {
              label          = "dev"
              latestRevision = true
              weight         = 100
            }
          ]
        }
      }
      template = {
        containers = [
          {
            name  = "helloworld"
            image = "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"
            resources = {
              cpu    = 0.5
              memory = "1.0Gi"
            }
          }
        ]
        revisionSuffix = random_string.aca.result
        scale = {
          minReplicas = 0
          maxReplicas = 30
          rules = [
            {
              name = "http-rule"
              http = {
                metadata = {
                  concurrentRequests = "100"
                }
              }
            }
          ]
        }
      }
    }
  })

  # this tells azapi to pull out properties and stuff into the output attribute for the object
  response_export_values = ["properties.configuration.ingress.fqdn"]
}

data "azurerm_subscription" "aca" {}
data "azurerm_client_config" "aca" {}

resource "azapi_resource" "amg" {
  type      = "Microsoft.Dashboard/grafana@2022-08-01"
  name      = "amg-${local.resource_name}"
  parent_id = azurerm_resource_group.aca.id
  location  = azurerm_resource_group.aca.location

  identity {
    type = "SystemAssigned"
  }

  body = jsonencode({
    properties = {
      apiKey                            = "Enabled"
      autoGeneratedDomainNameLabelScope = "TenantReuse"
      deterministicOutboundIP           = "Enabled"
      publicNetworkAccess               = "Enabled"
      zoneRedundancy                    = "Disabled"
    }
    sku = {
      name = "Standard"
    }
  })

  # this tells azapi to pull out properties and stuff into the output attribute for the object
  response_export_values = ["identity.principalId"]
}

resource "azurerm_role_assignment" "amg_reader" {
  scope                = data.azurerm_subscription.aca.id
  role_definition_name = "Monitoring Reader"
  principal_id         = jsondecode(azapi_resource.amg.output).identity.principalId
}

resource "azurerm_role_assignment" "amg_admin" {
  scope                = azapi_resource.amg.id
  role_definition_name = "Grafana Admin"
  principal_id         = data.azurerm_client_config.aca.object_id
}

output "helloworld_ingress_url" {
  value = format("%s%s", "https://", jsondecode(azapi_resource.helloworld.output).properties.configuration.ingress.fqdn)
}

# optional to automate the dashboard import process
resource "null_resource" "aca" {
  provisioner "local-exec" {
    command = <<-EOT
        az config set extension.use_dynamic_install=yes_without_prompt
        az grafana dashboard import -g ${azurerm_resource_group.aca.name} -n ${azapi_resource.amg.name} --definition 16592
    EOT
  }
}

Resource References

Securely connect to your Azure Linux Virtual Machine with Tailscale SSH

2022-08-12 12 min read Tutorial

Being on the Cloud Advocate team at Microsoft, we’re always looking to empower every developer to achieve more on Azure. One way of doing this is by bringing you hands-on content to deliver end-to-end scenarios using cloud-native and open source technologies.

My colleague on the Cloud Native team, Aaron Wislang has been cooking up a bunch of labs in our Azure Open Source Labs repo and one area we’ve been collaborating on is within the Azure Linux VM space.

Continue reading

Exploring .NET WebAssembly with WASI

2022-08-09 12 min read Tutorial

Overview

WebAssembly (Wasm) is something that the Cloud Native Advocacy team has been exploring. It has been around for a few years and has mostly been used within browser-based applications. There are many blog posts on what makes WebAssembly an ideal target for running applications (e.g., smaller footprint with .wasm files compared to containers, code isolation, and sandboxing). My colleague Steven Murawski wrote a blog series on getting started with hosting Wasm apps on an emerging PaaS platform called Hippo which is developed by folks at Fermyon. In Part 1 of the series, he introduces topics and define some of the acronyms like “Wagi” and “WASI”. He also introduced a runtime called Wasmtime which implements the WebAssembly System Interface (WASI) standard. This article will walk you through how Steven and I went about getting a .NET console app running as a Wasm app on the Wasmtime runtime in a Dev Container. The .NET console app produced in this article has also been contributed as a csharp template in the yo-wasm repo which is also maintained by Fermyon; so you can quickly test it out for yourself later.

Continue reading

Extending Visual Studio Code Dev Container Features

2022-07-27 10 min read Tutorial

UPDATE: The dev-container-features-template repo referenced in this post has been archived. Please see my new post here or visit containers.dev for the latest on this topic.

Have you ever wanted to try an Azure CLI extension without having to install the extension yourself on your local machine? VSCode Dev Containers may be a good option.

What is a Dev Container?

Visual Studio Code has an extension called Remote - Containers. This extension lets you use a Docker container as a development environment and is the technology that powers GitHub Codespaces. If you don’t have the option to use Codespaces, the remote container technology also allows you to open build/open the container within your local environment as long as you have Docker Desktop,or Rancher Desktop (with dockerd as the container runtime since containerd will not work with remote containers), or Docker Engine running on your local machine.

Continue reading
Older posts Newer posts