Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Con la Microsoft.Resources/deploymentScriptsversione dell'API della risorsa2023-08-01, è possibile eseguire script di distribuzione privatamente all'interno di un'Istanza di Azure Container (ACI).
Configurare l'ambiente
In questa configurazione, l’ACI creata dallo script di distribuzione viene eseguita in una rete virtuale e ottiene un indirizzo IP privato. Stabilisce quindi una connessione con un account di archiviazione nuovo o esistente tramite un endpoint privato. La proprietà containerSettings/subnetIds specifica l'ACI che deve essere distribuito in una subnet della rete virtuale.
Per eseguire gli script di distribuzione privatamente, è necessaria l'infrastruttura seguente, come illustrato nel diagramma dell'architettura:
- Creare una rete virtuale con due subnet:
- Una subnet per l’endpoint privato.
- Una subnet per ACI; questa subnet richiede una delega
Microsoft.ContainerInstance/containerGroups.
- Creare un account di archiviazione senza accesso alla rete pubblica.
- Creare un endpoint privato all'interno della rete virtuale configurata con la sotto-risorsa
filenell'account di archiviazione. - Creare una zona DNS privata
privatelink.file.core.windows.nete registrare l'indirizzo IP dell'endpoint privato come record A. Collegare la zona DNS privata alla rete virtuale creata. - Creare un'identità gestita assegnata dall'utente con autorizzazioni
Storage File Data Privileged Contributorper l'account di archiviazione e specificarla nella proprietàidentitynella risorsa script di distribuzione. Per assegnare l'identità, vedere Identità. - La risorsa ACI viene creata automaticamente dalla risorsa di script di distribuzione.
Importante
Se assegni un'identità gestita con permessi che superano i requisiti operativi dello script, l'autore dello script è responsabile di garantire che l'account di archiviazione sia protetto da accessi indesiderati. Dove possibile, segui il principio del minimo privilegio.
Il file Bicep seguente configura l'infrastruttura necessaria per l'esecuzione di uno script di distribuzione privatamente:
@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@2025-01-31-preview' = {
name: userAssignedIdentityName
location: location
}
resource storageAccount 'Microsoft.Storage/storageAccounts@2025-06-01' = {
name: storageAccountName
kind: 'StorageV2'
location: location
sku: {
name: 'Standard_LRS'
}
properties: {
publicNetworkAccess: 'Disabled'
networkAcls: {
defaultAction: 'Deny'
bypass: 'AzureServices'
}
}
}
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2025-01-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@2024-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@2025-01-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: '14.0'
retentionInterval: 'P1D'
scriptContent: 'Write-Host "Hello World!"'
}
}
ACI scarica le immagini dei contenitori da Microsoft Container Registry. Se usi un firewall, aggiungi l'URL mcr.microsoft.com all'elenco degli elementi consentiti per scaricare l'immagine. Il mancato download dell'immagine del contenitore fa sì che ACI entri in uno stato di waiting, causando infine un errore di timeout.
Passaggi successivi
In questo articolo si è appreso come usare gli script di distribuzione in un endpoint privato. Per altre informazioni, vedere: