Implement containerized solutions -III
Table of contents
- Azure Container Apps
- Use Cases
- Features
- Example Scenarios
- ACA Environments
- Features
- Limitations
- Deploying ACA Using Azure CLI
- Connecting Multiple Containers
- Scaling ACA
- Revisions in ACA
- Health Probes in ACA
- Limitations
- Network Integration in ACA
- ACA - Volumes and Storage Mounts
- Authentication and Authorization in ACA
- Manage Secrets in ACA
- Defining secrets
Azure Container Apps
Azure Container Apps(ACA) provide the flexibility you need with a serverless container service built for microservice applications with robust autoscaling robust autoscaling capabilities without the overhead of managing the complex infrastructure.
ACA enables you to run microservices and containerized applications on a serverless platform which uses Kubernetes technologies internally under the hood. Specifically, it leverages Kubernetes for container orchestration, but abstracts away much of the complexity involved in managing a Kubernetes cluster. Essentially, ACA simplifies the experience, removing the need to manually configure and manage Kubernetes.
Azure Container Service(ACS) is built on top of Kubernetes and open source technologies like Dapr
Can develop K8s style apps and microservices with features like service discovery and traffic splitting
ACS doesn’t provide direct access to the underlying Kubernetes APIs
It is fully serverless (scales down to zero)
Applications built on ACA can dynamically scale based on
HTTP traffic
Event-Driven processing
CPU or Memory load
Any KEDA supported scaler
Use Cases
Deploying API endpoints
Hosting background processing applications
Handling event-driven processing
Running microservices
Features
Run multiple container revisions and manage the application lifecycle of the container app
Autoscale your apps based on any KEDA-supported scale trigger
Enable HTTPS ingress without having to manage other Azure infrastructure
Split traffic
Use internal ingress and service discovery for secure internal-only endpoints with built-in DNS-based service discovery.
Public and Private container registry support
Microservices with Dapr
Azure VNET integration
Secrets for storing confidential key/values
Integrated with log analytics
Example Scenarios
Public API Endpoints
HTTP requests are split between two versions of container app where the first version gets 80% of the traffic, while a new version receives the remaining 20%.
Scaling is determined by the number of concurrent HTTP requests.
Background Processing
A continuously-running background process that transforms data in a database.
Scaling is determined by the level of CPU or memory load.
Event-Driven Processing
A queue render application that process messages as they arrive in a queue.
Scaling is determined by the number of messages in the queue.
Microservices
Deploy and manage microservices architecture with option to integrate with Dapr.
Individual microservices can scale according to any KEDA scale trigger.
ACA Environments
Environments serve as an isolation boundary for a group of container apps. Container apps within the same environment are deployed in the same virtual network and log data to the same Log Analytics workspace.
Features
Configure a common virtual network for all container apps within the environment to ensure secure communication between them.
Scale applications independently within the same environment.
Enable centralized monitoring and logging for all container apps within the environment.
Allow applications to share the same Dapr configuration.
Share the same log analytics workspace across applications.
Limitations
No root access
Linux based containers only
Deploying ACA Using Azure CLI
Step 1: Create an ACA Environment
az containerapp env create \
--name myContainerAppEnv \
--resource-group myResourceGroup \
--location eastus \
--logs-workspace-id <log-analytics-workspace-id> \
--logs-workspace-key <log-analytics-workspace-key>
Step 2: Deploy a Container App
az containerapp create \
--name myContainerApp \
--resource-group myResourceGroup \
--environment myContainerAppEnv \
--image mcr.microsoft.com/azuredocs/aci-helloworld \
--target-port 80 \
--ingress external \
--cpu 0.5 \
--memory 1.0Gi
Step 3: Configure Scaling Rules
az containerapp create \
--name myContainerApp \
--resource-group myResourceGroup \
--environment myContainerAppEnv \
--image mcr.microsoft.com/azuredocs/aci-helloworld
--min-replicas 0 \
--max-replicas 5 \
--scale-rule-name azure-http-rule \
--scale-rule-type http \
--scale-rule-http-concurrency 100
Step 4: Update the Container App
az containerapp update \
--name myContainerApp \
--resource-group myResourceGroup \
--image myregistry.azurecr.io/myapp:latest
Step 5: Monitor and Logs
az containerapp logs show \
--name myContainerApp \
--resource-group myResourceGroup
Advanced Networking with CLI
az containerapp update \
--name myContainerApp \
--resource-group myResourceGroup \
--vnet myVNet \
--subnet mySubnet
Connecting Multiple Containers
You can define multiple containers within a single container app to implement the sidecar pattern. The containers in a container app share disk space, network resources, and follow the same application lifecycle.
Examples of sidecar containers include:
An agent that reads logs from the primary app container on a shared volume and forwards them to a logging service.
A background process that refreshes a cache used by the primary app container in a shared volume.
Note: To run multiple containers in a container app, include more than one container in the container array of the container app template.
Container Registries - You can deploy images hosted on private registries by providing credentials in the container app's configuration.
{
...
"registries": [{
"server": "docker.io",
"username": "my-registry-user-name",
"passwordSecretRef": "my-password-secret-name"
}]
}
ACA exposes each container app through a domain name if ingress is enabled. With ingress enabled, your application is assigned a FQDN. The domain name takes the following forms
https:<app-name>.<environment-identifier>.<region>.azurecontainerapps.io
There are two types of ingresses
External - <app-name>.<environment-identifier>.<region>.azurecontainerapps.io
Internal - <app-name>.internal.<environment-identifier>.<region>.azurecontainerapps.io
Ingress endpoints can be exposed either publicly to the world or internally and only available to other container apps in the same environment.
Scaling ACA
Horizontal scaling - As a container app scales out, new instances of the container app are created on demand. These instances are referred to as replicas.
When you initially create a container app, the scale rule is set to zero, and there are no charges incurred when the application scales down to zero (when not running).
Revisions in ACA
The changes to your container apps are deployed as revisions (versions). A revision is an immutable snapshot of a container app version. You can use revisions to release a new version of your app, or quickly revert to an earlier version of your app.
Changing application code doesn’t automatically create a new revision in container app. But changing the template section of Azure resource template (revision-scope changes) creates a new version.
Basically when you change the container image or change the scale parameters(min/max replicas), it will create a new version. And it is called revision scope(template section).
Revision Scope
Container/images
Scale rules
Application Scope
Secret values
Revision mode
Ingress configuration
Credentials for container registries
Dapr settings
Revision modes
You can configure a revision mode for an Azure Container App, choosing between single or multiple modes.
In single mode, previous revisions will not be accessible and in multiple mode, previous versions will remain accessible.
Why do we need revisions?
Release a new version of your app
Quickly revert to an earlier version of your app
Split traffic between revisions for A/B testing
Gradually phase in a new revision in blue-green deployments
You have the ability to manage which revisions are active and direct external traffic to each active revision. Revision names are used to identify a revision and are included in the revision URLs.
The Application Lifecycle consists of three stages:
Deployment Phase - When a container app is deployed, the initial revision is created.
Update Phase - When a container app undergoes a revision scope change, a new version is created. You can decide whether to automatically deactivate old versions or keep them active.
Deactivate Phase - When a revision is no longer required, you can deactivate it with the option to reactivate it later. During reactivation, containers in the revision are shut down. This shutdown process also occurs as a container app scales down when the load is low.
Health Probes in ACA
Distributed systems consist of multiple components working together to achieve a common goal. An orchestration system manages these components or containers, overseeing their lifecycle and scaling. This system must monitor the application's health status. If a container encounters issues or malfunctions, health probes inform the orchestration engine, which can then restart the container to restore its functionality.
ACA utilize three types of health probes, which are based on Kubernetes health probes. These include:
Liveness Probes: These check if the application is running. If the liveness probe fails, the container is restarted.
Readiness Probes: These determine if the application is ready to serve traffic. If the readiness probe fails, the container is temporarily removed from the service load balancers.
Startup Probes: These are used to determine if the application within the container has started. If the startup probe fails, the container is killed and subject to the container's restart policy.
These probes help ensure that the orchestration system can maintain the application's health and availability.
There are two types of health probes based on protocol.
HTTP - Allows to implement custom logic to check the status of application dependencies before reporting a healthy status (custom HTTP endpoint).
TCP - Waits for connection to be established with the server to indicate success. A probe failure is registered if no connection is made.
Limitations
Each container can have only one of each probe type.
Exec probes are not supported. (Exec is used in Kubernetes to execute an application inside the container, and based on the response, Kubernetes determines the health status.)
Port values must be integers; named ports are not supported.
gRPC is not supported.
Network Integration in ACA
A virtual network is a software-defined network on Azure that enables communication and security management among various Azure services deployed within the network.
The diagram illustrates a virtual network setup in Azure, featuring two subnets, each hosting a virtual machine (VM). These VMs are capable of intercommunication, with security managed through Network Security Groups (NSG) and Application Security Groups. Furthermore, resources within the virtual network can securely interact with other Platform as a Service (PaaS) offerings, such as SQL Server, Key Vault, and Storage accounts.
In addition to PaaS services, you can enable VPN connections to this virtual network. These clients could be your on-premises clients or your PC or mobile devices connecting to the virtual network through a VPN connection (P2S/S2S). Once connected to the VPN, the devices will be able to securely access the resources.
Benefits
The container app will now have all the features available to the VM. For instance, it can securely communicate with PaaS services without the traffic going over the internet. Additionally, resources already deployed in the virtual network can interact securely with the container app. This secure access is possible because the resources are within virtual networks that have service/private endpoint connections enabled, allowing traffic to flow through Azure private networks instead of the public internet. You also have the option to disable public internet access to the container app.
ACA - Volumes and Storage Mounts
Docker Volumes are file systems attached to Docker containers to retain data produced by the running container. Azure Container Apps (ACA) offer three methods for writing files to a container:
Container File System: This is temporary storage limited to the local container. It can be used for writing to a local app cache, but it is not very useful as it will be cleared if the container app restarts or scales up or down.
Temporary Storage: This storage is temporary and specific to each individual replica. It can be used for sharing files between containers within a replica. For example, the main container app can write log files that a sidecar container processes.
Azure Files: This is a permanent storage solution. It can be used for writing files to a file share, making data accessible to other systems.
Authentication and Authorization in ACA
ACA offer built-in authentication and authorization capabilities to secure your external ingress-enabled container app with little to no coding required. This feature streamlines the process by providing ready-to-use authentication with federated identity providers
This feature should only be used with HTTPA
Ensure
allowInsecure
is disabled on container apps ingress configurationTo restrict app access to authenticated users, set its
Restrict Access
toRequire Authentication
To authenticate but not restrict access, set its
Restrict Access
toAllow Unauthenticated
It supports two features
Server directed flow (browser based applications)
Ideal for browser-based applications
Container Apps handle the authentication process, making it very easy to implement
Cookie-based approach
Client directed flow (For API/mobile backends)
Ideal for APIs and mobile backends’
Your app has to provide auth and submit the token
Token based
How Auth Works?
When authentication is enabled for a container app, a new container is deployed within the same replica as the application container. This container, known as the authentication middleware, acts as a proxy for all requests received by the application container after the authentication feature is enabled.
Manage Secrets in ACA
ACA provide a secure way to store sensitive configuration values. Once secrets are defined at the application level, they become accessible to container apps and can be referenced within scale rules. These secrets are scoped to the application, independent of any specific application revision. Modifying secrets—whether adding, removing, or changing them—does not create new revisions. Each application revision can utilize one or more secrets, and multiple revisions can share the same secrets. When a secret is updated or deleted, existing revisions are not automatically affected. To address changes, you can either deploy a new revision or restart an existing one. Before deleting a secret, ensure you deploy a new revision that no longer references it, and deactivate all revisions that do.
Container apps do not support direct integration with Azure Key Vault. Instead, enable managed identity in the container app and use the Key Vault SDK within the app to access secrets.
Defining secrets
When creating a container app, secrets are defined using the --secrets
parameter.
The parameter accepts a space-delimited set of name/value pairs.
Each pair is delimited by an equals sign (
=
).
az containerapp create \
--resource-group "my-resource-group" \
--name queuereader \
--environment "my-environment-name" \
--image demos/queuereader:v1 \
--secrets "queue-connection-string=$CONNECTION_STRING"
Once secrets are declared at the application level, you can reference them in environment variables when creating a new revision of your container app. When an environment variable references a secret, it is populated with the secret's defined value. In the Azure CLI, to reference a secret in an environment variable, set its value to secretref:
, followed by the secret's name.
az containerapp create \
--resource-group "my-resource-group" \
--name myQueueApp \
--environment "my-environment-name" \
--image demos/myQueueApp:v1 \
--secrets "queue-connection-string=$CONNECTIONSTRING" \
--env-vars "QueueName=myqueue" "ConnectionString=secretref:queue-connection-string"