(Part-3) Leverage Bicep: Standard model to Automate Azure IaaS deployment
Published Apr 28 2023 12:19 PM 6,665 Views

Chapter 3

<< Chapter 1          << Chater 2


  • Traps and Avoidance

    1. Pitfalls of dependency and update sequence

    With Hub&Spoke vNET/Subnet in place, we need to create an Azure Firewall and Route table and associate the Route table with the Subnet.


  • Approach to Solution
    - Write in one Bicep file
       It is true that referencing existing resources and passing variables becomes easier and less complicated. However, in large-scale development, we want to utilize modules as much as possible.

    - Override and rebuild existing resources
      When referencing a resource using "existing", there is a limitation that the resource cannot be deployed to another resource with the same name. There is a way to add a child resource by writing "name: parent resource/child resource" in the name property. However, this will initialize the initial settings of the child resource, and in some cases may break network communication with the existing resource. Therefore, it is not a realistic solution in all cases.

    Declarative application design to minimize resources
       An implementation that deadlocks due to dependencies and updates is likely to be designed as a procedural application design. Declare with a single workload and a single resource whenever possible and implement loosely coupled implementations within a single bicep file. Only the dependencies and the parts where updates occur should be described in the same bicep file.

    If you create a vNET hub & Spoke and create a Route table with Azure Firewall, you need to make spoke-vnet/subnet associate a route table with Azure Firewall's Private IP address. In this case, separate the creation of hub-vnet and spoke-vnet into separate bicep files.

      1,Create hub-vnet
      2、Create Azure Firewall
      3,Azure Firewall's Private IP address is received as a variable when creating spoke-vnet.
      4、When creating spoke-vnet, also create route table and set the resource ID of route table to the subnet of spoke-vnet.

    2. Mismanagement of Bicep Files


  • Managing too much content in one file
       Certainly, reduces dependency problems and variable passing problems. It is not a problem in small-scale development, but it is extremely inconvenient in team development for large-scale development.

  • Too much modularized management
    Modularization is convenient and easy to manage for team development.
    On the other hand, too much modularization can lead to many disadvantages, such as complex dependencies, long deployment times, and frequent references to existing resources.

    -> Prepare a bicep file for modularization only, implement only loosely coupled processes in each module as much as possible, and pass the minimum necessary variables to the module.

    3. How to handle frequently updated definitions

  • All definitions hard coated.
    In the case of incorporating definitions into properties in resources or storing them in var variables, it is easy to make a mistake or cause a bug because the bicep file is updated each time.

    -> Definitions that are frequently updated, such as Azure Firewall rules and NSG rules, should be carved out as individual definition files and managed separately.

    4. Sequence number position is shifted (ex. subnets[0].id)

  • There is no problem using arrays but be careful not to specify array numbers when referencing a resource created using arrays as an existing resource from another bicep file. It does not necessarily mean that the resource is created according to the array number. When referencing a subnet, make sure to reference child resources as follows.


    There are other ways to specify such as "name: 'vnetName/subnetName," but due to the limitation of only one "/" available in the name property, the above reference method is best. In particular, when referring to blob storage, there are cases where even grandchildren and great-grandchildren resources such as storage account, blob, container, and object are referenced.

    5. Order of scope property

    The following cases are likely to apply.
       1, Create LAW
       2, Create hub-vnet and set data transfer to LAW in vent's diagnostic settings.
       3, Created the following resources
        AMPLS (Azure Monitor Private Link Scope)
           PE (Private Endpoint)
           Private DNS Zone
       4, I want to deny Public Access Ingest of LAW, but I can't update existing resources.

       1, Create hub-vnet
       2, Create AMPLS/PE/Private DNS Zone
       3, Create LAW(Log Analytics Workspace)
       4, Refer to the existing resources in hub-vnet and set diagnostic settings.

    Extension by scope property should be done in the last process as it can be added to the existing resources at any time. In particular, RBAC, diagnostic settings, and locks, which are frequently used, should be set last.

    6. About KeyVault's getSecret()

    The getSecret method is the most secure way to obtain confidential information in bicep.

    However, there is a restriction that the getSecret function can only be used in a Module resource declaration. Therefore, when using KeyVault, you must be aware of the order in which bicep files are processed.

    The simplest approach is to create the KeyVault first.
       1, Create KeyVault
       2, Refer to the KeyVault and use getSecret in the module resource
       3, In the module file, use @secure decorator to receive
       4, Set the variable name of @secure to the necessary position

    Key Vault secret with Bicep - Azure Resource Manager | Microsoft Learn



Unlike ARM templates, bicep is a very easy language to work with. If you are interested in automating and streamlining your infrastructure, please try it out.

Thank you.


<< Chapter 1          << Chater 2

1 Comment
Version history
Last update:
‎May 11 2023 10:22 PM
Updated by: