Compartilhar via


Módulos Bicep

O Bicep permite que você organize implantações em módulos. Um módulo é um arquivo Bicep (ou um modelo JSON do Azure Resource Manager) que é implantado de outro arquivo Bicep. Com os módulos, você melhora a legibilidade dos arquivos Bicep com o encapsulamento de detalhes complexos de sua implantação. Você também pode facilmente reutilizar módulos em implantações diferentes.

Para compartilhar módulos com outras pessoas em sua organização, crie um modelo de especificação ou registro privado. As especificações de modelo e os módulos no registro estão disponíveis somente para usuários com as permissões corretas.

Dica

A escolha entre o registro do módulo e as especificações de modelo é principalmente uma questão de preferência. Há algumas coisas a serem consideradas ao escolher entre os dois:

  • Só há suporte para o registro do módulo no Bicep. Se você ainda não estiver usando o Bicep, use as especificações de modelo.
  • O conteúdo do registro do módulo Bicep só pode ser implantado por meio de outro arquivo Bicep. As especificações de modelo podem ser implantadas diretamente por meio da API, do Azure PowerShell, da CLI do Azure e do portal do Azure. Você pode, até mesmo, usar UiFormDefinition para personalizar a experiência de implantação do portal.
  • O Bicep tem algumas funcionalidades limitadas para inserir outros artefatos de projeto (incluindo arquivos que não são do Bicep nem do modelo do ARM). Por exemplo, scripts do PowerShell, scripts da CLI e outros binários usando as funções loadTextContent e loadFileAsBase64. As especificações de modelo não podem empacotar esses artefatos.

Os módulos Bicep são convertidos em um único modelo do Azure Resource Manager com modelos aninhados. Para obter mais informações sobre como o Bicep resolve arquivos de configuração e como o Bicep mescla o arquivo de configuração definido pelo usuário com o arquivo de configuração padrão, veja Processo de resolução do arquivo de configuração e Processo de mesclagem do arquivo de configuração.

Recursos de treinamento

Se preferir aprender sobre módulos por meio de diretrizes passo a passo, confira Criar arquivos Bicep combináveis usando módulos.

Definir módulos

A sintaxe básica para definir um módulo é:

@<decorator>(<argument>)
module <symbolic-name> '<path-to-file>' = {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
}

Assim, um exemplo simples do mundo real seria semelhante a:

module stgModule '../storageAccount.bicep' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Você também pode usar um modelo do ARM JSON como módulo:

module stgModule '../storageAccount.json' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Use o nome simbólico para fazer referência ao módulo em outra parte do arquivo Bicep. Por exemplo, você pode usar o nome simbólico para obter a saída de um módulo. O nome simbólico pode conter a-z, A-Z, 0-9 e sublinhado (_). O nome não pode começar com um número. Um módulo não pode ter o mesmo nome que um parâmetro, variável ou recurso.

O caminho pode ser um arquivo local ou um arquivo em um registro. O arquivo local pode ser um arquivo Bicep ou um modelo ARM JSON. Para saber mais, confira Caminho até o módulo.

A propriedade name é obrigatória. Ela se torna o nome do recurso de implantação aninhado no modelo gerado.

Se um módulo com um nome estático for implantado simultaneamente no mesmo escopo, haverá o potencial de uma implantação interferir na saída da outra. Por exemplo, se dois arquivos Bicep usarem o mesmo módulo com o mesmo nome estático (examplemodule) e direcionados para o mesmo grupo de recursos, uma implantação poderá mostrar a saída errada. Se você estiver preocupado com implantações simultâneas no mesmo escopo, dê um nome exclusivo ao módulo.

O exemplo a seguir concatena o nome da implantação para o nome do módulo. Se você fornecer um nome exclusivo para a implantação, o nome do módulo também será exclusivo.

module stgModule 'storageAccount.bicep' = {
  name: '${deployment().name}-storageDeploy'
  scope: resourceGroup('demoRG')
}

Se você precisar especificar um escopo diferente do escopo do arquivo principal, adicione a propriedade scope. Para saber mais, confira Definir escopo do módulo.

// deploy to different scope
module <symbolic-name> '<path-to-file>' = {
  name: '<linked-deployment-name>'
  scope: <scope-object>
  params: {
    <parameter-names-and-values>
  }
}

Para implantar condicionalmente um módulo, adicione uma expressão if. O uso é semelhante à implantação condicional de um recurso.

// conditional deployment
module <symbolic-name> '<path-to-file>' = if (<condition-to-deploy>) {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
}

Para implantar mais de uma instância de um módulo, adicione a expressão for. Você pode usar o decorador batchSize para especificar se as instâncias são implantadas em série ou em paralelo. Para obter mais informações, confira Loops iterativos no Bicep.

// iterative deployment
@batchSize(int) // optional decorator for serial deployment
module <symbolic-name> '<path-to-file>' = [for <item> in <collection>: {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
}]

Assim como os recursos, os módulos são implantados em paralelo, a menos que eles dependam de outros módulos ou recursos. Normalmente, você não precisa definir dependências, pois elas são determinadas de forma implícita. Se você precisar definir uma dependência explícita, adicione dependsOn à definição do módulo. Para saber mais sobre dependências, confira Dependências de recurso.

module <symbolic-name> '<path-to-file>' = {
  name: '<linked-deployment-name>'
  params: {
    <parameter-names-and-values>
  }
  dependsOn: [
    <symbolic-names-to-deploy-before-this-item>
  ]
}

Caminho para o módulo

O arquivo para o módulo pode ser um arquivo local ou externo. O arquivo externo pode estar na especificação de modelo ou em um registro do módulo Bicep.

Arquivo local

Se o módulo for um arquivo local, forneça um caminho relativo para esse arquivo. Todos os caminhos no Bicep precisam ser especificados usando o separador de diretório de barra (/) para garantir a compilação consistente entre plataformas. Não há suporte para o caractere de barra invertida (\) do Windows. Os caminhos podem conter espaços.

Por exemplo, para implantar um arquivo que esteja um nível acima no diretório do seu arquivo principal, use:

module stgModule '../storageAccount.bicep' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Arquivo no registro

Registro de módulo público

Observação

Os módulos não AVM (Azure Verified Modules) são retirados do registro de módulos públicos.

Os Módulos Verificados do Azure são módulos pré-criados, pré-testados e pré-verificados para implantação de recursos no Azure. Criados e de propriedade de funcionários da Microsoft, esses módulos são projetados para simplificar e acelerar o processo de implantação de recursos e configurações comuns do Azure, ao mesmo tempo em que se alinham às práticas recomendadas, como o Well-Architected Framework.

Navegue até o Índice Bicep de Módulos Verificados do Azure para ver a lista de módulos disponíveis. Selecione os números destacados na captura de tela a seguir para ser levado diretamente para essa visualização filtrada.

Captura de tela dos Módulos Verificados do Azure (AVM).

A lista de módulos mostra a versão mais recente. Selecione o número da versão para ver uma lista de versões disponíveis:

Captura de tela das versões dos Módulos Verificados do Azure (AVM).

Para vincular a um módulo público, especifique o caminho do módulo com a seguinte sintaxe:

module <symbolic-name> 'br/public:<file-path>:<tag>' = {}
  • br/public é o alias para módulos públicos. Você pode personalizar esse alias no arquivo de configuração do Bicep.
  • O file path pode conter segmentos separados pelo caractere /.
  • tag é usada para especificar uma versão do módulo.

Por exemplo:

module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}

Observação

br/public é o alias para módulos públicos. Também pode ser escrito como:

module <symbolic-name> 'br:mcr.microsoft.com/bicep/<file-path>:<tag>' = {}

Registro de módulo privado

Se você publicou um módulo em um registro, poderá vincular a esse módulo. Forneça o nome para o registro de contêiner do Azure e um caminho para o módulo. Especifique o caminho do módulo com a seguinte sintaxe:

module <symbolic-name> 'br:<registry-name>.azurecr.io/<file-path>:<tag>' = {
  • br é o nome do esquema para um registro Bicep.
  • file path tem o nome de repository no Registro de Contêiner do Azure. O file path pode conter segmentos separados pelo caractere /.
  • tag é usada para especificar uma versão do módulo.

Por exemplo:

module stgModule 'br:exampleregistry.azurecr.io/bicep/modules/storage:v1' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

quando você faz referência a um módulo em um registro, a extensão BICEP no Visual Studio Code chama automaticamente bicep restore a fim de copiar o módulo externo para o cache local. A restauração do módulo externo demora alguns minutos. Se o IntelliSense do módulo não funcionar imediatamente, aguarde a conclusão da restauração.

O caminho completo de um módulo em um registro pode ser longo. Em vez de fornecer o caminho completo sempre que desejar usar o módulo, você pode configurar aliases no arquivo bicepconfig.json. Os aliases facilitam a referência do módulo. Por exemplo, com um alias, você pode encurtar o caminho para:

module stgModule 'br/ContosoModules:storage:v1' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Um alias foi predefinido para o registro de módulo público:

module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}

Você pode substituir o alias público no arquivo bicepconfig.json.

Arquivo na especificação de modelo

Depois de criar uma especificação de modelo, você poderá vincular a essa especificação de modelo em um módulo. Defina a especificação de modelo no seguinte formato:

module <symbolic-name> 'ts:<sub-id>/<rg-name>/<template-spec-name>:<version>' = {

No entanto, você pode simplificar o arquivo Bicep criando um alias para o grupo de recursos que contém as especificações de modelo. Ao usar um alias, a sintaxe será a seguinte:

module <symbolic-name> 'ts/<alias>:<template-spec-name>:<version>' = {

O módulo a seguir implanta uma especificação de modelo para criar uma conta de armazenamento. A assinatura e o grupo de recursos da especificação de modelo são definidos no alias nomeado ContosoSpecs.

module stgModule 'ts/ContosoSpecs:storageSpec:2.0' = {
  name: 'storageDeploy'
  params: {
    storagePrefix: 'examplestg1'
  }
}

Use decoradores

Os decoradores são escritos no formato @expression e são colocados acima das declarações do módulo. A tabela a seguir mostra os decoradores disponíveis para módulos.

Decorador Argument Descrição
batchSize nenhum Configure instâncias para implantar sequencialmente.
descrição string Forneça descrições para o módulo.

Os decoradores estão no namespace sys. Se você precisar diferenciar um decorador de outro item com o mesmo nome, preceda o decorador com sys. Por exemplo, se o arquivo Bicep incluir um parâmetro chamadodescription, você deverá adicionar o namespace sys ao usar o decorador de descrição.

BatchSize

Você só pode aplicar @batchSize() a uma definição de recurso ou módulo que use uma for expressão.

Por padrão, os módulos são implantados em paralelo. Ao adicionar o decorador @batchSize(int), você implanta as instâncias em série.

@batchSize(3)
module storage 'br/public:avm/res/storage/storage-account:0.11.1' = [for storageName in storageAccounts: {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}]

Para saber mais, consulte Implantar em lotes.

Descrição

Para adicionar explicação, adicione uma descrição às declarações do módulo. Por exemplo:

@description('Create storage accounts referencing an AVM.')
module storage 'br/public:avm/res/storage/storage-account:0.9.0' = {
  name: 'myStorage'
  params: {
    name: 'store${resourceGroup().name}'
  }
}

Texto formatado em Markdown pode ser usado para o texto descritivo.

Parâmetros

Os parâmetros que você fornece na definição de módulo correspondem aos parâmetros no arquivo Bicep.

O exemplo de Bicep a seguir tem três parâmetros: storagePrefix, storageSKU e location. O parâmetro storageSKU tem um valor padrão, ou seja, não é necessário fornecer um valor para esse parâmetro durante a implantação.

@minLength(3)
@maxLength(11)
param storagePrefix string

@allowed([
  'Standard_LRS'
  'Standard_GRS'
  'Standard_RAGRS'
  'Standard_ZRS'
  'Premium_LRS'
  'Premium_ZRS'
  'Standard_GZRS'
  'Standard_RAGZRS'
])
param storageSKU string = 'Standard_LRS'

param location string

var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'

resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: uniqueStorageName
  location: location
  sku: {
    name: storageSKU
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
}

output storageEndpoint object = stg.properties.primaryEndpoints

Para usar o exemplo anterior como um módulo, forneça valores para esses parâmetros.

targetScope = 'subscription'

@minLength(3)
@maxLength(11)
param namePrefix string

resource demoRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup1'
}

module stgModule '../create-storage-account/main.bicep' = {
  name: 'storageDeploy'
  scope: demoRG
  params: {
    storagePrefix: namePrefix
    location: demoRG.location
  }
}

output storageEndpoint object = stgModule.outputs.storageEndpoint

Definir escopo do módulo

Ao declarar um módulo, você pode definir um escopo para o módulo diferente do escopo do arquivo Bicep que o contém. Use a propriedade scope para definir o escopo do módulo. Quando a propriedade de escopo não é fornecida, o módulo é implantado no escopo de destino do pai.

O arquivo Bicep a seguir cria um grupo de recursos e uma conta de armazenamento nesse grupo de recursos. O arquivo é implantado em uma assinatura, mas o módulo está no escopo do novo grupo de recursos.

// set the target scope for this file
targetScope = 'subscription'

@minLength(3)
@maxLength(11)
param namePrefix string

param location string = deployment().location

var resourceGroupName = '${namePrefix}rg'

resource newRG 'Microsoft.Resources/resourceGroups@2024-03-01' = {
  name: resourceGroupName
  location: location
}

module stgModule '../create-storage-account/main.bicep' = {
  name: 'storageDeploy'
  scope: newRG
  params: {
    storagePrefix: namePrefix
    location: location
  }
}

output storageEndpoint object = stgModule.outputs.storageEndpoint

O exemplo a seguir implanta contas de armazenamento em dois grupos de recursos diferentes. Os dois grupos de recursos precisam já existir.

targetScope = 'subscription'

resource firstRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup1'
}

