Serverless Kubernetes with Azure Container Apps

Does Azure Container Apps deliver on the promise of serverless microservices reducing management, responsibility, and complexity? Let's find out!

A container ship, loading dock, and containers

Deploying containerized apps and microservices using a serverless service—not having to manage the underlying and usually complex infrastructure—sounds excellent. Serverless microservices are precisely what Azure Container Apps promises to deliver.

Let's look at the Azure Container Apps service and its features. Then we'll compare the service to other Azure services, followed by a step-by-step deployment of a simple containerized app.

Azure Container Apps

The Azure Container Apps service enables containerized apps on top of a serverless platform and doesn't care about the programming language or runtime version.

With Azure Container Apps, you can orchestrate your containers without the concerns of managing a Kubernetes cluster. You can think of Azure Container Apps as a serverless Kubernetes service. With this additional abstraction layer, you'll lose some control and flexibility in favor of ease of management and simplicity.

Azure Container Apps can autoscale your apps, including scaling down to zero instances. Run multiple revisions of your containers, including traffic splitting enabling various deployment scenarios. Integrate with an existing virtual network and much more.

As with almost every Azure service, new features are added regularly. Please refer to the documentation for a complete overview of the features.

Scaling of your app can take place based on different triggers, including:

  • HTTP Traffic: Based on the number of concurrent HTTPS requests.
  • Events: Using KEDA-supported scale triggers like Azure Service Bus messages. KEDA stands for Kubernetes-based Event Driven Autoscaler, and you can find more information about KEDA, including the supported scalers, on KEDA's website.
  • Resource usage: Based on the amount of CPU or memory used. Using resource usage-based scaling makes it impossible to scale down to zero instances.

Azure Container Apps supports Dapr integration. Dapr stands for Distributed Application Runtime and provides APIs that simplify microservice connectivity using sidecars. Dapr is out of scope for this post. But, you can find more information about Dapr on Dapr's website.

Environments

The container apps are deployed to an Azure Container Apps environment which enables the apps that are part of the environment to securely communicate with each other and share logging and a virtual network.

An environment can be deployed as a zone redundant resource, requiring virtual network integration. After creating the environment, it's impossible to modify the zone redundancy.

Service comparison

How does Azure Container Apps compares to other services like Azure Container Instances, Azure Kubernetes Service, or Azure Functions?

Azure Container Instances: This service is like a stripped-down version of Azure Container Apps and lacks the features like scaling and load balancing. Azure Container Instances is not as opinionated and can accommodate scenarios that do not align with Azure Container Apps. You can find more information about Azure Container Instances in the documentation.

Azure Kubernetes Service: This is Azure's managed Kubernetes service and supports all Kubernetes features. The Azure Kubernetes Service (AKS) gives you direct access to the Kubernetes API, enabling you to run any Kubernetes workload. Although, this comes with a higher degree of complexity, management, and responsibility.

AKS is a better option than creating and managing a Kubernetes cluster yourself. You can find more information about the Azure Kubernetes Service in the documentation.

Azure Functions: This service has much in common with Azure Container Apps like autoscaling, load balancing, and event integration but is optimized for function-as-a-service type workloads.

With a function, the function is the unit of work, whereas, with a container app, the entire container is the unit of work. You can find more information about  Azure Functions in the documentation.

Deployment

Let's deploy a simple containerized app to familiarize yourself with Azure Container Apps. But before you can start deploying, there are some prerequisites to fulfill:

  • Azure tenant and user account: You'll need an Azure tenant, an Azure Active Directory (Azure AD) instance. This instance is the foundation of the environment. And it allows you to create an identity (user account) to connect to Azure, set up the environment, and deploy the resources.
  • Subscriptions: You'll need a subscription and owner permissions to deploy the resources and minimize the costs by removing the resources at the end.
  • Azure CLI: You'll need the Azure command-line interface for deploying the resources, and you can find more information about the Azure CLI in the documentation.

Deploying the app

Now that the prerequisites are fulfilled, let's start! In the video, we'll go through the deployment step-by-step. And all the steps are available in the GitHub repository and this post.

Step 1: Start your preferred terminal and connect to Azure using the Azure CLI and your identity (user account).

az login

Step 2: List the available subscriptions and locate the preferred subscription id.

az account list --output table

Step 3: Set the subscription you're using to deploy the resources. Use the subscription id from the previous step.

az account set --subscription <subscriptionID>

Step 4: Because the Azure Container Apps extension is still in preview, you'll need to install the containerapp extension.

az extension add \
  --name containerapp \
  --upgrade

Step 5: Register the Microsoft.App and Microsoft.OperationalInsights namespaces.

az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.OperationalInsights

Step 6: Verify the status of the namespaces.

az provider show --namespace Microsoft.App --output table
az provider show --namespace Microsoft.OperationalInsights --output table

Step 7: Set the environment variables used throughout the upcoming commands.

RESOURCE_GROUP=apps-rg
LOCATION=westeurope
WORKSPACE=robino-apps-log01
ENVIRONMENT=robino-apps-env01
APP=robino-apps-app01

Step 8: Create the apps-rg resource group.

az group create \
  --location $LOCATION \
  --name $RESOURCE_GROUP

Step 9: Create the robino-apps-env01 container apps environment. The apps deployed in this environment use the same Log Analytics workspace created simultaneously with the environment.

az containerapp env create \
  --name $ENVIRONMENT \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

Step 10: Deploy the robino-apps-app01 container app to the environment using the latest containerapps-helloworld container image.

az containerapp create \
  --name $APP \
  --resource-group $RESOURCE_GROUP \
  --environment $ENVIRONMENT \
  --image mcr.microsoft.com/azuredocs/containerapps-helloworld:latest \
  --target-port 80 \
  --ingress external

Step 11: Verify the deployment by copying and using the URL in your browser. The container app will open.

The container app page

Step 12: Remove the apps-rg resource group, including all the resources. It'll prompt you for confirmation.

az group delete --name $RESOURCE_GROUP

Step 13: Finally, log out of the Azure CLI.

az logout

Summary

There it is! Thank you so much for taking the time to read this post. We went through the Azure Container Apps service and its features, compared it to other Azure services, and deployed a simple containerized app.

💡
Reminder: Don't forget to remove the resources to minimize the costs.

Azure Container Apps seems to be delivering on its promise, which means that Google Cloud Run and AWS Fargate have a fierce competitor for running containers using a serverless service, including essential features such as autoscaling, load balancing, and event integration.

Azure Container Apps was released into general availability in May, meaning the service is still evolving and maturing. I have the feeling that there's much more to come. Meanwhile, I'll further experiment with the service by diving deeper into all the features and building a microservices application. Stay tuned because this will be continued.