Folder structure, deployment best practices with bicep across multiple subscriptions #5469
-
Hi everyone, I am looking for best practices to follow on resources provisioning across multiple subscriptions via CI/CD using bicep. Imagine the following folder structure. Folder structure 1: Each resource group a seperate deployment
Folder structure 2 : One deploument pipeline, scripting to detect changes and deploy them iteratively
I am planning to follow Folder structure 2 by taking the following approach
I would love to hear your ideas/best practices on handling this with many resources, that's is deployed across multiple environments (subscriptions) Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 2 replies
-
This is a great topic to cover, thank you for sharing your ideas. I can add a few ideas. Trigger workflow on different scenaros for CI
https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows example of github actions with branch and path filters on the CI triggername: .NET BOT D1 INFRA WBR
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
# https://docs.github.com/en/free-pro-team@latest/actions/reference/events-that-trigger-workflows
push:
branches: [main]
paths:
- Modules/**
- tenants/XYZ/**
pull_request:
branches: [main]
paths:
- Modules/**
- .github/workflows/app-infra-release-*.yml So another way to think about things, is as below: == 1-Feature-branch ==Modules
Environment files
== 2-Dev-branch ==Modules
Environment files
== 3-Prod-branch ==Modules
Environment files
So now you make all changes in the Dev branch (or a different temporary working or feature branch depending) and deploy there many times a day, perhaps you actually mostly deploy from a local command line into a Sandbox environment to test all template and parameter file changes (for Dev/Sandbox) and try alternate Bicep configurations Etc. Then once you have working code, you can check in the changed to Dev and trigger the CI to the dev environment. (This is an inner dev loop). If all goes well in Dev, you can then merge changes into the Test (or other) branch... trigger CI, then eventually those template changes will get to prod (Branch), perhaps that is a manual or scheduled trigger instead of CI. There can be some complexity with this, so you may want to just have: working/feature branch (when needed) or else work in Dev, then merge into the Prod (or main) branch after changes are tested, as you get a feel for this process. In this example ALL files can live in all branches, so you will have a parameter file for each unique environment, it's just a way of introducing new changes that get tested in lower lanes, without breaking or affecting upper lanes (until it's tested and you are ready). New features can always be tested. In this scenario you make your templates backwards compatible with old features. E.g. if you are using Availability Sets in Dev, Test, Prod. then all of a sudden Azure has a new feature for Availability Zones, you first roll out availability Zones to Dev. Your templates will be updated to support availability zones, however continue to have a setting to deploy the Availability sets. So it is just a feature flag, you don't remove the ability to deploy old features, as you add new features. Eventually if a feature is redundant i.e. you don't have it deployed anywhere (and you are not using it anywhere) you could remove it from your templates. |
Beta Was this translation helpful? Give feedback.
-
Another idea more directly related to your question on file structure, that I can share is below. https://github.com/brwilkinson/AzureDeploymentFramework/tree/main/ADF --> All tenant files https://github.com/brwilkinson/AzureDeploymentFramework/tree/main/ADF/tenants Tenants are directories or different subscriptions, or more based around App platforms that run in those subscriptions. └───tenants Then under an individual tenant, there is:
Example of a RG file - ALL settings for resources in an Individual resource group. Example of a Global metadata file {
"Global": {
"OrgName": "BRW",
"AppName": "AOA",
"GlobalSA": {
"namesuffix": "global"
},
"GlobalRG": {
"name": "G1"
},
"PrimaryLocation": "CentralUS",
"SecondaryLocation": "EastUS2",
"PublicIPAddressforRemoteAccess": [
"73.147.200.527/32"
],
"vmAdminUserName": "brw",
"CertURLs": [
"*.fabrikam.com",
"*.contoso.com"
],
"ADDomainName": "contoso.com",
"DomainName": "fabrikam.com",
"DomainNameExt": "fabrikam.com", example of regional file {
"Global": {
"hubRG": {
"name": "P0"
},
"hubVN": {
"name": "vn"
},
"hubKV": {
"name": "VLT01"
},
"hubAA": {
"name": "OMSAutomation"
},
"networkId": [
"10.10.",
144
],
"DNSServers": [ // Leave Empty to use AzureDNS
"10.10.144.75",
"10.10.144.76"
],
"RTName": "Hub",
"shutdownSchedulerTimeZone": "Pacific Standard Time",
"patchSchedulerTimeZone": "America/Los_Angeles"
}
} The structure (and name of environments) is mainly based around these two ideas |
Beta Was this translation helpful? Give feedback.
Another idea more directly related to your question on file structure, that I can share is below.
https://github.com/brwilkinson/AzureDeploymentFramework/tree/main/ADF
--> All bicep files https://github.com/brwilkinson/AzureDeploymentFramework/tree/main/ADF/bicep
... Etc.
--> All tenant files https://github.com/brwilkinson/AzureDeploymentFramework/tree/main/ADF/tenants
Tenants are directories or different subscriptions, or more based around App platforms that run in those subscriptions.
└───tenants
├───ABC
├───ADF
├───AOA
├───HAA
├───HUB
└───PSO
Then under an individual tenant, there is: