Share via


End-to-End IaaS Workload Provisioning in the Cloud with Azure Automation and PowerShell DSC ( Part 2 )

This article is Part 2 of a two-part series on automating the end-to-end provisioning process for IaaS workloads running on the Microsoft Azure cloud platform.  This process includes orchestration of all tasks, provisioning cloud fabric resources, and configuring operating system and application workloads running inside Azure VMs. The end goal of this effort is to provide accelerated "push-button" delivery of highly available, load-balanced cloud applications.

End-to-End IaaS Provisioning in the Cloud

In Part 1 of this series, I provided an example of leveraging Azure Automation runbooks and PowerShell Workflows in a concerted approach to fully automate all aspects of deploying new load-balanced VM's on the Microsoft Azure cloud platform. If you haven't yet completed Part 1 of this series, be sure to go do that now, and then come back here when finished to continue on to the Part 2 steps below.

In this article, I'll provide an example of a working PowerShell DSC Configuration that can be used with Azure Automation runbooks to customize the configuration of operating system and web application components running inside each VM as part of the provisioning process. When we're all done, we'll be able to invoke one runbook to deploy everything needed to bring our web application online: VMs, load-balancing, OS configuration, and Web application content.

What is PowerShell DSC?

In prior articles, we've discussed PowerShell Desired State Configuration (DSC) as a declarative approach to specify the end-state of a server and application instance.  This is in contrast to the imperative approach that is commonly used in traditional scripting.  By using a declarative approach, we're able to focus on the end-state to which a set of server and application instances should conform, rather than lots of if-then-else, try-catch conditional logic. In this manner, configuration management is streamlined and we're able to accelerate solution delivery and updates.

PowerShell DSC was introduced with PowerShell 4.0 for Windows Server 2012 R2, and has since been extended to support Linux as well. In PowerShell 5.0, DSC continues to be enhanced with support for object classes, centralized error reporting, easier resource authoring, cross-computer dependencies and MORE!

Let's Get Started!

To complete the scenario presented in this article, you'll want to be sure to download the following components:

  • Download and Install: PowerShell DSC Resource Kit
     
    The PowerShell DSC Resource Kit provides an additional set of over 40 DSC resource modules. In this article, we'll be using the xWebAdministration module for provisioning IIS web application resources.
     
  • Download and Install: Microsoft Azure PowerShell Module
     
    The Azure PowerShell Module provides PowerShell scripting support for Azure subscriptions and cloud resources. In this article, we'll be using the Azure PowerShell Module to publish our DSC Configuration to an Azure Storage Account, where it will be accessible to the Azure VMs that are being provisioned from within the Azure Automation runbook that was defined in Part 1 of this article series.
     
    Tip! If you've previously downloaded the Azure PowerShell Module, be sure that you have the latest version installed on your PC - you can run Get-Module Azure to confirm the installed version of this module. The Azure PowerShell Module is regularly updated to include support for new Azure features, and to support the Azure VM Agent DSC Extension, you should be running version 0.8.6 or later.

Configure OS and Application payloads inside Azure VMs with PowerShell DSC

In the DSC Configuration below, we'll define all of the components required for deploying our web application on the base platform image for Windows Server 2012 R2.  This configuration includes the Windows Server features, IIS Web Site configurations, web application content, and SSL certificate that our web application will use. In addition to standard DSC resources, the example below also shows how a DSC Script resource can be leveraged, in this case for deploying the needed SSL certificate.

Configuration WebSiteConfig
{

    # Import DSC WebAdmin Module from DSC Resource Kit
Import-DscResource -ModuleName xWebAdministration

    Node ("localhost")
{

        # Install the Web Server role
WindowsFeature IIS
{
Ensure = "Present"
Name = "Web-Server"
}

       # Install the ASP.NET 4.5 role
WindowsFeature AspNet
{
Ensure = "Present"
Name = "Web-Asp-Net45"
}

# Stop the default website
xWebsite DefaultSite
{
Ensure = "Present"
Name = "Default Web Site"
State = "Stopped"
PhysicalPath = "C:\inetpub\wwwroot"
DependsOn = "[WindowsFeature]IIS"
}

# Copy web application content
File MyWebAppContent
{
Ensure = "Present" # You can also set Ensure to "Absent"
Type = "Directory" # Default is "File".
Recurse = $true # Ensure presence of subdirectories, too
SourcePath = "\\XXXdemoad01\source\MyWebApp"
DestinationPath = "C:\inetpub\MyWebApp"
DependsOn = "[WindowsFeature]AspNet"
}

        # Install SSL Certificate
Script MyWebAppCert
{
SetScript = "Import-PfxCertificate
-FilePath \\XXXdemoad01\source\certs\MyWebAppCert.pfx
-CertStoreLocation Cert:\LocalMachine\WebHosting"
TestScript = "try { (Get-Item
Cert:\LocalMachine\WebHosting\
C534DFBFE8DB597F22320682F7BBFBA2611DC45A
-ErrorAction Stop).HasPrivateKey} catch { `$False }"
GetScript = "@{Ensure = if ((Get-Item
Cert:\LocalMachine\WebHosting\
C534DFBFE8DB597F22320682F7BBFBA2611DC45A
-ErrorAction SilentlyContinue).HasPrivateKey)
{'Present'}
else {'Absent'}}"
DependsOn = "[WindowsFeature]IIS"
}

        # Create the web site for MyWebApp
xWebsite MyWebAppSite
{
Ensure = "Present"
Name = "MyWebApp"
State = "Started"
PhysicalPath = "C:\inetpub\MyWebApp"
BindingInfo = MSFT_xWebBindingInformation
{
Protocol = "HTTPS"
Port = 443
CertificateThumbprint =
"C534DFBFE8DB597F22320682F7BBFBA2611DC45A"
CertificateStoreName = "WebHosting"
}
DependsOn = @("[WindowsFeature]IIS",
"[File]MyWebAppContent",
"[Script]MyWebAppCert")
}
 

    }

}

After entering the DSC Configuration above, save it to a local PowerShell script file, such as AADSCWebConfig.ps1.

Tip! You may have noted in the DSC Configuration above that we're not specifying a password when importing the SSL Certificate as part of the Script MyWebAppCert DSC resource. Instead of using a password, we're storing this SSL certificate in a secured shared folder to which only domain computers have read access. In addition, when exporting the SSL Certificate to this folder as a PFX file, instead of protecting it with a password, we used the option to restrict access to only specific Active Directory computer accounts - a new security feature that was introduced in Windows Server 2012.

Publish PowerShell DSC Configuration to Azure Storage Account

After saving the DSC Configuration as a local PowerShell script file, we'll need to publish this configuration to an Azure Storage Account container so that the Azure VMs we are provisioning will be able to access it. To perform this publishing process, we'll use the Azure PowerShell Module and the script snippet below from within a new Windows PowerShell ISE session window.

# Authenticate to Azure
Add-AzureAccount

# Select Azure Subscription and Storage Account
$subscriptionName = (Get-AzureSubscription).SubscriptionName |
Out-GridView `
-Title "Select Your Azure Subcription" `
-PassThru

Select-AzureSubscription `
-SubscriptionName $subscriptionName

$storageName = (Get-AzureStorageAccount).StorageAccountName |
Out-GridView `
-Title "Select Your Azure Storage Account" `
-PassThru

Set-AzureSubscription `
-SubscriptionName $subscriptionName `
-CurrentStorageAccountName $storageName

# Publish DSC Configuration to Azure Storage AccountPublish-AzureVMDscConfiguration `
-ConfigurationPath .\AADSCWebConfig.ps1 `
-Force

Tip! When selecting the Azure Subscription and Storage Account in the code snippet above, be sure to select the same Subscription and Storage Account used in Part 1 of this article series within your Azure Automation Runbook.

During the publishing process above, the DSC Configuration will be packaged in a .ZIP file along with any modules imported using Import-Module in the Configuration block.  By default, this resulting .ZIP file package will be uploaded to a storage container named windows-powershell-dsc in the selected Azure Storage Account.

Use Azure VM Agent extensions to apply PowerShell DSC Configuration

We've got our PowerShell DSC Configuration defined and published to our Azure Storage Account.  Now, we'll need to add a bit of extra code to the original Azure Automation Runbook that we built in Part 1 of this series. This additional code will apply our published DSC Configuration inside each VM using the Azure VM Agent DSC extension.

Open the Azure Automation Runbook that you defined in Part 1 of this series and edit it in Draft mode. Insert the highlighted code between the Set-AzureSubnet and New-AzureVM code blocks as shown below.

...

# Specify HA Availability Set for VM
$vm = Set-AzureAvailabilitySet `
-VM $vm `
-AvailabilitySetName $Using:availabilitySetName

# Specify DSC Configuration to Apply within VM
$vm = Set-AzureVMDSCExtension `
-VM $vm `
-ConfigurationArchive $Using:dscArchive `
-ConfigurationName $Using:dscConfigName

# Provision new VM with specified configuration
New-AzureVM `
-VMs $vm `
-ServiceName $Using:vmServiceName `
-VnetName $Using:vNetName `
-AffinityGroup $Using:affinityGroupName `
-WaitForBoot

...

That's it! Save and test your revised Runbook.  Upon Runbook completion, you should have your finished cloud application fully deployed - cloud fabric resources, OS configuration, web application content and application settings - all from a single "push-button".

What's next?

In future articles, I'll be expanding on additional scenarios around automation with Microsoft Azure. In the meantime, be sure to check out these additional resources to continue your learning: