Exécuter un script de déploiement Bicep en privé sur un point de terminaison privé
Avec l’API de ressource Microsoft.Resources/deploymentScripts
version 2023-08-01
, vous pouvez exécuter des scripts de déploiement en privé dans une instance ACI (Azure Container Instance).
Configurer l’environnement
Dans cette configuration, l’instance ACI créée par le script de déploiement s’exécute dans un réseau virtuel et obtient une adresse IP privée. Elle établit ensuite une connexion à un compte de stockage nouveau ou préexistant via un point de terminaison privé. La propriété containerSettings/subnetIds
spécifie l’instance ACI qui doit être déployée dans un sous-réseau du réseau virtuel.
Pour exécuter des scripts de déploiement en privé, vous avez besoin de l’infrastructure suivante, comme indiqué dans le diagramme d’architecture :
- Créer un réseau virtuel avec deux sous-réseaux :
- Un sous-réseau pour le point de terminaison privé.
- Un sous-réseau pour l’instance ACI. Ce sous-réseau a besoin d’une délégation
Microsoft.ContainerInstance/containerGroups
.
- Créez un compte de stockage sans accès réseau public.
- Créez un point de terminaison privé au sein du réseau virtuel configuré avec la sous-ressource
file
sur le compte de stockage. - Créez une zone DNS privée
privatelink.file.core.windows.net
et inscrivez l’adresse IP du point de terminaison privé en tant qu’enregistrement A. Liez la zone DNS privée au réseau virtuel créé. - Créez une identité managée affectée par l’utilisateur avec des autorisations
Storage File Data Privileged Contributor
sur le compte de stockage, et spécifiez-la dans la propriétéidentity
dans la ressource de script de déploiement. Pour affecter l’identité, consultez Identité. - La ressource ACI est créée automatiquement par la ressource de script de déploiement.
Le fichier Bicep suivant configure l’infrastructure requise pour exécuter un script de déploiement en privé :
@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’instance ACI télécharge des images conteneur à partir de Microsoft Container Registry. Si vous utilisez un pare-feu, placez l’URL mcr.microsoft.com en liste verte pour télécharger l’image. Si le téléchargement de l’image conteneur échoue, l’instance ACI bascule à l’état waiting
, ce qui aboutit à une erreur de délai d’expiration.
Étapes suivantes
Dans cet article, vous avez appris à exécuter des scripts de déploiement sur un point de terminaison privé. Pour en savoir plus :