Azure Hands-On - Azure Container Instances (ACI)

Azure Hands-On - Azure Container Instances (ACI)

Azure Learning Path for Cloud and DevOps Engineers

📝Introduction

In this hands-on lab, we walked through the use of Azure Container Instances(ACI) which let us run a container in Azure without managing virtual machines and without a higher-level service.

Learning objectives:

  • Run containers in Azure Container Instances.

  • Control what happens when your container exits.

  • Use environment variables to configure your container when it starts.

  • Attach a data volume to persist data when your container exits.

  • Learn some basic ways to troubleshoot issues on your Azure containers.

📝Log in to the Azure Management Console

Using your credentials, make sure you're using the right Region. In my case, I am using the region eastus in my Cloud Playground Sandbox.

📌Note: You can also use the VSCode tool or from your local Terminal to connect to Azure CLI

More information on how to set it up is at the link.

📝Prerequisites:

  • Update to PowerShell 5.1, if needed.

  • Install .NET Framework 4.7.2 or later.

  • Visual Code

  • Web Browser (Chrome, Edge)

  • Azure CLI installed

  • Azure subscription

  • Docker installed

📝Setting an Azure Storage Account to Load Bash or PowerShell

  • Click the Cloud Shell icon (>_) at the top of the page.

  • Click PowerShell.

  • Click Show Advanced Settings. Use the combo box under Cloud Shell region to select the Region. Under Resource Group and Storage account(It's a globally unique name), enter a name for both. In the box under File Share, enter a name. Click ***Create storage (***if you don't have any yet).

📝Create an Azure Container Instance

  1. Sign in to the Azure portal with your Azure subscription.

  2. You can use the Open Azure Cloud Shell from the Azure portal by selecting the Cloud Shell icon or use another tool to use the Azure CLI bash environment.

  3. Create a new resource group <resource_group_name> so that it's easier to clean up these resources when you're finished with the lab. Remember it for the rest of the exercises in this lab you will use the same RG. You also need to choose a region in which you want to create the resource group; for example, East US.

     az group create --name <resource_group_name> --location <region>
    

  4. Create a container by providing a name, a Docker image, and an Azure resource group to the az container create command. You can optionally expose the container to the Internet by specifying a DNS name label. In this example, deploy a container that hosts a small web app. You can also select the location to place the image; we use the East US region, but you can change it to a location close to you.

  5. Provide a DNS name to expose your container to the Internet. Your DNS name must be unique. For learning purposes, run this command to create a Bash variable that holds a unique name:

     DNS_NAME_LABEL=aci-demo-$RANDOM
    
  6. Run the following az container create command to start a container instance:

     az container create \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --image mcr.microsoft.com/azuredocs/aci-helloworld \
       --ports 80 \
       --dns-name-label $DNS_NAME_LABEL \
       --location eastus
    

    $DNS_NAME_LABEL specifies your DNS name. We are using a sample image azuredocs/aci-helloworld, refers to a container image hosted on Microsoft Container Registry that runs a basic Node.js web application.

  7. When the az container create command completes, run az container show to check its status:

     az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query "{FQDN:ipAddress.fqdn,ProvisioningState:provisioningState}" \
       --output table
    

    You get your container's fully qualified domain name (FQDN) and its provisioning state. Here's an example:

    If your container is in the Creating state, wait a few moments, and run the command again until you see the Succeeded state.

  8. From a browser, go to your container's FQDN to see it running. Ensure you enter the http:// prefix in front of the aci-demo... string. You should get this welcome page:

📝Run a container to completion

With a configurable restart policy, you can specify that your containers are stopped when their processes have been completed.

Azure Container Instances has three restart-policy options:

Restart policyDescription
AlwaysContainers in the container group are always restarted. This policy makes sense for long-running tasks like a web server. This setting is the default applied when no restart policy is specified at container creation.
NeverContainers in the container group are never restarted. The containers run one time only.
OnFailureContainers in the container group are restarted only when the process executed in the container fails (when it terminates with a nonzero exit code). The containers are run at least once. This policy works well for containers that run short-lived tasks.

To create a container instance, we are using a sample image from the azuredocs/aci-wordcount container image and specify the OnFailure restart policy. This container refers to a container image hosted on Microsoft Container Registry that runs a Python script that analyzes the text of Shakespeare's Hamlet, writes the 10 most common words to standard output, and then exits.

  1. Run this az container create command to start the container:

     az container create \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --image mcr.microsoft.com/azuredocs/aci-wordcount:latest \
       --restart-policy OnFailure \
       --location eastus
    

    Azure Container Instances starts the container and then stops it when its process (a script, in this case) exits. When Azure Container Instances stops a container whose restart policy is Never or OnFailure, the container's status is set to Terminated.

  2. Run az container show to check your container's status:

     az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query "containers[0].instanceView.currentState.state"
    

    Repeat the command until it reaches the Terminated status.

  3. Run az container logs to view the container's logs to examine the output:

     az container logs \
       --resource-group <resource_group_name> \
       --name <name_container>
    

📝Deploy Azure Cosmos DB

Environment variables allow us to dynamically configure the application or script the container runs. We can use the Azure CLI, PowerShell, or the Azure portal to set variables when you create the container. Secured environment variables prevent sensitive information from displaying in the container's output.

Let's create an Azure Cosmos DB instance and use environment variables to pass the connection information to an Azure container instance. An application in the container uses the variables to write and read data from Azure Cosmos DB. We will create both an environment variable and a secured environment variable so that we can see the difference between them.

  1. Create an Azure Cosmos DB, providing a unique database name. For learning purposes, run this command in Cloud Shell to create a Bash variable that holds a unique name:

     COSMOS_DB_NAME=aci-cosmos-db-$RANDOM
    
  2. Run this az cosmosdb create command to create your Azure Cosmos DB instance:

     COSMOS_DB_ENDPOINT=$(az cosmosdb create \
       --resource-group <resource_group_name> \
       --name $COSMOS_DB_NAME \
       --query documentEndpoint \
       --output tsv)
    

    This command can take a few minutes to complete.

    $COSMOS_DB_NAME specifies your unique database name. The command prints the endpoint address for your database. Here, the command saves this address to the Bash variable COSMOS_DB_ENDPOINT.

  3. Run az cosmosdb keys list to get the Azure Cosmos DB connection key and store it in a Bash variable named COSMOS_DB_MASTERKEY:

     COSMOS_DB_MASTERKEY=$(az cosmosdb keys list \
       --resource-group <resource_group_name> \
       --name $COSMOS_DB_NAME \
       --query primaryMasterKey \
       --output tsv)
    

📝Deploy a container that works with CosmoDB

Create an Azure container instance that can read from and write records to our Azure Cosmos DB instance.

The two environment variables you created previously, COSMOS_DB_ENDPOINT and COSMOS_DB_MASTERKEY, hold the values you need to connect to the Azure Cosmos DB instance.

  1. Run the following az container create command to create the container:

     az container create \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --image mcr.microsoft.com/azuredocs/azure-vote-front:cosmosdb \
       --ip-address Public \
       --location eastus \
       --environment-variables \
         COSMOS_DB_ENDPOINT=$COSMOS_DB_ENDPOINT \
         COSMOS_DB_MASTERKEY=$COSMOS_DB_MASTERKEY
    

    azuredocs/azure-vote-front:cosmosdb refers to a container image that runs a fictitious voting app.

    Note the --environment-variables argument. This argument specifies environment variables that are passed to the container when the container starts. The container image is configured to look for these environment variables. Pass the name of the Azure Cosmos DB endpoint and its connection key.

  2. Run the az container show command to get your container's public IP address:

     az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query ipAddress.ip \
       --output tsv
    

  3. In a browser, go to your container's IP address.

    📌Note: Sometimes containers take a minute or two to fully start and be able to receive connections. If there's no response when you go to the IP address in your browser, wait a few moments and refresh the page.

    Once the app is available, you get this page:

Use secured environment variables to hide connection information

Let's learn how to prevent sensitive information.

  1. Let's start by seeing the current behavior in action. Run the following az container show command to display your container's environment variables:

     az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query containers[0].environmentVariables
    

    Although these values don't appear to your users through the voting application, it's a good security practice to ensure that sensitive information (such as connection keys) isn't stored in plain text.

    Secure environment variables prevent clear text output. To use secure environment variables, use the --secure-environment-variables argument instead of the --environment-variables argument.

  2. Run the following command to create a second container that makes use of secured environment variables:

     az container create \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --image mcr.microsoft.com/azuredocs/azure-vote-front:cosmosdb \
       --ip-address Public \
       --location eastus \
       --secure-environment-variables \
         COSMOS_DB_ENDPOINT=$COSMOS_DB_ENDPOINT \
         COSMOS_DB_MASTERKEY=$COSMOS_DB_MASTERKEY
    

    Note the use of the --secure-environment-variables argument.

  3. Run the following az container show command to display your container's environment variables:

     az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query containers[0].environmentVariables
    

    This time, we can see that your environment variables don't appear:

    The values of your environment variables don't appear at all. That's OK because these values refer to sensitive information.

📝Create an Azure file share

Azure Container Instances are stateless. If the container crashes or stops, all of its state is lost. To persist state beyond the lifetime of the container, we must mount a volume from an external store.

We will mount an Azure file share to an Azure container instance so that we can store data and access it later.

Let's create a storage account and a file share. Later, we can make the file share accessible to an Azure container instance.

  1. Our storage account requires a unique name. For learning purposes, run the following command to store a unique name in a Bash variable:

     STORAGE_ACCOUNT_NAME=demostorageaccount$RANDOM
    
  2. Run the following az storage account create command to create your storage account:

     az storage account create \
       --resource-group <resource_group_name> \
       --name $STORAGE_ACCOUNT_NAME \
       --sku Standard_LRS \
       --location eastus
    

  3. Run the following command to place the storage account connection string into an environment variable named AZURE_STORAGE_CONNECTION_STRING:

     export AZURE_STORAGE_CONNECTION_STRING=$(az storage account show-connection-string \
       --resource-group <resource_group_name> \
       --name $STORAGE_ACCOUNT_NAME \
       --output tsv)
    

    AZURE_STORAGE_CONNECTION_STRING is a special environment variable that the Azure CLI understands. The export part makes this variable accessible to other CLI commands that you run later.

  4. Run this command to create a file share in the storage account:

     az storage share create --name <name_share>
    

📝Get storage credentials

To mount an Azure file share as a volume in Azure Container Instances, we need these three values:

  • Storage account name

  • Share name

  • Storage account access key

We already have the first two values. The storage account name is stored in the STORAGE_ACCOUNT_NAME Bash variable. We specified a share name in the previous step. Here, we get the remaining value: the storage account access key.

  1. Run the following command to get the storage account key:

     STORAGE_KEY=$(az storage account keys list \
       --resource-group <resource_group_name> \
       --account-name $STORAGE_ACCOUNT_NAME \
       --query "[0].value" \
       --output tsv)
    

    The result is stored in a Bash variable named STORAGE_KEY.

  2. As an optional step, print the storage key to the console.

     echo $STORAGE_KEY
    

📝Deploy a container and mount the file share

To mount an Azure file share as a volume in a container, we specify the share and volume mount point when we create the container.

  1. Run this az container create command to create a container that mounts /aci/logs/ to our file share. This container refers to a simple container image hosted on Microsoft Container Registry that runs Node.js application showing how to interact with mounted Azure Files volumes from Azure Container Instances.

     az container create \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --image mcr.microsoft.com/azuredocs/aci-hellofiles \
       --location eastus \
       --ports 80 \
       --ip-address Public \
       --azure-file-volume-account-name $STORAGE_ACCOUNT_NAME \
       --azure-file-volume-account-key $STORAGE_KEY \
       --azure-file-volume-share-name <name_share> \
       --azure-file-volume-mount-path /aci/logs/
    

  2. Run az container show to get our container's public IP address:

     az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query ipAddress.ip \
       --output tsv
    

  3. From a browser, navigate to our container's IP address.

  4. Enter some text into the form, and select Submit. This action creates a file that contains the text you entered in the Azure file share.

  5. Run this az storage file list command to display the files that are contained in our file share:

     az storage file list -s <name_share> -o table
    
  6. Run az storage file download to download a file to our Cloud Shell session. Replace <filename> with one of the files that appeared in the previous step:

     az storage file download -s <name_share> -p <filename>
    
  7. Run the cat command to print the contents of the file.

     cat <filename>
    

Remember that our data persists when our container exits. We can mount our file share to other container instances to make that data available to them.

📝Troubleshoot Azure Container Instances

To help the understanding, here are some basic ways to troubleshoot container instances:

  • Pulling container logs

  • Viewing container events

  • Attaching to a container instance

Get logs from your prior deployed container instance

  1. Run the following az container logs command to see the output from the cats and dogs voting app container you created in the prior exercise:
az container logs \
  --resource-group <resource_group_name> \
  --name <name_container> \

Get container events

The az container attach command provides diagnostic information during container startup. Once the container has started, it also writes standard output and standard error streams to our local terminal.

  1. Run az container attach to attach to your container:

     az container attach \
       --resource-group <resource_group_name> \
       --name <name_container> \
    

📌Note: Enter <kbd>Ctrl+C</kbd> to disconnect from our attached container.

Execute a command in our container

We may need to run commands directly on our running containers for diagnoses and troubleshooting purposes.

  1. To see commands in our container, run the following az container exec command to start an interactive session on our container:

     az container exec \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --exec-command /bin/sh
    

    At this point, you're effectively working inside the container.

  2. Run a command.

  3. You can explore the system further if you wish. When you're done, run the exit command to stop the interactive session.

Monitor CPU and memory usage on our container

See how to monitor CPU and memory usage on our container.

  1. Run the following az container show command to get the ID of our Azure container instance and store the ID in a Bash variable:

     CONTAINER_ID=$(az container show \
       --resource-group <resource_group_name> \
       --name <name_container> \
       --query id \
       --output tsv)
    
  2. Run the az monitor metrics list command to retrieve CPU usage information:

     az monitor metrics list \
       --resource $CONTAINER_ID \
       --metrics CPUUsage \
       --output table
    

    Note the --metrics argument. Here, CPU Usage specifies to retrieve CPU usage.

  3. Run this az monitor metrics list command to retrieve memory usage information:

     az monitor metrics list \
       --resource $CONTAINER_ID \
       --metrics MemoryUsage \
       --output table
    

    Here, you specified MemoryUsage for the --metrics argument to retrieve memory usage information.

In the Azure portal, Azure Container Instances CPU and memory usage information look like this:

📌Note - At the end of each hands-on Lab, always clean up all resources previously created to avoid being charged.

Congratulations — you have completed this hands-on lab covering the basics of Azure Container Instances (ACI), running containers in Azure without managing virtual machines and without a higher-level service.

Thank you for reading. I hope you understood and learned something helpful from my blog.

Please follow me on Cloud&DevOpsLearn and LinkedIn, franciscojblsouza