Autoscaling Azure Container Apps
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 readingMicroservices Communications with Azure Container Apps
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 readingMonitoring Azure Container Apps With Azure Managed Grafana
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 readingTerraform: Azure Container Apps with Azure Managed Grafana using the AzAPI provider
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
}
}