Uruchamianie skryptu wdrożenia Bicep prywatnie za pośrednictwem prywatnego punktu końcowego
Przy użyciu wersji 2023-08-01
interfejsu Microsoft.Resources/deploymentScripts
API zasobów można uruchamiać skrypty wdrażania prywatnie w usłudze Azure Container Instance (ACI).
Konfigurowanie środowiska
W tej konfiguracji usługa ACI utworzona przez skrypt wdrożenia jest uruchamiana w sieci wirtualnej i uzyskuje prywatny adres IP. Następnie ustanawia połączenie z nowym lub wstępnie istniejącym kontem magazynu za pośrednictwem prywatnego punktu końcowego. Właściwość containerSettings/subnetIds
określa wartość ACI, która musi zostać wdrożona w podsieci sieci wirtualnej.
Aby uruchomić skrypty wdrażania prywatnie, potrzebna jest następująca infrastruktura, jak pokazano na diagramie architektury:
- Utwórz sieć wirtualną z dwiema podsieciami:
- Podsieć dla prywatnego punktu końcowego.
- Podsieć dla usługi ACI— ta podsieć wymaga delegowania
Microsoft.ContainerInstance/containerGroups
.
- Utwórz konto magazynu bez dostępu do sieci publicznej.
- Utwórz prywatny punkt końcowy w sieci wirtualnej skonfigurowanej
file
przy użyciu zasobu podrzędnego na koncie magazynu. - Utwórz prywatną strefę
privatelink.file.core.windows.net
DNS i zarejestruj prywatny adres IP punktu końcowego jako rekord A. Połącz prywatną strefę DNS z utworzoną siecią wirtualną. - Utwórz tożsamość zarządzaną przypisaną przez użytkownika z uprawnieniami
Storage File Data Privileged Contributor
na koncie magazynu i określ ją we właściwości widentity
zasobie skryptu wdrożenia. Aby przypisać tożsamość, zobacz Tożsamość. - Zasób ACI jest tworzony automatycznie przez zasób skryptu wdrażania.
Poniższy plik Bicep konfiguruje infrastrukturę wymaganą do prywatnego uruchamiania skryptu wdrażania:
@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!"'
}
}
Usługa ACI pobiera obrazy kontenerów z usługi Microsoft Container Registry. Jeśli używasz zapory, dodaj adres URL dozwolony mcr.microsoft.com do pobrania obrazu. Nie można pobrać obrazu kontenera powoduje wprowadzenie waiting
stanu przez interfejs ACI, co ostatecznie prowadzi do błędu przekroczenia limitu czasu.
Następne kroki
W tym artykule przedstawiono sposób uruchamiania skryptów wdrażania za pośrednictwem prywatnego punktu końcowego. Dodatkowe informacje: