Freigeben über


Privates Ausführen des Bicep-Bereitstellungsskripts über einen privaten Endpunkt

Mit der Microsoft.Resources/deploymentScripts-Ressourcen-API-Version 2023-08-01 können Sie Bereitstellungsskripts privat in einer Azure-Containerinstanz (ACI) ausführen.

Konfigurieren der Umgebung

In diesem Setup wird die vom Bereitstellungsskript erstellte ACI in einem virtuellen Netzwerk ausgeführt und erhält eine private IP-Adresse. Anschließend stellt sie über einen privaten Endpunkt eine Verbindung mit einem neuen oder bereits vorhandenen Speicherkonto her. Die containerSettings/subnetIds-Eigenschaft gibt die ACI an, die in einem Subnetz des virtuellen Netzwerks bereitgestellt werden muss.

Screenshot der allgemeinen Architektur, der zeigt, wie die Infrastruktur zum privaten Ausführen von Bereitstellungsskripts verbunden ist.

Um Bereitstellungsskripts privat auszuführen, benötigen Sie die folgende Infrastruktur, wie im Architekturdiagramm dargestellt:

  • Erstellen eines virtuellen Netzwerks mit zwei Subnetzen:
    • Ein Subnetz für den privaten Endpunkt.
    • Ein Subnetz für die ACI. Dieses Subnetz benötigt eine Microsoft.ContainerInstance/containerGroups-Delegierung.
  • Erstellen Sie ein Speicherkonto mit öffentlichem Netzwerkzugriff.
  • Erstellen Sie einen privaten Endpunkt innerhalb des virtuellen Netzwerks, der mit der file-Unterressource für das Speicherkonto konfiguriert ist.
  • Erstellen Sie die private DNS-Zone privatelink.file.core.windows.net, und registrieren Sie die IP-Adresse des privaten Endpunkts als A-Eintrag. Verknüpfen Sie die private DNS-Zone mit dem erstellten virtuellen Netzwerk.
  • Erstellen Sie eine benutzerseitig zugewiesene verwaltete Identität mit Storage File Data Privileged Contributor-Berechtigungen für das Speicherkonto, und geben Sie sie in der identity-Eigenschaft in der Bereitstellungsskriptressource an. Informationen zum Zuweisen der Identität finden Sie unter Identität.
  • Die ACI-Ressource wird automatisch von der Bereitstellungsskriptressource erstellt.

Die folgende Bicep-Datei konfiguriert die Infrastruktur, die für die private Ausführung eines Bereitstellungsskripts erforderlich ist:

@maxLength(10) // Required maximum length, because the storage account has a maximum of 26 characters
param namePrefix string
param location string = resourceGroup().location
param userAssignedIdentityName string = '${namePrefix}Identity'
param storageAccountName string = '${namePrefix}stg${uniqueString(resourceGroup().id)}'
param vnetName string = '${namePrefix}Vnet'
param deploymentScriptName string = '${namePrefix}ds'

var roleNameStorageFileDataPrivilegedContributor = '69566ab7-960f-475b-8e7c-b3118f30c6bd'
var vnetAddressPrefix = '192.168.4.0/23'
var subnetEndpointAddressPrefix = '192.168.4.0/24'
var subnetACIAddressPrefix = '192.168.5.0/24'

resource managedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@2023-01-31' = {
  name: userAssignedIdentityName
  location: location
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: storageAccountName
  kind: 'StorageV2'
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  properties: {
    publicNetworkAccess: 'Disabled'
    networkAcls: {
      defaultAction: 'Deny'
      bypass: 'AzureServices'
    }
  }
}

resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-11-01' = {
   name: storageAccount.name
   location: location
   properties: {
    privateLinkServiceConnections: [
      {
        name: storageAccount.name
        properties: {
          privateLinkServiceId: storageAccount.id
          groupIds: [
            'file'
          ]
        }
      }
    ]
    customNetworkInterfaceName: '${storageAccount.name}-nic'
    subnet: {
      id: virtualNetwork::privateEndpointSubnet.id
    }
   }
}

resource storageFileDataPrivilegedContributorReference 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
  name: roleNameStorageFileDataPrivilegedContributor
  scope: tenant()
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  name: guid(storageFileDataPrivilegedContributorReference.id, managedIdentity.id, storageAccount.id)
  scope: storageAccount
  properties: {
    principalId: managedIdentity.properties.principalId
    roleDefinitionId: storageFileDataPrivilegedContributorReference.id
    principalType: 'ServicePrincipal'
  }
}

resource privateDnsZone 'Microsoft.Network/privateDnsZones@2020-06-01' = {
  name: 'privatelink.file.core.windows.net'
  location: 'global'

  resource virtualNetworkLink 'virtualNetworkLinks' = {
    name: uniqueString(virtualNetwork.name)
    location: 'global'
    properties: {
      registrationEnabled: false
      virtualNetwork: {
        id: virtualNetwork.id
      }
    }
  }

  resource resRecord 'A' = {
    name: storageAccount.name
    properties: {
      ttl: 10
      aRecords: [
        {
          ipv4Address: first(first(privateEndpoint.properties.customDnsConfigs)!.ipAddresses)
        }
      ]
    }
  }
}

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: vnetName
  location: location
  properties:{
    addressSpace: {
      addressPrefixes: [
        vnetAddressPrefix
      ]
    }
  }

  resource privateEndpointSubnet 'subnets' = {
    name: 'PrivateEndpointSubnet'
    properties: {
      addressPrefixes: [
        subnetEndpointAddressPrefix
      ]
    }
  }

  resource containerInstanceSubnet 'subnets' = {
    name: 'ContainerInstanceSubnet'
    properties: {
      addressPrefix: subnetACIAddressPrefix
      delegations: [
        {
          name: 'containerDelegation'
          properties: {
            serviceName: 'Microsoft.ContainerInstance/containerGroups'
          }
        }
      ]
    }
  }
}

resource privateDeploymentScript 'Microsoft.Resources/deploymentScripts@2023-08-01' = {
  name: deploymentScriptName
  dependsOn: [
    privateEndpoint
    privateDnsZone::virtualNetworkLink
  ]
  location: location
  kind: 'AzurePowerShell'
  identity: {
    type: 'UserAssigned'
    userAssignedIdentities: {
      '${managedIdentity.id}' : {}
    }
  }
  properties: {
    storageAccountSettings: {
      storageAccountName: storageAccount.name
    }
    containerSettings: {
      subnetIds: [
        {
          id: virtualNetwork::containerInstanceSubnet.id
        }
      ]
    }
    azPowerShellVersion: '9.0'
    retentionInterval: 'P1D'
    scriptContent: 'Write-Host "Hello World!"'
  }
}

Die ACI lädt Containerimages aus der Microsoft-Containerregistrierung herunter. Wenn Sie eine Firewall verwenden, setzen Sie die URL mcr.microsoft.com zum Herunterladen des Images auf die Positivliste. Fehler beim Herunterladen des Containerimages führen dazu, dass die ACI in den Zustand waiting versetzt wird, was schließlich zu einem Timeoutfehler führt.

Nächste Schritte

In diesem Artikel haben Sie erfahren, wie Sie Bereitstellungsskripts über einen privaten Endpunkt ausführen. Weitere Informationen: