Deploy Container App and pull image from Azure Container Registry using Terraform and AzAPI : Thomas Thornton

Deploy Container App and pull image from Azure Container Registry using Terraform and AzAPI
by: Thomas Thornton
blow post content copied from  Thomas Thornton
click here to view original post


In this blog I am going to show how to deploy Container App and pull an image from Azure Container Registry using user assigned managed identity for authentication. I will be achieving this using Terraform and AzAPI.

Image below shows a diagram of what I will be deploying; it shows container app accessing a container registry using a user created identity.

Terraform

The terraform will create:

  • Resource Group
  • Log Analytics Workspace
  • Container App Environment
  • Container App
  • User created identity
  • Assign IAM permissions to an already created container registry for the user created identity
  • Assign user created identity to the container App
  • Successfully deploy container app with image stored in container registry

Resource Group

resource "azurerm_resource_group" "rg" {
  name     = "${var.aca_name}-rg"
  location = var.location
}

Log Analytics Workspace

resource "azurerm_log_analytics_workspace" "loganalytics" {
  name                = "${var.aca_name}-la"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku                 = "PerGB2018"
  retention_in_days   = 30
}

Data resources associated with already created Container Registry

data "azurerm_resource_group" "acr" {
  name = "tamops-acr-github"
}

data "azurerm_container_registry" "acr" {
  name                = "tamopsactionacr"
  resource_group_name = data.azurerm_resource_group.acr.name
}

Container App Environment deployed using AzAPI and Log Analytics workspace associated to send logs

esource "azapi_resource" "containerapp_environment" {
  type      = "Microsoft.App/managedEnvironments@2022-03-01"
  name      = "${var.aca_name}env"
  parent_id = azurerm_resource_group.rg.id
  location  = azurerm_resource_group.rg.location

  body = jsonencode({
    properties = {
      appLogsConfiguration = {
        destination = "log-analytics"
        logAnalyticsConfiguration = {
          customerId = azurerm_log_analytics_workspace.loganalytics.workspace_id
          sharedKey  = azurerm_log_analytics_workspace.loganalytics.primary_shared_key
        }
      }
    }
  })
}

Create user assigned identity and associated IAM role assignment

resource "azurerm_user_assigned_identity" "containerapp" {
  location            = azurerm_resource_group.rg.location
  name                = "containerappmi"
  resource_group_name = azurerm_resource_group.rg.name
}

resource "azurerm_role_assignment" "containerapp" {
  scope                = data.azurerm_resource_group.acr.id
  role_definition_name = "acrpull"
  principal_id         = azurerm_user_assigned_identity.containerapp.principal_id
  depends_on = [
    azurerm_user_assigned_identity.containerapp
  ]
}

Create Azure Container App using AzAPI, notice:

  • Highlighted lines 8-11: Showing assignment of user assigned identity created above
  • Highlighted lines 21-26: Showing registry being assigned to the container registry
  • Highlighted line 31: Showing image assigned from container registry
resource "azapi_resource" "containerapp" {
  type      = "Microsoft.App/containerapps@2022-03-01"
  name      = var.aca_name
  parent_id = azurerm_resource_group.rg.id
  location  = azurerm_resource_group.rg.location


  identity {
    type         = "SystemAssigned, UserAssigned"
    identity_ids = [azurerm_user_assigned_identity.containerapp.id]
  }
  body = jsonencode({

    properties = {
      managedEnvironmentId = azapi_resource.containerapp_environment.id
      configuration = {
        ingress = {
          external : true,
          targetPort : 80
        },
        "registries" : [
          {
            "server" : data.azurerm_container_registry.acr.login_server,
            "identity" : azurerm_user_assigned_identity.containerapp.id
          }
        ]
      }
      template = {
        containers = [
          {
            image = "${data.azurerm_container_registry.acr.login_server}/aspcoresample:76ef8d9511d310649729a28563fdf6d133338e30",
            name  = "firstcontainerappacracr"
            resources = {
              cpu    = 0.25
              memory = "0.5Gi"
            },
            "probes" : [
              {
                "type" : "Liveness",
                "httpGet" : {
                  "path" : "/",
                  "port" : 80,
                  "scheme" : "HTTP"
                },
                "periodSeconds" : 10
              },
              {
                "type" : "Readiness",
                "httpGet" : {
                  "path" : "/",
                  "port" : 80,
                  "scheme" : "HTTP"
                },
                "periodSeconds" : 10
              },
              {
                "type" : "Startup",
                "httpGet" : {
                  "path" : "/",
                  "port" : 80,
                  "scheme" : "HTTP"
                },
                "periodSeconds" : 10
              }
            ]
          }
        ]
        scale = {
          minReplicas = 0,
          maxReplicas = 2
        }
      }
    }

  })
  ignore_missing_property = true
  depends_on = [
    azapi_resource.containerapp_environment
  ]
}

The terraform files here – have been setup to run locally, with running a successful plan

terraform init
terraform plan

Terraform Plan output:

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # azapi_resource.containerapp will be created
  + resource "azapi_resource" "containerapp" {
      + body                      = (known after apply)
      + id                        = (known after apply)
      + ignore_casing             = false
      + ignore_missing_property   = true
      + location                  = "uksouth"
      + name                      = "tamopsacablog"
      + output                    = (known after apply)
      + parent_id                 = (known after apply)
      + schema_validation_enabled = true
      + tags                      = (known after apply)
      + type                      = "Microsoft.App/containerapps@2022-03-01"

      + identity {
          + identity_ids = (known after apply)
          + principal_id = (known after apply)
          + tenant_id    = (known after apply)
          + type         = "SystemAssigned, UserAssigned"
        }
    }

  # azapi_resource.containerapp_environment will be created
  + resource "azapi_resource" "containerapp_environment" {
      + body                      = (sensitive)
      + id                        = (known after apply)
      + ignore_casing             = false
      + ignore_missing_property   = true
      + location                  = "uksouth"
      + name                      = "tamopsacablogenv"
      + output                    = (known after apply)
      + parent_id                 = (known after apply)
      + schema_validation_enabled = true
      + tags                      = (known after apply)
      + type                      = "Microsoft.App/managedEnvironments@2022-03-01"

      + identity {
          + identity_ids = (known after apply)
          + principal_id = (known after apply)
          + tenant_id    = (known after apply)
          + type         = (known after apply)
        }
    }

  # azurerm_log_analytics_workspace.loganalytics will be created
  + resource "azurerm_log_analytics_workspace" "loganalytics" {
      + daily_quota_gb                     = -1
      + id                                 = (known after apply)
      + internet_ingestion_enabled         = true
      + internet_query_enabled             = true
      + location                           = "uksouth"
      + name                               = "tamopsacablog-la"
      + primary_shared_key                 = (sensitive value)
      + reservation_capacity_in_gb_per_day = (known after apply)
      + resource_group_name                = "tamopsacablog-rg"
      + retention_in_days                  = 30
      + secondary_shared_key               = (sensitive value)
      + sku                                = "PerGB2018"
      + workspace_id                       = (known after apply)
    }

  # azurerm_resource_group.rg will be created
  + resource "azurerm_resource_group" "rg" {
      + id       = (known after apply)
      + location = "uksouth"
      + name     = "tamopsacablog-rg"
    }

  # azurerm_role_assignment.containerapp will be created
  + resource "azurerm_role_assignment" "containerapp" {
      + id                               = (known after apply)
      + name                             = (known after apply)
      + principal_id                     = (known after apply)
      + principal_type                   = (known after apply)
      + role_definition_id               = (known after apply)
      + role_definition_name             = "acrpull"
      + scope                            = "/subscriptions/04109105-f3ca-44ac-a3a7-66b4936112c3/resourceGroups/tamops-acr-github"
      + skip_service_principal_aad_check = (known after apply)
    }

  # azurerm_user_assigned_identity.containerapp will be created
  + resource "azurerm_user_assigned_identity" "containerapp" {
      + client_id           = (known after apply)
      + id                  = (known after apply)
      + location            = "uksouth"
      + name                = "containerappmi"
      + principal_id        = (known after apply)
      + resource_group_name = "tamopsacablog-rg"
      + tenant_id           = (known after apply)
    }

Plan: 6 to add, 0 to change, 0 to destroy.

Running terraform apply, we can review the deployed resources in Azure

terraform apply

Reviewing container app identities, we can see the user assigned identity successfully

Reviewing the container app URL, we can see the container image has been deployed successfully!

Awesome! Successfully deployed Container App and pulled an image from Azure Container Registry using user assigned managed identity for authentication.

GitHub repository containing example terraform


December 15, 2022 at 03:03PM
Click here for more details...

=============================
The original post is available in Thomas Thornton by Thomas Thornton
this post has been published as it is through automation. Automation script brings all the top bloggers post under a single umbrella.
The purpose of this blog, Follow the top Salesforce bloggers and collect all blogs in a single place through automation.
============================

Salesforce