A few days are left before the start of the first noted event of the 2014 Powershell Winter Scripting Games. In the meantime I have decided to write a blog post on moving your first steps in a Windows Azure environment with Powershell. This can be particularly useful if you wanted to take part in the Games and still don't have an environment with Powershell 4.0 installed, since you can create a few Windows 2012 R2 VMs with the following quick steps.
As an introduction, know that in these times there is a growing interest for Cloud technologies and Microsoft has answered the need for outsourced infrastructures with the possibility to run your IT as a Service (IaaS) in its Cloud datacenters. Windows Azure is the name Microsoft gave back in 2008 to its Cloud application platform, which became available on February 2010.
Microsoft is offering a one-month free trial, so activate your subscription and download and install the latest version of Windows Azure Powershell, which is 0.7.2.1 at the time of writing.
The package will install a new module for Azure:
Get-Module Azure -ListAvailable Directory: C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell ModuleType Name ExportedCommands ---------- ---- ---------------- Binary Azure {Disable-AzureServiceProjectRemoteDesktop, E
At this point you don't even need to import any module since starting with Powershell 3.0 there is a module auto-load feature: so type the cmdlet you need and PowerShell will load the Azure module for you.
As a general information, the last version of the Azure module comes with 242 cmdlets. The most common nouns in this module are the following ones:
gcm -Module azure | group noun | sort count -desc | select name, count -first 10Name Count ---- ----- AzureVM 9 WAPackVM 9 AzureWebsite 8 AzureService 6 AzureDeployment 5 AzureVMImage 5 AzureSqlDatabaseServerFirewallRule 4 AzureAclConfig 4 AzureStorageAccount 4 AzureVNetGateway 4
The next step is to configure Windows Azure Active Directory authentication in PowerShell with Add-AzureAccount (this is much easier than using the combination of Get-AzurePublishSettingsFile and Import-AzurePublishSettingsFile). For a basic usage, this cmdlet takes no parameter: it just opens a browser dialog box asking for the Microsoft Account that you registered to manage your subscriptions.
You can check that you have properly bound to your account with Get-Azureaccount:
Get-AzureAccount Name ActiveDirectories ---- ----------------- happysysadm.com {{ ActiveDirectoryTenantId = 5e649293-9...
and with Get-AzureSubscription:
Get-AzureSubscription SubscriptionName : Visual Studio Ultimate con MSDN SubscriptionId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ServiceEndpoint : https://management.core.windows.net/ ActiveDirectoryEndpoint : https://login.windows.net/ ActiveDirectoryTenantId : 5e649293-9842-111a-b2ab-d234d8cc5f54 IsDefault : True Certificate : CurrentStorageAccountName : CurrentCloudStorageAccount : ActiveDirectoryUserId : happysysadm.com
As you can see in the output of the last cmdlet, the CurrentStorageAccountName is empty. If you tried to build a new virtual machine at this moment you would get the following error:
New-AzureQuickVM : CurrentStorageAccountName is not accessible. Ensure the current storage account is accessible and in the same location or affinity group as your cloud service.
The solution is to associate your Azure storage account with your subscription prior to deploying any new VM:
Set-AzureSubscription -SubscriptionName (Get-AzureSubscription).SubscriptionName -CurrentStorageAccount (Get-AzureStorageAccount).label
Once your subscription is filled with all the proper information, nothing easier than using New-AzureQuickVM to create and provision your new Windows Azure virtual machines.
Here's the syntax for this cmdlet as extracted from the help:
man New-AzureQuickVM NAME New-AzureQuickVM SYNOPSIS SYNTAX New-AzureQuickVM -ImageName-Linux -LinuxUser -Password -ServiceName [-AffinityGroup ] [-AvailabilitySetName ] [-DnsSettings ] [-HostCaching ] [-InstanceSize ] [-Location ] [-MediaLocation ] [-Name ] [-SSHKeyPairs ] [-SSHPublicKeys ] [-SubnetNames ] [-VNetName ] [ ] New-AzureQuickVM -AdminUsername -ImageName -Password -ServiceName -Windows [-AffinityGroup ] [-AvailabilitySetName ] [-Certificates ] [-DisableWinRMHttps] [-DnsSettings ] [-EnableWinRMHttp] [-HostCaching ] [-InstanceSize ] [-Location ] [-MediaLocation ] [-Name ] [-NoExportPrivateKey] [-NoWinRMEndpoint] [-SubnetNames ] [-VNetName ] [-WaitForBoot] [-WinRMCertificate ] [-X509Certificates ] [ ] DESCRIPTION The New-AzureQuickVM sets the configuration for a new virtual machine and creates the virtual machine. It can create a new Windows Azure service, or deploy the new virtual machine into an existing service if neither -Location or -AffinityGroup is specified. RELATED LINKS Get-AzureVM New-AzureVMConfig Remove-AzureVM New-AzureVM REMARKS To see the examples, type: "get-help New-AzureQuickVM -examples". For more information, type: "get-help New-AzureQuickVM -detailed". For technical information, type: "get-help New-AzureQuickVM -full". For online help, type: "get-help New-AzureQuickVM -online"
Before we deploy a new test virtual machine, I want to make a short digression on the VM sizes you can choose from. There are eight possible sizes, starting from Extra Small to A7:
As you can see in the image above, Small is the minimum recommended size for a Production VM (and with the free trial you can run two of them for a whole month), while Large is the minimum for a SQL node.
Keep in mind that the daily cost for each of this virtual machine size is different, so plan accordingly to your budget:
- XS 11€ per VM per month
- Small 49€
- Medium 99€
- Large 199€
- A5 221€
- ExtraLarge 398€
- A6 443€
- A7 886€
Let's move to the provisioning of your first VM in just a one-liner:
New-AzureQuickVM -Windows -ServiceName 'cloudoftheday' -Name 'cloudvm01' -ImageName (Get-AzureVMImage | Where Label -Like "Windows Server 2012 R2 Datacenter")[-1].ImageName -AdminUsername 'happysysadm' -Password 'VerySecurePassw0rd' -InstanceSize Small -Location 'west europe'
Once the cmdlet ends, your VM is already available for use with the OS installed, RDP and WinRM enabled on their standard ports. Public ports for these services are also opened trough a Port Address Translation (PAT) mechanism.
Now, I haven't been succesfull in using the New-AzureQuickVM cmdlet againts an existing service. The cmdlet fails with the following error message:
"New-AzureQuickVM : ResourceNotFound: The deployment name 'existingcloud' does not exist."
It must be a bug, since in the cmdlet help it says that I can specify an existing service name:
-ServiceNameSpecifies the new or existing service name.
So for the moment you have to stick to creating a new Service Name each time you run this cmdlet...
As a side note, I am deploying my VMs using 'West Europe' as location (The 'west europe' datacenter is in Amsterdam). Microsoft Public Cloud offers various possible locations and you should choose the one near to you:
Get-AzureLocation AvailableServices : {Compute, Storage, PersistentVMRole, HighMemory} DisplayName : East Asia Name : East Asia OperationDescription : Get-AzureLocation OperationId : f89f3076-6587-59ba-b9ff-4e47e4658c82 OperationStatus : Succeeded AvailableServices : {Compute, Storage, PersistentVMRole, HighMemory} DisplayName : Southeast Asia Name : Southeast Asia OperationDescription : Get-AzureLocation OperationId : f89f3076-6587-59ba-b9ff-4e47e4658c82 OperationStatus : Succeeded AvailableServices : {Compute, Storage, PersistentVMRole, HighMemory} DisplayName : North Europe Name : North Europe OperationDescription : Get-AzureLocation OperationId : f89f3076-6587-59ba-b9ff-4e47e4658c82 OperationStatus : Succeeded AvailableServices : {Compute, Storage, PersistentVMRole, HighMemory} DisplayName : West Europe Name : West Europe OperationDescription : Get-AzureLocation OperationId : f89f3076-6587-59ba-b9ff-4e47e4658c82 OperationStatus : Succeeded AvailableServices : {Compute, Storage, PersistentVMRole, HighMemory} DisplayName : East US Name : East US OperationDescription : Get-AzureLocation OperationId : f89f3076-6587-59ba-b9ff-4e47e4658c82 OperationStatus : Succeeded AvailableServices : {Compute, Storage, PersistentVMRole, HighMemory} DisplayName : West US Name : West US OperationDescription : Get-AzureLocation OperationId : f89f3076-6587-59ba-b9ff-4e47e4658c82 OperationStatus : Succeeded
Now the question that comes to my mind is whether I can deploy many VMs at the same time using a Workflow in Powershell 4.0. Let's see the answer. I have prepared the following workflow as an example:
WorkFlow Deploy-AzureVm { [cmdletbinding()] param( [Int]$Quantity = 5, [String]$ImageName = "Windows Server 2012 R2 Datacenter", [String]$ServiceName, [String]$Prefix, [String]$AdminUsername, [String]$Password, [String]$InstanceSize ) #Retrieving image name in Windows Azure repository $Image = (Get-AzureVMImage | Where Label -Like $ImageName)[-1].ImageName "Deploying first VM with Location parameter" New-AzureQuickVM -Windows -ServiceName $ServiceName ` -Name "$Prefix" -ImageName $Image ` -AdminUsername $AdminUsername -Password $Password -InstanceSize $InstanceSize -Location "west europe" foreach -parallel ($VM in 2..$Quantity){ "Deploying VM $Prefix$VM" New-AzureQuickVM -Windows -ServiceName $ServiceName ` -Name "$Prefix$VM" -ImageName $Image ` -AdminUsername $AdminUsername -Password $Password -InstanceSize $InstanceSize } }
Once I run it I get the following problem:
Deploy-AzureVm -Quantity 3 -ImageName "Windows Server 2012 R2 Datacenter" -ServiceName "WorkflowCloud007" `
>> -Prefix "VMcloud16Jan" -AdminUsername 'happysysadm' -Password 'VerySecurePassw0rd' -InstanceSize Small
>>
Deploying first VM with Location parameter
PSComputerName : localhost
PSSourceJobInstanceId : de553192-bd99-4c46-be19-505f0007e819
OperationDescription : New-AzureQuickVM
OperationId : 2438374c-egb1-529d-af64-ce5b879ee3e1
OperationStatus : Succeeded
PSComputerName : localhost
PSSourceJobInstanceId : de553192-bd99-4c46-be19-505f0007e819
OperationDescription : New-AzureQuickVM
OperationId : 2438374c-egb1-529d-af64-ce5b879ee3e1
OperationStatus : Succeeded
Deploying VM VMcloud16Jan3
Deploying VM VMcloud16Jan2
New-AzureQuickVM : ConflictError: Windows Azure is currently performing an operation with x-ms-requestid
123a90e4325857d986b25524987b7d9b on this deployment that requires exclusive access.
At Deploy-AzureVm:20 char:20
+
+ CategoryInfo : CloseError: (:) [New-AzureQuickVM], CloudException
+ FullyQualifiedErrorId : Microsoft.WindowsAzure.Commands.ServiceManagement.IaaS.PersistentVMs.NewQuickVM
+ PSComputerName : [localhost]
PSComputerName : localhost
PSSourceJobInstanceId : de553192-bd99-4c46-be19-505f0007e819
OperationDescription : New-AzureQuickVM
OperationId : 2438374c-egb1-529d-af64-ce5b879ee3e1
OperationStatus : Succeeded
It looks like operations like virtual machine provisioning or deletion keep an exclusive access on the deployment engine and don't allow for parallel virtual machine setup in the same Windows Azure environment. I haven't found a solution to this and that's sad because I liked the idea of deploying a whole IaaS in just one Powershell Workflow. But, I am sure the technology under the hood is making huge steps forward and I would expect such a feature like Powershell workflow to be fully leveraged in the first major release of the Azure module. Meanwhile we have to stick to serial execution of our VM provisioning, which is nonethless extremely trivial.
Performancewise, the rapidity of the deployment of a new VM in the Cloud is pretty stunning, with the vhd disks deployed in a bunch of seconds and the VM started in a couple of minutes:
Measure-Command -expression { New-AzureQuickVM -Windows -ServiceName 'cloudofthedayxx001' -Name 'abc01' -ImageName (Get-AzureVMImage | Where Label -Like "Windows Server 2012 R2 Datacenter")[-1].ImageName -AdminUsername 'carlo' -Password 'VerySecurePassw0rd' -InstanceSize Small -Location 'west europe' } Days : 0 Hours : 0 Minutes : 1 Seconds : 12 Milliseconds : 422 Ticks : 724220786 TotalDays : 0,000838218502314815 TotalHours : 0,0201172440555556 TotalMinutes : 1,20703464333333 TotalSeconds : 72,4220786 TotalMilliseconds : 72422,0786
That's all for this first post on Windows Azure and on the Windows Azure Powershell module. I hope you have found the subject passionating and in that case I hope you'll share it and give feedback. Stay tuned for more, and good luck with the Games if you're in (I hope you are).
Impressive, I wasn't aware of the benefits of using Powershell with Azure! Great and thx for sharing!
ReplyDeleteWelcome!
DeleteThank you very much, this post on Azure was illuminating. I am having lot of fun with it and the free trial is huge!!!
ReplyDeleteDan
Hi Dan, glad I could help you out.
DeleteHi
ReplyDeleteI have been trying to understand this for a longtime and in the end I found this blog! You rock! Thx for sharing
Mike
You're welcome!! :-)
DeleteThe reason you cannot use an already existing service is because you are also specifying either -AffinityGroup or -Location (these are mutually exclusive). Use either of these for creating a new service, but not when using a service that already exists.
DeleteNice information. I was searching for the same. It helped me alot and saved my time. Thanks alot. , windows azure training in hyderabad
ReplyDelete