Part 1: Introduction To Azure Container Apps
Series: Building microservices using Azure Container Apps and Terraform
7 min read
Looking for an alternative to Azure App Services for containers, but not too excited about the costs of an AKS cluster, or looking for an unopinionated hosting platform that's straightforward to use for your containers? This and more will be covered in this series on Building Microservices with Azure Container Apps And Terraform.
I will be using Dotnet, C#, and docker for these services. But as mentioned if your code can run in a container then do not fear.
What Are Azure Container Apps?
It is a serverless application-centric hosting service that is unopinionated about the programming model or language deployed to it, as long as your code is packaged in a container. Container apps are built on top of the Kubernetes ecosystem but you the developer do not maintain or learn all the intricacies of Kubernetes, its maintenance, or all the underlying orchestrators and infrastructure.
Under the hood, container apps runs on Azure Kubernetes Services (AKS) with integration with Distributed application runtime (Dapr), Envoy, and Kubernetes Event Driven Autoscaling (KEDA).
As mentioned Microservice is a prime use case but there are others such as:
- An application that needs to consume messages from a queue and requires to scale as the volume increases by spinning up/down instances based on the number of messages.
- Long-running background processes.
- HTTP message processing which can be split based on a % between instances. i.e. revision 1 gets 80% of the traffic and revision 2 gets 20% of the traffic.
- I have even seen some teams migrate their Azure Function into Container Apps.
- Supports Managed Identities
- Custom Domains
- Encrypted traffic between apps
- VNET integration
- Health Probes
- AAD and other social account authentication integration
- Environment Secrets
- Scaling based on scale triggers
- Configured to expose services internally or external
- Control over the app's number of vCPUs and RAM.
How Does It Work?
Ok so the first thing you are going to be working with and shipping containers, so naturally you will need some sort of container registry like Azure Container Registry.
When creating an Azure Container App you are required to specify a Container Apps Environment and place it in a region. This is used as a secure boundary around one or more container apps that communicate with each other and share a virtual network, Dapr, and logging. Note the apps in this environment would be writing to the same Log Analytics workspace. At the time of writing, you can't have an environment over multiple regions or VNETs, thus it's region & VNET specific.
Inside the Azure Container Apps Environment is where your Container Apps live. Each Container App consists of a Revision, Replica, and Container(s).
Is an immutable snapshot of a container app version. The 1st revision is created upon the 1st deployment. The app can run in a single or multi-revision mode and retain up to 100 revisions. With revisions, it's possible to split HTTP traffic between them. Revisions are the core of the Container Apps application lifecycle
In single revision mode only one revision is active at a time and when a new revision becomes available it replaces the current revision. In multi-revision mode, multiple revisions are running concurrently beside each other.
Changes to the container app fall into either application/revision-scope changes.
- Revision-Scope: Changes only affect a specific revision and are triggered through:
- Container configuration and image changes
- Revision Suffix
- Scale rules for the container app
- Application-Scope: Changes which are applied to all revisions but do not create a new revision and are triggered through:
- Secret value changes (Note: you need to restart the revision before it recognizes the change)
- Revision Mode Changed
- Dapr settings
- Private container registry credential changes
- Ingress changes such as: turning it on/off | traffic splitting rules | labels
Note: When making a revision-scope change then a new revision is automatically created. You can only affect a revision through application-scope change because a revision is immutable and these changes will be applied globally.
Revision labels With Container Apps you can split a % of your inbound HTTP traffic between multiple revisions of the app, but what happens if you want to create a revision and give that specific URL to say some test users? This is where labels come in, they are means by which you can direct external traffic to a specific revision. To switch the traffic between revisions using labels you need to set the revision mode to multiple and update the label against your targeted revision.
An example here is a container app with revision mode set to multiple where revision-3 has a label assigned test-users. The URL for the revision with the label would be:
This is useful because when you move the label to another revision the URL would remain the same.
- You can choose to use a label, traffic splitting, or both.
- Only one label can be applied to a revision.
- Traffic splitting isn't required to use a label
Azure Container Apps manages Kubernetes for us and takes care of the orchestration. As mentioned earlier you can run either a single container or multiple containers in a sidecar pattern in a single container app.
Containers from any public or private container registry can be used as well as any Linux-based x86-64 container image.
When configuring a container app you need to specify the container registry, the resources (vCPU/RAM), any volume mounts, and the container image name and you can specify health probes.
Later in this series, we will dive into health probes, those familiar with Kubernetes would recognize these 3:
Container apps support Managed Identities and late we will see how to setup up a managed Identity between Azure Container Registry and the Container Apps as well as between a Container App and Azure App Configuration.
Important to note that if your app tries to run a process that requires root then the application running inside the container would throw a runtime error and only Linux-based container images are supported.
Application Life Cycle
There are 4 life cycle states of a Container App: Deployment, Update, Deactivate, and Shutdown.
- Upon 1st deployment, a new revision is automatically created and set to active.
- When a container app is updated a new revision is created.
- You can deactivate a revision or choose to automatically deactivate old revisions
- Shutdown occurs when: App Scales in, is being deleted, or is being deactivated
Billing is broken up into two types of charges:
- Resource Consumption:
- The vCPU/RAM allocated is billed on a per-second basis - HTTP Requests:
- The number of HTTP request your app receives.
At the time of writing you do get some free stuff per calendar month per subscription:
- The first 180,000 vCPU-seconds
- The first 360,000 GiB-seconds
- The first 2 million HTTP requests
If your container app has no replicas running then no consumption charges are incurred. But when you have replicas and revisions running they are billed at an active rate. Microsoft does point out that a replica can enter an idle state which is then billed at a reduced rate.
On top of the resource consumption, you will be billed with request charges based on the HTTP requests received. worth pointing out that at the time of writing this is set the first 2 million requests are free per subscription per calendar month.
Kubernetes comes with a steep learning curve and Azure Container Apps make it easier for devs to take advantage of those features without having to invest the cost and time upfront to get started with Kubernetes or AKS. It's a great model for hosting your microservices and getting your team to focus on delivering customer value faster.
Our investigation continues in the next section "Introduction To Terraform"