Implement containerized solutions -III

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

  1. 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.

  2. Background Processing

    A continuously-running background process that transforms data in a database.

    Scaling is determined by the level of CPU or memory load.

  3. 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.

  4. 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

  1. External - <app-name>.<environment-identifier>.<region>.azurecontainerapps.io

  2. 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:

  1. Deployment Phase - When a container app is deployed, the initial revision is created.

  2. 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.

  3. 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:

  1. Liveness Probes: These check if the application is running. If the liveness probe fails, the container is restarted.

  2. 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.

  3. 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.

  1. HTTP - Allows to implement custom logic to check the status of application dependencies before reporting a healthy status (custom HTTP endpoint).

  2. 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:

  1. 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.

  2. 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.

  3. 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 configuration

  • To restrict app access to authenticated users, set its Restrict Access to Require Authentication

  • To authenticate but not restrict access, set its Restrict Access to Allow Unauthenticated

It supports two features

  1. 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

  2. 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"

Did you find this article valuable?

Support .NET - Sankarshan Ramesh by becoming a sponsor. Any amount is appreciated!