Невозможно создать уже существующий ресурс — при создании ContainerApp в два этапа (начальная загрузка + окончательный вPython

Программы на Python
Anonymous
Невозможно создать уже существующий ресурс — при создании ContainerApp в два этапа (начальная загрузка + окончательный в

Сообщение Anonymous »

Контекст
Я использую Pulumi (Python) с pulumi-azure-native и pulumi-azuread для развертывания приложения-контейнера Azure с назначаемым системой управляемым удостоверением, где это удостоверение должно быть членом существующей группы идентификаторов Entra (которая уже имеет AcrPull в ACR и секретах хранилища ключей). Пользователь в хранилище ключей).
Поскольку Principal_id управляемого удостоверения существует только после создания приложения-контейнера, а конфигурация реестра ACR требует, чтобы удостоверение уже имело AcrPull, прежде чем приложение сможет получить частный образ, я пробую трехэтапный подход:
  • Создайте приложение-контейнер с помощью назначенное системой удостоверение и общедоступный загрузочный образ (без конфигурации ACR).
  • Добавьте субъект-службу удостоверения в существующую группу Entra.
  • Обновите приложение-контейнер, используя частный образ и реестры[].identity = "system".
Я смоделировал шаги 1 и 3 как два отдельных ресурса ContainerApp Pulumi, ориентированные на одно и то же имя ресурса Azure, с родительским=bootstrap и depend_on=[membership] на конечном ресурсе.
Проблема

Код: Выделить всё

pulumi up
завершается сбоем на втором ресурсе ContainerApp с:

Код: Выделить всё

error: cannot create already existing resource
'/subscriptions/xxx/resourceGroups/rg-demo/providers/Microsoft.App/containerApps/orchestrator-demo'
Это имеет смысл: Pulumi пытается создать Orchestrator-final как новый ресурс, но ресурс Azure уже существует (созданный Orchestrator-bootstrap). Ресурс Orchestrator-final никогда не попадает в состояние.
Код

Код: Выделить всё

# __main__.py
import pulumi
import pulumi_azure_native as azure_native
import pulumi_azuread as azuread
from pulumi_azure_native.app import (
ConfigurationArgs,
ContainerApp,
ContainerArgs,
ContainerResourcesArgs,
ManagedServiceIdentityArgs,
ManagedServiceIdentityType,
RegistryCredentialsArgs,
ScaleArgs,
TemplateArgs,
)

# Minimal repro goal:
# - Existing Container App Environment and ACR
# - New Container App with system-assigned managed identity
# - Add that identity's service principal to an existing Entra group
# - Use group-based AcrPull instead of a direct role assignment on the identity

config = pulumi.Config()

resource_group_name = config.require("resourceGroupName")
location = config.require("location")
container_app_env_name = config.require("containerAppEnvironmentName")
container_app_name = config.get("containerAppName")
entra_group_display_name = config.require("entraGroupDisplayName")
acr_name = config.require("acrName")
acr_resource_group_name = config.require("acrResourceGroupName")
private_image = config.require("privateImage")

bootstrap_image = (
config.get("bootstrapImage")
or "mcr.microsoft.com/azuredocs/containerapps-helloworld:latest"
)

managed_environment = azure_native.app.get_managed_environment_output(
environment_name=container_app_env_name,
resource_group_name=resource_group_name,
)

acr = azure_native.containerregistry.get_registry_output(
registry_name=acr_name,
resource_group_name=acr_resource_group_name,
)

entra_group = azuread.get_group_output(display_name=entra_group_display_name)

bootstrap = ContainerApp(
"orchestrator-bootstrap",
container_app_name=container_app_name,
resource_group_name=resource_group_name,
location=location,
managed_environment_id=managed_environment.id,
identity=ManagedServiceIdentityArgs(type=ManagedServiceIdentityType.SYSTEM_ASSIGNED),
configuration=ConfigurationArgs(
ingress=None,
active_revisions_mode="Single",
),
template=TemplateArgs(
containers=[
ContainerArgs(
name=container_app_name,
image=bootstrap_image,
resources=ContainerResourcesArgs(cpu=0.25, memory="0.5Gi"),
)
],
scale=ScaleArgs(min_replicas=0, max_replicas=1),
),
opts=pulumi.ResourceOptions(
# The update resource below manages template/configuration.
ignore_changes=["configuration", "template"],
),
)

membership = azuread.GroupMember(
"orchestrator-group-membership",
group_object_id=entra_group.object_id,
member_object_id=bootstrap.identity.principal_id,
opts=pulumi.ResourceOptions(
depends_on=[bootstrap],
# First run can fail if identity propagation in Entra is not complete.
custom_timeouts=pulumi.CustomTimeouts(create="10m"),
),
)

app = ContainerApp(
"orchestrator-final",
container_app_name=container_app_name,
resource_group_name=resource_group_name,
location=location,
managed_environment_id=managed_environment.id,
identity=ManagedServiceIdentityArgs(type=ManagedServiceIdentityType.SYSTEM_ASSIGNED),
configuration=ConfigurationArgs(
ingress=None,
active_revisions_mode="Single",
registries=[
RegistryCredentialsArgs(
server=acr.login_server,
identity="system",
)
],
),
template=TemplateArgs(
containers=[
ContainerArgs(
name=container_app_name,
image=private_image,
resources=ContainerResourcesArgs(cpu=0.25, memory="0.5Gi"),
)
],
scale=ScaleArgs(min_replicas=1, max_replicas=1),
),
opts=pulumi.ResourceOptions(
parent=bootstrap,
depends_on=[membership],
),
)

pulumi.export("managedIdentityPrincipalId", app.identity.principal_id)
pulumi.export("groupObjectId",  entra_group.object_id)
pulumi.export("acrLoginServer", acr.login_server)
Сообщения об ошибках
Команда pulumi up завершилась неудачей со следующим сообщением:

Код: Выделить всё

pulumi up

View in Browser (Ctrl+O): https://app.pulumi.com/xxx/so-containerapp-mi-group/example/updates/2

Type                                 Name                              Status                  Info
pulumi:pulumi:Stack                  so-containerapp-mi-group-example  **failed**              1 error
+   ├─ azure-native:app:ContainerApp     orchestrator-bootstrap            created (17s)
+   │  └─ azure-native:app:ContainerApp  orchestrator-final                **creating failed**     1 error
+   └─ azuread:index:GroupMember         orchestrator-group-membership     created (1s)

Diagnostics:
azure-native:app:ContainerApp (orchestrator-final):
error: cannot create already existing resource '/subscriptions/xxx/resourceGroups/rg-demo/providers/Microsoft.App/containerApps/orchestrator-demo'

pulumi:pulumi:Stack (so-containerapp-mi-group-example):
error: update failed
Вот детали стека после ошибки:

Код: Выделить всё

pulumi stack

Current stack is example:
Owner: laurent-laporte-pro-org
Last updated: 1 minute ago (2026-03-03 18:41:24.392413 +0100 CET)
Pulumi version used: v3.224.0
Current stack resources (5):
TYPE                                      NAME
pulumi:pulumi:Stack                       so-containerapp-mi-group-example
├─ azure-native:app:ContainerApp          orchestrator-bootstrap
├─ azuread:index/groupMember:GroupMember  orchestrator-group-membership
├─ pulumi:providers:azure-native          default_3_13_0
└─ pulumi:providers:azuread               default_6_8_1

Current stack outputs (0):
No output values currently in this stack
Что я рассмотрел
  • Использование одного ресурса ContainerApp с зависимостью от GroupMember — но я не могу добавить удостоверение в группу до создания приложения и не могу настроить доступ ACR до того, как удостоверение получит роль.
  • Использование импорта / pulumi.ResourceOptions(import_=...) на последнем ресурсе — но это кажется хакерским, и я не уверен, что это правильный шаблон.
Вопросы
  • Это два-

    Код: Выделить всё

    ContainerApp
    -шаблон ресурса (bootstrap + Final) правильный подход, и если да, то как мне сказать Pulumi, что оркестратор-final должен обновить существующий ресурс, а не пытаться его создать?
  • В качестве альтернативы, существует ли более чистый шаблон Pulumi для обработки такого рода циклической зависимости (необходимо, чтобы ресурс существовал, чтобы получить его идентификатор, необходимо, чтобы идентификатор имел роль, прежде чем ресурс сможет его использовать)?
Окружающая среда

Подробнее здесь: https://stackoverflow.com/questions/799 ... -in-2-step

Вернуться в «Python»