I want to create my resource groups and my virtual network in this part of the blog series. To create these resources will use a combination of Bicep files, where I split my code into an execution file with parameters and a generic template file. I am doing this to not limit my options for deploying environments. In fact, the last post in this series will be to deploy the same environment but switching the execution code with a PowerShell script.
The first thing I want to do is creating a new branch in my GitHub repository. I will do this from VS Code by clicking the branch icon in the bottom left corner and then selecting “Create new branch” in the top midsection of the screen.
I will name my branch “RG_and_vNet”
I always verify that the branch I just created is also the branch I am working in. I do this by checking the branch name in the lower-left corner.
I can now update my resource group file to contain the resource groups I want to create. I have done this in the code below. Finally, I will save the updated ResourceGroup.bicep file and commit it to GitHub.
targetScope = 'subscription'
param Location string = 'WestEurope'
param companyPrefix string = 'bicep'
var ResourceGroups = [
'rg-${companyPrefix}-sharedservices-network-001'
'rg-${companyPrefix}-sharedservices-vm-001'
'rg-${companyPrefix}-citrix-network-001'
'rg-${companyPrefix}-citrix-vm-001'
'rg-${companyPrefix}-citrix-workers-001'
]
resource resourcegroups 'Microsoft.Resources/resourceGroups@2021-01-01' = [for ResourceGroup in ResourceGroups: {
location: Location
name: ResourceGroup
}]
Next, I want to create my Bicep file for the virtual network in Azure. I found the documentation for the template here, but it contains more options that I want to use, so after I removed all the items I don’t want to use, it looks like this.
param Name string
param Prefix string
param Subnets array
param Location string
param dnsServers array
resource vnet 'Microsoft.Network/virtualNetworks@2021-02-01' = {
name: Name
location: Location
properties: {
addressSpace: {
addressPrefixes: [
Prefix
]
}
dhcpOptions: {
dnsServers: dnsServers
}
subnets: [for Subnet in Subnets: {
name: Subnet.name
properties: {
addressPrefix: Subnet.Prefix
}
}]
}
}
output name string = vnet.name
The code above will create a virtual network with custom DNS servers and an array of subnets. I will save this file in a new folder called “Templates” placed in a new folder called “Network”. I like to organize my code this way to easier find the files I want to edit.
I now have the template for my virtual network, and I am now ready to create the execution code for the virtual networks I want to create. First, I will create a new Bicep file called “DeployNetwork.bicep” and place it in the “Network” folder. I find it easiest to write the modules first and then my parameters and variables afterward. I will create two modules, one for each vNet I want to create. In the code below, you can see that I have an entry in each module for each parameter I created in my template file. I will normally use variables or parameters for my execution code, but this is not strictly needed. I have two modules, one for a Citrix vNet and one for Shared Services vNet. Each of the modules has a scope set for a resource group. The bicep deployment can be scoped to either management group, subscription, or resource group. Since I want to deploy into two resource groups, I need to target my execution file at the subscription level.
module CitrixvNet './Templates/vNet.bicep' = {
name: 'Citrix-vNet-Deployment'
params: {
dnsServers: Citrix_vNet_dnsServers
Location: Location
Subnets: Citrix_vNet_Subnets
Name: Citrix_vNetName
Prefix: Citrix_vNet_Prefix
}
dependsOn: [
SharedservicevNet
]
scope: resourceGroup(Citrix_ResourceGroup)
}
module SharedservicevNet './Templates/vNet.bicep' = {
name: 'Sharedservice-vNet-Deployment'
params: {
dnsServers: Sharedservice_vNet_dnsServers
Location: Location
Subnets: Sharedservice_vNet_Subnets
Name: Sharedservice_vNet_Name
Prefix: Sharedservice_vNet_Prefix
}
scope: resourceGroup(Sharedservice_ResourceGroup)
}
Now that I have the modules in place, I can see which parameters and variables I need to create, so I will go ahead and do that. Below, I put the targetScope as the first line to indicate that this deployment is targeted at the subscription level. Next, I have a parameter called “companyPrefix”, which has a default value of “bicep”. I created this parameter to allow the execution of different environments based on either the value in the file or a value coming from the Github Actions execution. This could be from a RestAPI call, for instance.
targetScope = 'subscription'
param companyPrefix string = 'bicep'
var Location = 'WestEurope'
var Sharedservice_ResourceGroup = 'rg-${companyPrefix}-sharedservices-network-001'
var Sharedservice_vNet_Name = 'vnet-${companyPrefix}-sharedservices-001'
var Sharedservice_vNet_Prefix = '172.16.0.0/16'
var Sharedservice_vNet_Subnets = [
{
name: 'GatewaySubnet'
prefix: '172.16.0.0/26'
}
{
name: 'snet-sharedservices-adds-001'
prefix: '172.16.0.64/26'
}
]
var Sharedservice_vNet_dnsServers = [
'192.168.10.10'
]
var Citrix_ResourceGroup = 'rg-${companyPrefix}-citrix-network-001'
var Citrix_vNetName = 'vnet-${companyPrefix}-citrix-001'
var Citrix_vNet_Prefix = '172.17.0.0/16'
var Citrix_vNet_Subnets = [
{
name: 'snet-citrix-vm-001'
prefix: '172.17.0.0/26'
}
{
name: 'snet-citrix-workers-001'
prefix: '172.17.1.0/24'
}
{
name: 'snet-citrix-workers-002'
prefix: '172.17.2.0/24'
}
]
var Citrix_vNet_dnsServers = [
'192.168.10.10'
]
I now have the code for my virtual networks ready, and before I move on, I want to ensure that it is running as expected using Github actions. First, I will update my deploy.yml file to include the virtual network deployment, so the file now looks like the code below. Notice that I have changed the branch for push triggers to run for my working branch and not the main branch. Normally, I have actions run on either a development branch or the main branch, but this is easier for the current scenario since we are testing this branch.
name: CI
# Controls when the action will run.
on:
# Triggers the workflow on push or pull request events but only for the main branch
push:
branches: [ RG_and_vNet ]
pull_request:
branches: [ main ]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS_BLOGSERIES }}
- name: Deploy resource group
uses: azure/arm-deploy@main
with:
scope: subscription
subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION }}
region: westeurope
template: ./ResourceGroup/ResourceGroup.bicep
- name: Deploy virtual network
uses: azure/arm-deploy@main
with:
scope: subscription
subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION }}
region: westeurope
template: ./Network/DeployNetwork.bicep
I now have the following resource groups in Azure and I also have the virtual networks as shown below.
I now know that my code can deploy my resource groups and virtual networks, so the last thing I want to cover in this part of the series is peering the two virtual networks together. So, I will create a new template under my network folder and call it “Peering.bicep”. I found the documentation on network peering here , and I adjusted that to fit my needs, and that created the code below. Notice that I have a lookup for my remote virtual network to make it easier to read and deploy the code.
param virtualNetworkName string
param allowForwardedTraffic bool = true
param allowGatewayTransit bool = false
param allowVirtualNetworkAccess bool = true
param useRemoteGateways bool = true
param remoteResourceGroup string
param remoteVirtualNetworkName string
resource remotevnet 'Microsoft.Network/virtualNetworks@2021-02-01' existing = {
name: remoteVirtualNetworkName
scope: resourceGroup(remoteResourceGroup)
}
resource peering 'Microsoft.Network/virtualNetworks/virtualNetworkPeerings@2021-02-01' = {
name: '${virtualNetworkName}/Peering-To-${remoteVirtualNetworkName}'
properties: {
allowForwardedTraffic: allowForwardedTraffic
allowGatewayTransit: allowGatewayTransit
allowVirtualNetworkAccess: allowVirtualNetworkAccess
useRemoteGateways: useRemoteGateways
remoteVirtualNetwork: {
id: remotevnet.id
}
}
}
Next, I will add the peering modules to the “DeployNetwork.bicep” file to have all my virtual network configurations in one deployment file. I have added the lines below into the deployment file and notice that I use the output from the virtual network deployment module as input to my peering module.
module CitrixPeering './Templates/Peering.bicep' = {
name: 'CitrixvNetPeering'
params: {
allowForwardedTraffic: true
allowGatewayTransit: false
allowVirtualNetworkAccess: true
remoteResourceGroup: 'rg-${companyPrefix}-sharedservices-network-001'
remoteVirtualNetworkName: 'vnet-${companyPrefix}-sharedservices-001'
useRemoteGateways: false
virtualNetworkName: CitrixvNet.outputs.name
}
dependsOn: [
CitrixvNet
]
scope: resourceGroup(Citrix_ResourceGroup)
}
module SharedservicePeering './Templates/Peering.bicep' = {
name: 'SharedServicevNetPeering'
params: {
allowForwardedTraffic: true
allowGatewayTransit: true
allowVirtualNetworkAccess: true
remoteResourceGroup: 'rg-${companyPrefix}-citrix-network-001'
remoteVirtualNetworkName: 'vnet-${companyPrefix}-citrix-001'
useRemoteGateways: false
virtualNetworkName: SharedservicevNet.outputs.name
}
dependsOn: [
CitrixPeering
]
scope: resourceGroup(Sharedservice_ResourceGroup)
}
I can now save the two new files and commit them to my repository. I don’t need to change anything for the Github action since I updated the deployment file I already configured. After the deployment, I can see that my peering is working.
Before I close this part of the blog series, I will merge my changes into the main branch and delete the working branch for the network. This is done in Github by going to “Pull requests” and then click on “Compare & pull request”.
I fill out the fields as shown below with new title and description.
Github will list my commits and run tests to ensure that my code won’t conflict with the existing code. Finally, when all the lights are green, I will click on “Merge pull request”.
When the pull request has been merged, I will delete the branch I merge code from.
This will end this part of the blog series. Next, I will create the VPN connection from Azure to my on-premises lab environment.
Stay tuned.
Comments