如何配置 Azure 应用服务以使用 terraform 从 ACR 中提取图像?

Posted

技术标签:

【中文标题】如何配置 Azure 应用服务以使用 terraform 从 ACR 中提取图像?【英文标题】:How to configure an Azure app service to pull images from an ACR with terraform? 【发布时间】:2020-05-11 20:10:33 【问题描述】:

我有以下 terraform 模块来在同一计划下设置应用服务:

provider "azurerm" 


variable "env" 
    type = string
    description = "The SDLC environment (qa, dev, prod, etc...)"


variable "appsvc_names" 
    type = list(string)
    description = "The names of the app services to create under the same app service plan"


locals 
    location = "eastus2"
    resource_group_name = "app505-dfpg-$var.env-web-$local.location"
    acr_name = "app505dfpgnedeploycr88836"


resource "azurerm_app_service_plan" "asp" 
    name                = "$local.resource_group_name-asp"
    location            = local.location
    resource_group_name = local.resource_group_name
    kind                = "Linux"
    reserved            = true

    sku 
        tier = "Basic"
        size = "B1"
    


resource "azurerm_app_service" "appsvc" 
    for_each            = toset(var.appsvc_names)

    name                = "$local.resource_group_name-$each.value-appsvc"
    location            = local.location
    resource_group_name = local.resource_group_name
    app_service_plan_id = azurerm_app_service_plan.asp.id

    site_config 
        linux_fx_version = "DOCKER|$local.acr_name/$each.value:latest"
    

    app_settings = 
        DOCKER_REGISTRY_SERVER_URL = "https://$local.acr_name.azurecr.io"
     


output "hostnames" 
  value = 
    for appsvc in azurerm_app_service.appsvc: appsvc.name => appsvc.default_site_hostname
  

我通过如下配置调用它:

terraform 
    backend "azurerm" 
    


locals 
    appsvc_names = ["gateway"]


module "web" 
    source = "../../modules/web"
    env = "qa"
    appsvc_names = local.appsvc_names


output "hostnames" 
    description = "The hostnames of the created app services"
    value       = module.web.hostnames

容器注册表有我需要的图像:

C:\> az acr login --name app505dfpgnedeploycr88836
Login Succeeded
C:\> az acr repository list  --name app505dfpgnedeploycr88836
[
  "gateway"
]
C:\> az acr repository show-tags --name app505dfpgnedeploycr88836 --repository gateway
[
  "latest"
]
C:\>

当我应用 terraform 配置时,一切都创建得很好,但是在 Azure 门户中检查创建的应用服务资源会发现它的容器设置显示没有 docker 图像:

现在,我可以手动切换到另一个 ACR,然后再切换回我想要的那个:

Cannot perform credential operations for /subscriptions/0f1c414a-a389-47df-aab8-a351876ecd47/resourceGroups/app505-dfpg-ne-deploy-eastus2/providers/Microsoft.ContainerRegistry/registries/app505dfpgnedeploycr88836 as admin user is disabled. Kindly enable admin user as per docs: https://docs.microsoft.com/en-us/azure/container-registry/container-registry-authentication#admin-account

这让我很困惑。根据https://docs.microsoft.com/en-us/azure/container-registry/container-registry-authentication#admin-account,不应使用管理员用户,因此我的 ACR 没有。另一方面,我知道我需要以某种方式配置应用服务以通过 ACR 进行身份验证。

那么正确的做法是什么?

【问题讨论】:

【参考方案1】:

因此,自从 v2.71 版本的 Azure RM 提供程序以来,这已经成为可能。有几件事必须发生......

    为应用程序分配托管标识(也可以使用用户分配,但需要做更多工作) 将site_config.acr_use_managed_identity_credentials 属性设置为true 在容器上授予应用程序的身份 ACRPull 权限。

下面是上面代码的修改版,没测试过但应该没问题

provider "azurerm" 


variable "env" 
    type = string
    description = "The SDLC environment (qa, dev, prod, etc...)"


variable "appsvc_names" 
    type = list(string)
    description = "The names of the app services to create under the same app service plan"


locals 
    location = "eastus2"
    resource_group_name = "app505-dfpg-$var.env-web-$local.location"
    acr_name = "app505dfpgnedeploycr88836"


resource "azurerm_app_service_plan" "asp" 
    name                = "$local.resource_group_name-asp"
    location            = local.location
    resource_group_name = local.resource_group_name
    kind                = "Linux"
    reserved            = true

    sku 
        tier = "Basic"
        size = "B1"
    


resource "azurerm_app_service" "appsvc" 
    for_each            = toset(var.appsvc_names)

    name                = "$local.resource_group_name-$each.value-appsvc"
    location            = local.location
    resource_group_name = local.resource_group_name
    app_service_plan_id = azurerm_app_service_plan.asp.id

    site_config 
        linux_fx_version = "DOCKER|$local.acr_name/$each.value:latest"
        acr_use_managed_identity_credentials = true
    

    app_settings = 
        DOCKER_REGISTRY_SERVER_URL = "https://$local.acr_name.azurecr.io"
    

    identity 
        type = "SystemAssigned"
       


data "azurerm_container_registry" "this" 
  name                = local.acr_name
  resource_group_name = local.resource_group_name


resource "azurerm_role_assignment" "acr" 
  for_each             = azurerm_app_service.appsvc
  
  role_definition_name = "AcrPull"
  scope                = azurerm_container_registry.this.id
  principal_id         = each.value.identity[0].principal_id


output "hostnames" 
  value = 
    for appsvc in azurerm_app_service.appsvc: appsvc.name => appsvc.default_site_hostname
  

2021 年 12 月 21 日编辑 关于由 Azure 重置的值的 MS documentation issue 现已解决,您还可以通过门户控制托管标识。

【讨论】:

可能值得一提的是,使用系统分配的身份进行 ACR 身份验证存在一个持续存在的问题。 github.com/MicrosoftDocs/azure-docs/issues/64660 @Percolator 这就是示例代码下方的段落(和链接)所指的 - 最新信息是除西欧和美国中南部以外的所有地区都已修补并且不会出现重置问题, 将在所有区域修复后更新【参考方案2】:

因此您可以将服务主体身份验证与App Service 一起使用,但您必须创建服务主体授予它对注册表的 ACRpull 权限并在应用服务站点配置中使用服务主体登录\密码

DOCKER_REGISTRY_SERVER_USERNAME DOCKER_REGISTRY_SERVER_PASSWORD

【讨论】:

但这意味着将其密码存储在版本控制中。不过,我可以将它作为一个变量使用,然后在 Azure DevOps 服务器中安排一个秘密变量。 在这种情况下,MS 实际上颠覆了他们对托管身份的整个想法,这很烦人 - 为什么在引用他们自己的网站时需要提供用户名/密码对“托管身份已通过身份验证Azure AD,因此您不必在代码中存储任何凭据。”

以上是关于如何配置 Azure 应用服务以使用 terraform 从 ACR 中提取图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何配置 GitHub Actions 以构建依赖于私有存储库的 Azure 静态 Web 应用程序?

如何在 Azure 管道中使用 Visual Studio 中的发布配置文件选项?

如何使用 WordPress 配置 Windows Azure 以进行 URL 重写?

自托管 azure 代理 - 如何配置管道以共享相同的构建文件夹

如何在微软Azure上搭建个人博客网站

如何在Azure VM上配置IIS站点以接受来自其他外部IP地址的请求?