Friday, January 17, 2014

First steps in Windows Azure with Powershell

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 10
Name 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:
-ServiceName
Specifies 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).

6 comments:

  1. Impressive, I wasn't aware of the benefits of using Powershell with Azure! Great and thx for sharing!

    ReplyDelete
  2. Thank you very much, this post on Azure was illuminating. I am having lot of fun with it and the free trial is huge!!!
    Dan

    ReplyDelete
    Replies
    1. Hi Dan, glad I could help you out.

      Delete
  3. Hi
    I have been trying to understand this for a longtime and in the end I found this blog! You rock! Thx for sharing
    Mike

    ReplyDelete

Related Posts Plugin for WordPress, Blogger...