Eseguire lo script di distribuzione di Bicep privatamente in un endpoint privato
Con la Microsoft.Resources/deploymentScripts
versione 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’Istanza di Azure Container creata dallo script di distribuzione viene eseguita all’interno di 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'Istanza di Azure Container che deve essere distribuita 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 l'Istanza di Azure Container, che 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
file
nell'account di archiviazione. - Creare una zona DNS privata
privatelink.file.core.windows.net
e 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 Contributor
per l'account di archiviazione e specificarla nella proprietàidentity
nella risorsa script di distribuzione. Per assegnare l'identità, vedere Identità. - La risorsa Istanza di Azure Container viene creata automaticamente dalla risorsa script di distribuzione.
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@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!"'
}
}
L’Istanza di Azure Container scarica le immagini del contenitore dal Registro Container Microsoft. Se si usa un firewall, consentire all'URL mcr.microsoft.com, aggiunto all’elenco di elementi consentiti, di scaricare l'immagine. Il mancato download dell'immagine del contenitore comporta l'immissione di uno stato di waiting
da parte dell’Istanza di Azure Container, 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: