Ejecución del script de implementación de Bicep de forma privada a través de un punto de conexión privado
Con la versión de la API de recursos de Microsoft.Resources/deploymentScripts
2023-08-01
, puede ejecutar scripts de implementación de forma privada dentro de una instancia de Azure Container Instance (ACI).
Configuración del entorno
En esta configuración, la ACI creada por el script de implementación se ejecuta dentro de una red virtual y obtiene una dirección IP privada. A continuación, establece una conexión a una cuenta de almacenamiento nueva o preexistente a través de un punto de conexión privado. La propiedad containerSettings/subnetIds
especifica la ACI que se debe implementar en una subred de la red virtual.
Para ejecutar scripts de implementación de forma privada, necesita la siguiente infraestructura como se muestra en el diagrama de arquitectura:
- Cree una red virtual con dos subredes:
- Una subred para el punto de conexión privado.
- Una subred para la ACI, esta subred necesita una delegación
Microsoft.ContainerInstance/containerGroups
.
- Cree una cuenta de almacenamiento sin acceso a la red pública.
- Cree un punto de conexión privado dentro de la red virtual configurada con el subrecurso
file
en la cuenta de almacenamiento. - Cree una zona DNS privada
privatelink.file.core.windows.net
y registre la dirección IP del punto de conexión privado como un registro A. Vincule la zona DNS privada a la red virtual creada. - Cree una identidad administrada asignada por el usuario con permisos
Storage File Data Privileged Contributor
en la cuenta de almacenamiento y especifíquela en la propiedadidentity
en el recurso de script de implementación. Para asignar la identidad, consulte Identidad. - El recurso de script de implementación crea automáticamente el recurso de script de implementación.
El siguiente archivo de Bicep configura la infraestructura necesaria para ejecutar un script de implementación de forma privada:
@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!"'
}
}
ACI descarga imágenes de contenedor de Microsoft Container Registry. Si usa un firewall, incluya en la lista de permitidos la dirección URL mcr.microsoft.com descargar la imagen. Si no se descarga la imagen de contenedor, la ACI entra en un estado de waiting
, provoca un error de tiempo de espera.
Pasos siguientes
En este artículo, ha aprendido a ejecutar scripts de implementación a través de un punto de conexión privado. Para obtener más información: