Virtual Datacenter Concept | 3 of 10 | Resource Groups

Welcome back to the Azure Virtual Datacenter Concept blog post series.

In our previous posts about naming conventions and Azure Governance, we’ve defined our rules of play. Now it’s time to start populating our Azure environment with some Resource Groups.

Azure Governance Scaffold : Resource Groups
Let’s talk resources!

When deploying new resources in Azure, they reside in the Azure Resource Manager model. The Azure Resource Manager model is the successor of the Azure Service Management model which is often referred to as Azure v1 or Azure Classic. Since we are deploying resources in Azure, we want some kind of containerization or logical management layer on top of that. And that is exactly why we need a resource group before we can deploy a resource in Azure.

A resource group is a logical boundary that can organize your resources based on the environment, application or other specific characteristics. We can harden our resource group from unwanted changes by implementing role based access controls and resource locks.

Resource Manager request model
Azure Resource Manager Model
Stuff to think about

Prior to deploying our first resource in a resource group, we have a couple of recommendations and/or limitations that we need to take care of:

  • A resource can only exist in one resource group
  • Resources can be moved from one resource group to another group
  • Resources are able to communicate or connect to other resource groups
  • Resource groups can be controlled by specific RBAC controls or resource locks.
    • Takeway: Our advice is to assign specific roles of access to the resource groups and apply a delete lock by default.
    • Tip: We can force these roles and locks with Azure Policy
  • Resource groups can contain resources that are located in different regions
    • Takeaway: Our advice is to keep your resources within the same region as your resource group.
    • Tip: We can force this behavior via Azure Policy
Ready, set, GO? STOP! Let’s first take a couple of design decisions.

Taking the above information into account, we don’t want to go and start deploying resources and resource groups via the Azure Portal. Rule of thumb is to use the Azure Portal as much as you can for view / read only actions and perform your deployments with ARM templates, powershell or CLI.

Now before we are going to deploy our base set of resource groups, let’s have some thought on which resource groups we are going to deploy and why. Below table gives you an example that you can use in any of your Azure designs to provide an holistic overview of the required resource groups. Have a look here at how naming conventions are provisioned / enforced.

Resource Group NameResources
HUB
<cus>-hub-storage-rgAll components related to central storage
<cus>-hub-management-rgAll components related to central management tools
<cus>-hub-network-rgAll components related to central networking
<cus>-hub-mig-rgAll components related to migration workloads
<cus>-hub-backup-rgAll components related to the central backup instance
<cus>-hub-identity-rgAll components related to the central Identity instance
ENV
<cus>-dev-app-rgAll components related to the development application tier
<cus>-dev-web-rgAll components related to the development web tier
<cus>-dev-network-rgAll components related to the development network tier
<cus>-dev-db-rgAll components related to the development database tier
<cus>-dev-storage-rgAll components related to the development storage tier

The table above gives you guidance on how to deploy a central HUB for resources and create a set of resource groups per environment.

Our environment specific resource groups are designed in a way that we can re-utilize them for multiple purposes.

Design ready, let’s go!

Below PowerShell script can be used to deploy a tier based environment starting from a simple hub and production approach to a full blow DTAP (Development, Test, Acceptance, Production) environment.

Powershell Script

##################

Param(
  [string]$RG_PurposeHUB,
  [string]$RG_PurposePRD,
  [string]$RG_PurposeACC,
  [string]$RG_PurposeTST,
  [string]$RG_PurposeDEV,
  [string]$Cus,
  [string]$fullLocation,
  [string]$owner,
  [string]$EnvironmentTier

)


#####################################################################################
######## START OF NAMING CONVENTION RESOURCE GROUPS HUB,PRD,DEV,TST ########
#####################################################################################

################### HUB
$HUBRGID = $Cus + '-' + $RG_PurposeHUB + '-' + 'identity' + '-rg'
$HUBRGSTOR = $Cus + '-' + $RG_PurposeHUB + '-' + 'storage' + '-rg'
$HUBRGMGM = $Cus + '-' + $RG_PurposeHUB + '-' + 'management' + '-rg'
$HUBRGNET = $Cus + '-' + $RG_PurposeHUB + '-' + 'network' + '-rg'
$HUBRGMIG = $Cus + '-' + $RG_PurposeHUB + '-' + 'mig' + '-rg'
$HUBRGRSV = $Cus + '-' + $RG_PurposeHUB + '-' + 'backup' + '-rg'

################### PRD

$PRDRGAPP = $Cus + '-' + $RG_PurposePRD + '-' + 'app' + '-rg'
$PRDRGDB = $Cus + '-' + $RG_PurposePRD + '-' + 'db' + '-rg'
$PRDRGSTOR = $Cus + '-' + $RG_PurposePRD + '-' + 'storage' + '-rg'
$PRDRGNET = $Cus + '-' + $RG_PurposePRD + '-' + 'network' + '-rg'
$PRDRGWEB = $Cus + '-' + $RG_PurposePRD + '-' + 'web' + '-rg'

################### ACC

$ACCRGAPP = $Cus + '-' + $RG_PurposeACC + '-' + 'app' + '-rg'
$ACCRGDB = $Cus + '-' + $RG_PurposeACC + '-' + 'db' + '-rg'
$ACCRGSTOR = $Cus + '-' + $RG_PurposeACC + '-' + 'storage' + '-rg'
$ACCRGNET = $Cus + '-' + $RG_PurposeACC + '-' + 'network' + '-rg'
$ACCRGWEB = $Cus + '-' + $RG_PurposeACC + '-' + 'web' + '-rg'

################### TST

$TSTRGAPP = $Cus + '-' + $RG_PurposeTST + '-' + 'app' + '-rg'
$TSTRGDB = $Cus + '-' + $RG_PurposeTST + '-' + 'db' + '-rg'
$TSTRGSTOR = $Cus + '-' + $RG_PurposeTST + '-' + 'storage' + '-rg'
$TSTRGNET = $Cus + '-' + $RG_PurposeTST + '-' + 'network' + '-rg'
$TSTRGWEB = $Cus + '-' + $RG_PurposeTST + '-' + 'web' + '-rg'

################### DEV

$DEVRGAPP = $Cus + '-' + $RG_PurposeDEV + '-' + 'app' + '-rg'
$DEVRGDB = $Cus + '-' + $RG_PurposeDEV + '-' + 'db' + '-rg'
$DEVRGSTOR = $Cus + '-' + $RG_PurposeDEV + '-' + 'storage' + '-rg'
$DEVRGNET = $Cus + '-' + $RG_PurposeDEV + '-' + 'network' + '-rg'
$DEVRGWEB = $Cus + '-' + $RG_PurposeDEV + '-' + 'web' + '-rg'

#####################################################################################
######## END OF NAMING CONVENTION RESOURCE GROUPS HUB,PRD,DEV,TST ########
#####################################################################################



#####################################################################################
######## START OF CREATION RESOURCE GROUPS HUB,PRD,DEV,TST,ACC ########
#####################################################################################


function new-resourcegroups
{
Param ([string]$fullLocation,[string]$owner,[string]$rsgapp,[string]$rsgdb,[string]$rsgstor,[string]$rsgnet,[string]$rsgweb,[string]$rsgpurpose)

            New-AzResourceGroup -Name $rsgapp -Location $fullLocation -Tag @{Environment="$rsgpurpose";Purpose="Application";Owner="$owner"}
            New-AzResourceGroup -Name $rsgdb -Location $fullLocation -Tag @{Environment="$rsgpurpose";Purpose="Database";Owner="$owner"}
            New-AzResourceGroup -Name $rsgstor -Location $fullLocation -Tag @{Environment="$rsgpurpose";Purpose="Storage";Owner="$owner"}
            New-AzResourceGroup -Name $rsgnet -Location $fullLocation -Tag @{Environment="$rsgpurpose";Purpose="Networking";Owner="$owner"}
            New-AzResourceGroup -Name $rsgweb -Location $fullLocation -Tag @{Environment="$rsgpurpose";Purpose="Web";Owner="$owner"}
}


function new-hubresourcegroups
{
Param ([string]$fullLocation,[string]$owner,[string]$rsgmgm,[string]$rsgdb,[string]$rsgstor,[string]$rsgnet,[string]$rsgweb,[string]$rsgpurpose,[string]$rsgmig,[string]$rsgrsv,[string]$rsgidentity)

            ### HUB AZ Powershell
            New-AzResourceGroup -Name $rsgstor -Location $fullLocation -Tag @{Environment="$RG_PurposeHUB";Purpose="Storage";Owner="$owner"}
            New-AzResourceGroup -Name $rsgmgm -Location $fullLocation -Tag @{Environment="$RG_PurposeHUB";Purpose="Management";Owner="$owner"}
            New-AzResourceGroup -Name $rsgnet -Location $fullLocation -Tag @{Environment="$RG_PurposeHUB";Purpose="Networking";Owner="$owner"}        
            New-AzResourceGroup -name $rsgmig -Location $fullLocation -Tag @{Environment="$RG_PurposeHUB";Purpose="Migration";Owner="$owner"}
            New-AzResourceGroup -Name $rsgidentity -Location $fullLocation -Tag @{Environment="$rsgpurposeHUB";Purpose="Identity";Owner="$owner"}     
            New-AzResourceGroup -Name $rsgrsv -Location $fullLocation -Tag @{Environment="$rsgpurpose";Purpose="Backup";Owner="$owner"}   
          }



$EnvironmentTier
   
# Select the setup steps required for this environment
    Switch ($EnvironmentTier)
    {
        1 {
            # new HUB Resource Groups
            new-hubresourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $HUBRGAPP -rsgdb $HUBRGDB -rsgstor $HUBRGSTOR -rsgnet $HUBRGNET -rsgweb $HUBRGWEB -rsgpurpose $RG_PurposeHUB -rsgmgm $HUBRGMGM -rsgmig $HUBRGMIG -rsgidentity $HUBRGID -rsgrsv $HUBRGRSV
            # new PRD Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $PRDRGAPP -rsgdb $PRDRGDB -rsgstor $PRDRGSTOR -rsgnet $PRDRGNET -rsgweb $PRDRGWEB -rsgpurpose $RG_PurposePRD 
          }
        2 {
            # new HUB Resource Groups
            new-hubresourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $HUBRGAPP -rsgdb $HUBRGDB -rsgstor $HUBRGSTOR -rsgnet $HUBRGNET -rsgweb $HUBRGWEB -rsgpurpose $RG_PurposeHUB -rsgmgm $HUBRGMGM -rsgmig $HUBRGMIG -rsgidentity $HUBRGID -rsgrsv $HUBRGRSV
            # new PRD Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $PRDRGAPP -rsgdb $PRDRGDB -rsgstor $PRDRGSTOR -rsgnet $PRDRGNET -rsgweb $PRDRGWEB -rsgpurpose $RG_PurposePRD 
            # new ACC Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $ACCRGAPP -rsgdb $ACCRGDB -rsgstor $ACCRGSTOR -rsgnet $ACCRGNET -rsgweb $ACCRGWEB -rsgpurpose $RG_PurposeACC

          }
        3 {
            # new HUB Resource Groups
            new-hubresourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $HUBRGAPP -rsgdb $HUBRGDB -rsgstor $HUBRGSTOR -rsgnet $HUBRGNET -rsgweb $HUBRGWEB -rsgpurpose $RG_PurposeHUB -rsgmgm $HUBRGMGM -rsgmig $HUBRGMIG -rsgidentity $HUBRGID -rsgrsv $HUBRGRSV
            # new PRD Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $PRDRGAPP -rsgdb $PRDRGDB -rsgstor $PRDRGSTOR -rsgnet $PRDRGNET -rsgweb $PRDRGWEB -rsgpurpose $RG_PurposePRD 
            # new ACC Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $ACCRGAPP -rsgdb $ACCRGDB -rsgstor $ACCRGSTOR -rsgnet $ACCRGNET -rsgweb $ACCRGWEB -rsgpurpose $RG_PurposeACC
            # new TST Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $TSTRGAPP -rsgdb $TSTRGDB -rsgstor $TSTRGSTOR -rsgnet $TSTRGNET -rsgweb $TSTRGWEB -rsgpurpose $RG_PurposeTST
           }
        4 {
            # new HUB Resource Groups
            new-hubresourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $HUBRGAPP -rsgdb $HUBRGDB -rsgstor $HUBRGSTOR -rsgnet $HUBRGNET -rsgweb $HUBRGWEB -rsgpurpose $RG_PurposeHUB -rsgmgm $HUBRGMGM -rsgmig $HUBRGMIG -rsgidentity $HUBRGID -rsgrsv $HUBRGRSV
            # new PRD Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $PRDRGAPP -rsgdb $PRDRGDB -rsgstor $PRDRGSTOR -rsgnet $PRDRGNET -rsgweb $PRDRGWEB -rsgpurpose $RG_PurposePRD 
            # new ACC Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $ACCRGAPP -rsgdb $ACCRGDB -rsgstor $ACCRGSTOR -rsgnet $ACCRGNET -rsgweb $ACCRGWEB -rsgpurpose $RG_PurposeACC
            # new TST Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $TSTRGAPP -rsgdb $TSTRGDB -rsgstor $TSTRGSTOR -rsgnet $TSTRGNET -rsgweb $TSTRGWEB -rsgpurpose $RG_PurposeTST
            # new DEV Resource Groups
            new-resourcegroups -fullLocation $fullLocation -owner $owner -rsgapp $DEVRGAPP -rsgdb $DEVRGDB -rsgstor $DEVRGSTOR -rsgnet $DEVRGNET -rsgweb $DEVRGWEB -rsgpurpose $RG_PurposeDEV
          }
    }


#####################################################################################
######## END OF CREATION RESOURCE GROUPS HUB,PRD,DEV,TST ########
#####################################################################################

If we save the script as “1._Create_Az_ResourceGroups_v2.ps1” and run it with the parameters below this should give us the following result.

.\1._Create_Az_ResourceGroups_v2.ps1 -RG_PurposeHUB "hub" -RG_PurposePRD "prd" -RG_PurposeACC "acc" -RG_PurposeTST "tst" -RG_PurposeDEV "dev" -Cus "cus" -fullLocation "westeurope" -owner "Yannick Dils" -EnvironmentTier 4

View / Read-only on the Azure Portal

hub or central resource groups
hub resource groups
production resource groups
prd resource groups

Summary

Thank you for reading through the resource groups blog post, our aim was to give you an overview and set of best practices on how to implement resource groups based on a couple of design standards. When looking at the virtual datacenter concept. We now have a clear naming standard with a set of policies that are being applied to our management groups, subscriptions and resource groups. Our resource groups have been pre-configured in order to facilitate the deployment of our future resources.

What’s next?

The following aspects of the virtual datacenter concept will be highlighted in the following upcoming posts:

  • Virtual Datacenter Concept – 4 of 10 – Virtual Networking
  • Virtual Datacenter Concept – 5 of 10 – Cloud Storage
  • Virtual Datacenter Concept – 6 of 10 – Identity Options
  • Virtual Datacenter Concept – 7 of 10 – Log Analytics
  • Virtual Datacenter Concept – 8 of 10 – Security
  • Virtual Datacenter Concept – 9 of 10 – Business Continuity
  • Virtual Datacenter Concept – 10 of 10 – Automation

Missed a part or want to review a previous section? Be sure to check out my previous posts:

Leave a Reply

Your email address will not be published. Required fields are marked *