Created
September 29, 2015 09:26
-
-
Save RafPe/f6a43bc4332115da16fc to your computer and use it in GitHub Desktop.
Azure ARM deployment creating 4 VMs from which one has static IP address (as we will use it later for DC configuraitons ). There is no availability set and only first VM has public IP address.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #region Setup subscription and script variables | |
| ## Get up your credentials (only if using Azure AD ) | |
| # credentialSubscription = Get-Credential | |
| # Add-AzureAccount -Credential | |
| ## Enable debugging ? | |
| # $DebugPreference ='Continue' | |
| ## Login into your subscription | |
| Add-AzureAccount | |
| # using grid view select a subscription - in scripted scenario you will have the ID supplied to this script | |
| $subscriptionId = (Get-AzureSubscription |Out-GridView -Title 'Choose your subscription' -PassThru).SubscriptionId | |
| # Since user can click cancel if we dont have a subscriptionId we quit - again only for non automated scenario | |
| if ( [string]::IsNullOrEmpty( $subscriptionId ) ) { return } | |
| # If you have more than 1 subscription associated it might be handy to choose current :) | |
| Select-AzureSubscription -SubscriptionId $subscriptionId -Current | |
| ## Switch to ARM - be aware that this functionality will be deprecated | |
| ## https://github.com/Azure/azure-powershell/wiki/Deprecation-of-Switch-AzureMode-in-Azure-PowerShell | |
| Switch-AzureMode AzureResourceManager | |
| ## Check available locations | |
| $azureLocations= Get-AzureLocation | |
| ## Check which locations we have available | |
| ($azureLocations | Where-Object Name -eq ResourceGroup).Locations | |
| ## Select one location (we could use the grid view however I will deploy in West Europe) | |
| $selectedAzureLocation = 'West Europe' | |
| ## Check registrered providers - also useful when looking for resources | |
| Get-AzureProvider | |
| ## Define resources prefix that we will use across this script | |
| ## If this would be coming from variable outside of script we would need to make sure its lowercase | |
| $rscprefix = ('armdeploy').ToLower() | |
| ## Create tags to be used later | |
| $tags = New-Object System.Collections.ArrayList | |
| $tags.Add( @{ Name = 'project'; Value = 'armdeploy' } ) | |
| $tags.Add( @{ Name = 'env'; Value = 'demo' } ) | |
| ## Another way to create tags | |
| $tags = @( @{ Name='project'; Value='armdeploy' }, @{ Name='env'; Value='demo'} ) | |
| ## Number of VMs to create | |
| $VMcount=4 | |
| #endregion | |
| #region Create Azure Resource Group | |
| ## Prepare resource group name | |
| $rscgName = "rg-${rscprefix}" | |
| ## Check if our resource group exists | |
| If (!(Test-AzureResourceGroup -ResourceGroupName $rscgName)) | |
| { | |
| # Does not exist - create it - also set up deployment name | |
| $resourceGroup = New-AzureResourceGroup -Name $rscgName -Location $selectedAzureLocation -Tag $tags -DeploymentName "deploy-${rscgName}" | |
| } | |
| else | |
| { | |
| # Exists - get the resource by resource group name | |
| $resourceGroup = Get-AzureResourceGroup -Name $rscgName | |
| } | |
| #endregion | |
| #region Create Azure Storage Account | |
| # Since we need to store the virutal machine data somewhere we need storage account | |
| # we can script in a way that if it does not exist it will be created within our resource group | |
| ## Storage account name | |
| $saName="sa${rscprefix}" | |
| ## handy method to find valid types for storage account type | |
| # First we get our command | |
| $gc= get-command New-AzureStorageAccount | |
| # Then we navigate to property holding attributes which are TypeId of System.Management.Automation.ValidateSetAttribute | |
| # so it is clearly visible that those will be validate set values | |
| $gc.Parameters['Type'].Attributes.ValidValues | |
| # Based on the above lets choose a type for the storage account | |
| $saType = 'Standard_LRS' | |
| ## Here we will check if we have storage account within our resource group | |
| if (!(Test-AzureResource -ResourceName $saName -ResourceType 'Microsoft.Storage/storageAccounts' -ResourceGroupName $resourceGroup)) | |
| { | |
| # No storage account so lets go ahead and create it based on parameters we have above | |
| $sa = New-AzureStorageAccount -Name $saName -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -Type $saType | |
| } | |
| else | |
| { | |
| # Storage account exists - lets grab its resource | |
| $storageAccount = Get-AzureStorageAccount -ResourceGroupName $resourceGroup -Name $saName | |
| } | |
| ## Once this is completed lets set subscription storage account since we do have ID already | |
| Set-AzureSubscription -SubscriptionId $subscriptionId -CurrentStorageAccountName $saName | |
| #endregion | |
| #region Create Azure Virtual Network | |
| $vnetName = "vnet-${rscprefix}" | |
| $vNetsubnet1Name = "${rscprefix}-subnet1" | |
| $vNetsubnet2Name = "${rscprefix}-subnet2" | |
| # Create Virtual Network if it doesn't exist | |
| if (!(Test-AzureResource -ResourceName $vnetName -ResourceType 'Microsoft.Network/virtualNetworks' -ResourceGroupName $resourceGroup.ResourceGroupName)) | |
| { | |
| # Create first subnet | |
| $vSubnet1 = New-AzureVirtualNetworkSubnetConfig -Name $vNetsubnet1Name -AddressPrefix '10.0.1.0/24' | |
| # Create second subnet | |
| $vSubnet2 = New-AzureVirtualNetworkSubnetConfig -Name $vNetsubnet2Name -AddressPrefix '10.0.2.0/24' | |
| # Create virtual network | |
| $vNetwork = New-AzureVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -AddressPrefix '10.0.0.0/16' -Subnet $vSubnet1, $vSubnet2 -Tag $tags | |
| } | |
| else | |
| { | |
| # retrieve virtual network if already exists | |
| $vNetwork = Get-AzureVirtualNetwork -Name $vnetName -ResourceGroupName $resourceGroup.ResourceGroupName | |
| } | |
| #endregion | |
| #region Create Azure Public IP address | |
| $publicIPname = "pip-${rscprefix}" # PublicIP => pip | |
| $publicIPdns = "dns-${rscprefix}" # this will be our DNS name | |
| ## Here we check pi | |
| $retryCntDns = 0 | |
| do | |
| { | |
| $retryCntDns++ | |
| $publicIPdns="dns-${rscprefix}-${retryCntDns}" | |
| $domainAvailable = ( Test-AzureDnsAvailability -DomainQualifiedName $publicIPdns -Location $selectedAzureLocation ) | |
| } | |
| while(!$domainAvailable -or $retryCntDns -eq 3 ) | |
| # Check if we have our resource already existing | |
| if (!(Test-AzureResource -ResourceName $publicIPname -ResourceType 'Microsoft.Network/publicIPAddresses' -ResourceGroupName $resourceGroup.ResourceGroupName)) | |
| { | |
| If (!$domainAvailable) | |
| { | |
| # we dont have public domain available here - we create without DNS entry | |
| $publicIp = New-AzurePublicIpAddress -Name $publicIPname -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -AllocationMethod Dynamic -Tag $tags | |
| } | |
| else | |
| { | |
| # We do have dns available - lets create it with DNS name | |
| $publicIp = New-AzurePublicIpAddress -Name $publicIPname -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -AllocationMethod Dynamic -DomainNameLabel $publicIPdns -Tag $tags | |
| } | |
| } | |
| else | |
| { | |
| # Seems like we have already public IP address so we can just go ahead and retrieve it | |
| $publicIp = Get-AzurePublicIpAddress -Name $publicIPname -ResourceGroupName $resourceGroup.ResourceGroupName | |
| } | |
| #endregion | |
| #region Create Network Security Group & Rules | |
| # Define unique name for NSG resource | |
| $nsgName = "nsg-${rscprefix}" | |
| if (!(Test-AzureResource -ResourceName $nsgName -ResourceType 'Microsoft.Network/networkSecurityGroups' -ResourceGroupName $resourceGroup.ResourceGroupName)) | |
| { | |
| # Create RDP access rule (at the script allow from everywhere - you should investigate this for your environment security) | |
| $nsgRule_RDP = New-AzureNetworkSecurityRuleConfig ` | |
| -Name 'allow-in-rdp' ` | |
| -Description 'Allow Remote Desktop Access' ` | |
| -SourceAddressPrefix * ` | |
| -DestinationAddressPrefix * ` | |
| -Protocol Tcp ` | |
| -SourcePortRange * ` | |
| -DestinationPortRange 3389 ` | |
| -Direction Inbound ` | |
| -Access Allow ` | |
| -Priority 100 | |
| # Create Network Security Group with Rule above | |
| $nsg = New-AzureNetworkSecurityGroup -Name $nsgName -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -SecurityRules $nsgRule_RDP -Tag $tags | |
| } | |
| else | |
| { | |
| # Get NSG if already created | |
| $nsg = Get-AzureNetworkSecurityGroup -Name $nsgName -ResourceGroupName $resourceGroup.ResourceGroupName | |
| } | |
| #endregion | |
| #region Define network interfaces | |
| $networkInterfaces = @() # We will use this array to hold our network interfaces | |
| # For each VM we will create a network interface | |
| for ($count = 1; $count -le $VMcount; $count++) | |
| { | |
| $nicName = "${rscprefix}-nic${count}" | |
| if (!(Test-AzureResource -ResourceName $nicName -ResourceType 'Microsoft.Network/networkInterfaces' -ResourceGroupName $resourceGroup.ResourceGroupName)) | |
| { | |
| $nicIndex = $count – 1 | |
| # The first VM will be our domain controller/DNS and it needs static IP address | |
| if ($count -eq 1) | |
| { | |
| $networkInterfaces += New-AzureNetworkInterface -Name $nicName -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -SubnetId $vNetwork.Subnets[0].Id -NetworkSecurityGroupId $nsg.Id -IpConfigurationName 'ipconfig-dc01' -PrivateIpAddress 10.0.1.4 -PublicIpAddressId $publicIp.Id | |
| } | |
| else | |
| { | |
| $networkInterfaces += New-AzureNetworkInterface -Name $nicName -ResourceGroupName $resourceGroup.ResourceGroupName -Location $selectedAzureLocation -SubnetId $vNetwork.Subnets[0].Id -NetworkSecurityGroupId $nsg.Id | |
| } | |
| } | |
| else | |
| { | |
| # retrieve existing | |
| $networkInterfaces += Get-AzureNetworkInterface -Name $nicName -ResourceGroupName $resourceGroup.ResourceGroupName | |
| } | |
| } | |
| #endregion | |
| #region Provision virtual machines | |
| ## If you would like to you could use those to present enduser (or yourself) with visual option to choose publisher/offer and SKU | |
| ## as this is scripted version example we will use hardcoded values | |
| #$publisherName = ( Get-AzureVMImagePublisher -Location $selectedAzureLocation ).PublisherName | Out-GridView -Title 'Select a VM Image Publisher ...' -PassThru | |
| #$offerName = ( Get-AzureVMImageOffer -PublisherName $publisherName -Location $selectedAzureLocation ).Offer | Out-GridView -Title 'Select a VM Image Offer ...' -PassThru | |
| #$skuName = ( Get-AzureVMImageSku -PublisherName $publisherName -Offer $offerName -Location $selectedAzureLocation ).Skus |Out-GridView -Title 'Select a VM Image SKU' -PassThru | |
| $publisherName = 'MicrosoftWindowsServer' | |
| $offerName='WindowsServer' | |
| $skuName='2016-Technical-Preview-3-with-Containers' | |
| # Take latest version | |
| $version = 'latest' | |
| # We will use basic version of VMs - later we will be able to provision it further | |
| $vmSize = 'Basic_A1' | |
| # Get credentials for admin account - you may want to modify username | |
| $vmAdminCreds = Get-Credential Adminowski -Message 'Provide credentials for admin account' | |
| # array to hold VMs | |
| $vm = @() | |
| # Create VMs | |
| for ($count = 1; $count -le $VMcount; $count++) | |
| { | |
| # create suffixed VM name | |
| $vmName = "vm-${count}" | |
| # Check if resource already exists | |
| if (!(Test-AzureResource -ResourceName $vmName -ResourceType 'Microsoft.Compute/virtualMachines' -ResourceGroupName $resourceGroup.ResourceGroupName)) | |
| { | |
| $vmIndex = $count - 1 | |
| $osDiskLabel = 'OSDisk' | |
| $osDiskName = "${rscprefix}-${vmName}-osdisk" | |
| $osDiskUri = $sa.PrimaryEndpoints.Blob.ToString() + "vhds/${osDiskName}.vhd" | |
| $dataDiskSize = 200 # Size in GB | |
| $dataDiskLabel = 'DataDisk01' | |
| $dataDiskName = "${rscprefix}-${vmName}-datadisk01" | |
| $dataDiskUri = $sa.PrimaryEndpoints.Blob.ToString() + "vhds/${dataDiskName}.vhd" | |
| $vmConfig = New-AzureVMConfig -VMName $vmName -VMSize $vmSize | ` | |
| Set-AzureVMOperatingSystem ` | |
| -Windows ` | |
| -ComputerName $vmName ` | |
| -Credential $vmAdminCreds ` | |
| -ProvisionVMAgent ` | |
| -EnableAutoUpdate | | |
| Set-AzureVMSourceImage ` | |
| -PublisherName $publisherName ` | |
| -Offer $offerName ` | |
| -Skus $skuName ` | |
| -Version $version | | |
| Set-AzureVMOSDisk ` | |
| -Name $osDiskLabel ` | |
| -VhdUri $osDiskUri ` | |
| -CreateOption fromImage | | |
| Add-AzureVMDataDisk ` | |
| -Name $dataDiskLabel ` | |
| -DiskSizeInGB $dataDiskSize ` | |
| -VhdUri $dataDiskURI ` | |
| -CreateOption empty | | |
| Add-AzureVMNetworkInterface ` | |
| -Id $networkInterfaces[$vmIndex].Id ` | |
| -Primary | |
| New-AzureVM ` | |
| -VM $vmConfig ` | |
| -ResourceGroupName $resourceGroup.ResourceGroupName ` | |
| -Location $selectedAzureLocation ` | |
| -Tags $tags | |
| } | |
| else | |
| { | |
| # Get the VM if already provisioned | |
| $vm += Get-AzureVM -Name $vmName -ResourceGroupName $resourceGroup.ResourceGroupName | |
| } | |
| } | |
| #endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment