Using PowerShell to Manage Windows Azure Applications

I was recently asked to do a presentation on managing Windows Azure applications with PowerShell by the Charlotte PowerShell users group.   At first I was a bit unsure about doing the presentation – with Jim Christopher and Ed Wilson in the group as well as other PowerShell gurus, it can be tough to ramp up to a respectable level of knowledge.  But, these guys are awesome and Ed welcomed me to pen a blog post for them, so check it out on the Hey, Scripting Guy! blog. I learned a ton in the process.  While I knew there were the Azure PowerShell cmdlets to aid in virtually everything you  can do via the management interface, getting hands on and really putting it through the paces still wows me at what you can do with PowerShell. In the blog post, an sample website is deployed to two different datacenters, and then load balanced geographically using the Traffic Manager.  Instances can be easily altered, storage accounts created, etc.  And then, finishing it with only a few lines a code to tear it all down.    All in all, it integrates really nicely with any application lifecycle process. Check out the post and try the code out for yourself!

Azure Miniseries #4: Monitoring Applications

In this screencast, we'll take a look at monitoring Azure applications by capturing event logs and performance counters. We'll also look at using PowerShell to deploy and configure applications using the management API. Finally, we'll take a sneak peek at Azure Diagnostics Manager, a tool from Cerebrata that allows you explore event logs and look at performance counters visually. Here are some links from the screencast: Windows Azure Cmdlets Cerebrata (Cloud Storage Studio and Azure Diagnostics Monitor) Finally, let’s get into some code snippets! Watch for wrap on the PowerShell lines, and note the single quote ` character as the line continuation: Creating a self-signed certificate command:
makecert -r -pe -a sha1 -n "CN=Azure Service Test" -ss My -len 2048 -sp "Microsoft Enhanced RSA and AES Cryptographic Provider" -sy 24 AzureServiceTest.cer
Uploading a new deployment to the staging slot, and starting it (requires Azure CmdLets):
$cert = Get-Item cert:\CurrentUser\My\{thumbprint} $sub = "{subscription GUID}" $servicename = "{service name}" $package = "CloudApp.cspkg" $config = "ServiceConfiguration.cscfg" [DateTime]$datelabel = Get-Date $lbl = $datelabel.ToString("MM-dd-yyyy-HH:mm") Write-Host "Label for deployment: " $lbl Add-PSSnapin AzureManagementToolsSnapIn Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub | New-Deployment -Slot Staging $package $config -Label $lbl | Get-OperationStatus -WaitToComplete Get-Deployment staging -serviceName $servicename -SubscriptionId $sub -Certificate $cert | Set-DeploymentStatus running | Get-OperationStatus -WaitToComplete
Increasing the number of instances:
Add-PSSnapin AzureManagementToolsSnapIn $cert = Get-Item cert:\CurrentUser\My\{thumbprint} $sub = "{subscription GUID}" $servicename = "{service name}" $storage = "{storage name}" #get storage account name and key $key = (Get-StorageKeys -ServiceName $storage -Certificate $cert -SubscriptionId $sub).Primary $deployId = (Get-HostedService $servicename -SubscriptionId $sub -Certificate $cert | Get-Deployment Production).DeploymentId        Get-HostedService $servicename -Certificate $cert -SubscriptionId $sub |     Get-Deployment -Slot Staging |     Set-DeploymentConfiguration {$_.RolesConfiguration["WebRole1"].InstanceCount += 1}
Updating the performance counters – specifically, adding total processor time, ASP.NET req/sec, and memory usage to be polled every 30 seconds, and uploaded every 1 minute:
Add-PSSnapin AzureManagementToolsSnapIn $cert = Get-Item cert:\CurrentUser\My\{thumbprint} $sub = "{subscription GUID}" $servicename = "{service name}" $storage = "{storage name}" #get storage account name and key $key = (Get-StorageKeys -ServiceName $storage -Certificate $cert -SubscriptionId $sub).Primary $deployId = (Get-HostedService $servicename -SubscriptionId $sub -Certificate $cert | Get-Deployment Production).DeploymentId        # rate at which counters are polled $rate = [TimeSpan]::FromSeconds(30) Get-DiagnosticAwareRoles -StorageAccountName $storage -StorageAccountKey $key -DeploymentId $deployId | foreach {     $role = $_     write-host $role     Get-DiagnosticAwareRoleInstances $role -DeploymentId $deployId `         -StorageAccountName $storage -StorageAccountKey $key |     foreach {         $instance = $_         $config = Get-DiagnosticConfiguration -RoleName $role -InstanceId $_ -StorageAccountName $storage `              -StorageAccountKey $key -BufferName PerformanceCounters -DeploymentId $deployId                     $processorCounter = New-Object Microsoft.WindowsAzure.Diagnostics.PerformanceCounterConfiguration `                 -Property @{CounterSpecifier='\Processor(_Total)\% Processor Time'; SampleRate=$rate }         $memoryCounter = New-Object Microsoft.WindowsAzure.Diagnostics.PerformanceCounterConfiguration `                 -Property @{CounterSpecifier='\Memory\Available Mbytes'; SampleRate=$rate }         $requestsCounter = New-Object Microsoft.WindowsAzure.Diagnostics.PerformanceCounterConfiguration `                 -Property @{CounterSpecifier='\ASP.NET Applications(__Total__)\Requests/Sec'; SampleRate=$rate }         $config.DataSources.Clear()         $config.DataSources.Add($processorCounter)         $config.DataSources.Add($memoryCounter)         $config.DataSources.Add($requestsCounter)         Set-PerformanceCounter -PerformanceCounters $config.DataSources -RoleName $role `              -InstanceId $instance -DeploymentId $deployId `              -TransferPeriod 1 `              -StorageAccountName $storage -StorageAccountKey $key                          }   }
And finally, the webrole.cs class from the screencast:
public class WebRole : RoleEntryPoint     {         public override bool OnStart()         {             DiagnosticMonitorConfiguration diagConfig =                 DiagnosticMonitor.GetDefaultInitialConfiguration();             diagConfig.PerformanceCounters.DataSources.Add(                 new PerformanceCounterConfiguration()                 {                     CounterSpecifier = @"\Processor(_Total)\% Processor Time",                     SampleRate = TimeSpan.FromSeconds(5)                 });             diagConfig.PerformanceCounters.DataSources.Add(                 new PerformanceCounterConfiguration()                 {                     CounterSpecifier = @"\Memory\Available Mbytes",                     SampleRate = TimeSpan.FromSeconds(5)                 });             diagConfig.PerformanceCounters.ScheduledTransferPeriod =                 TimeSpan.FromMinutes(1);             diagConfig.Logs.ScheduledTransferLogLevelFilter = LogLevel.Information;             diagConfig.Logs.ScheduledTransferPeriod = TimeSpan.FromMinutes(1);             DiagnosticMonitor.Start("DiagnosticsConnectionString", diagConfig);             System.Diagnostics.Trace.TraceInformation("Done configuring diagnostics.");             // For information on handling configuration changes             // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.             RoleEnvironment.Changing += RoleEnvironmentChanging;             return base.OnStart();         }         public override void OnStop()         {             System.Diagnostics.Trace.TraceWarning("Onstop called.");             base.OnStop();         }         private void RoleEnvironmentChanging(object sender, RoleEnvironmentChangingEventArgs e)         {             // If a configuration setting is changing             if (e.Changes.Any(change => change is RoleEnvironmentConfigurationSettingChange))             {                 // Set e.Cancel to true to restart this role instance                 e.Cancel = true;             }         }     }

My Apps

Dark Skies Astrophotography Journal Vol 1 Explore The Moon
Mars Explorer Moons of Jupiter Messier Object Explorer
Brew Finder Earthquake Explorer Venus Explorer  

My Worldmap

Month List