resource secondRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup2'
}

module storage1 '../create-storage-account/main.bicep' = {
  name: 'westusdeploy'
  scope: firstRG
  params: {
    storagePrefix: 'stg1'
    location: 'westus'
  }
}

module storage2 '../create-storage-account/main.bicep' = {
  name: 'eastusdeploy'
  scope: secondRG
  params: {
    storagePrefix: 'stg2'
    location: 'eastus'
  }
}

Defina a propriedade scope como um objeto de escopo válido. Se o arquivo Bicep implantar um grupo de recursos, uma assinatura ou um grupo de gerenciamento, você poderá definir o escopo de um módulo para o nome simbólico para esse recurso. Ou você pode usar as funções de escopo para obter um escopo válido.

Essas funções são:

O exemplo a seguir usa a função managementGroup para definir o escopo.

param managementGroupName string

module mgDeploy 'main.bicep' = {
  name: 'deployToMG'
  scope: managementGroup(managementGroupName)
}

Saída

Você pode obter valores de um módulo e usá-los no arquivo Bicep principal. Para obter um valor de saída de um módulo, use a propriedade outputs no objeto do módulo.

O primeiro exemplo cria uma conta de armazenamento e retorna os pontos de extremidade primários.

@minLength(3)
@maxLength(11)
param storagePrefix string

@allowed([
  'Standard_LRS'
  'Standard_GRS'
  'Standard_RAGRS'
  'Standard_ZRS'
  'Premium_LRS'
  'Premium_ZRS'
  'Standard_GZRS'
  'Standard_RAGZRS'
])
param storageSKU string = 'Standard_LRS'

param location string

var uniqueStorageName = '${storagePrefix}${uniqueString(resourceGroup().id)}'

resource stg 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: uniqueStorageName
  location: location
  sku: {
    name: storageSKU
  }
  kind: 'StorageV2'
  properties: {
    supportsHttpsTrafficOnly: true
  }
}

output storageEndpoint object = stg.properties.primaryEndpoints

Quando usado como módulo, você poderá obter esse valor de saída.

targetScope = 'subscription'

@minLength(3)
@maxLength(11)
param namePrefix string

resource demoRG 'Microsoft.Resources/resourceGroups@2024-03-01' existing = {
  name: 'demogroup1'
}

module stgModule '../create-storage-account/main.bicep' = {
  name: 'storageDeploy'
  scope: demoRG
  params: {
    storagePrefix: namePrefix
    location: demoRG.location
  }
}

output storageEndpoint object = stgModule.outputs.storageEndpoint

Próximas etapas