Microsoft Azure provides Point-to-Site VPN (aka. Client VPN) connectivity for secure remote access by development and operations teams to cloud-based workloads that are provisioned on an Azure Virtual Network. Azure Point-to-Site VPN connectivity uses SSTP as a firewall-friendly tunneling protocol and certificates for mutual authentication of each client connection.
You can find more details on configuring Azure Point-to-Site VPNs at the following link location:
When discussing Azure Point-to-Site VPN connectivity, one of the questions I frequently hear is ...
Great! But ... how do I disable a Point-to-Site VPN user when they're leaving my organization?
Azure Point-to-Site VPNs use certificates for user authentication and authorization, so we can simply revoke a user's certificate to disable their Point-to-Site VPN access. In this article, we'll step through the process of revoking and reinstating user certificates for Azure Point-to-Site VPNs by using the Azure PowerShell module and the Azure Service Management REST API.
Before we can manage Azure resources via the Azure PowerShell module, we'll first need to authenticate. Authentication to Azure can be accomplished via management certificates, or via Azure Active Directory. In this article, we'll use management certificates to authenticate to Azure via both Azure PowerShell and the Azure Service Management REST API.
# Download Azure Management Certificate Get-AzurePublishSettingsFile # Import Azure Management Certificate Import-AzurePublishSettingsFile "${env:USERPROFILE}\Documents\Azure.publishsettings"
# Download Azure Management Certificate
Get-AzurePublishSettingsFile
# Import Azure Management Certificate
Import-AzurePublishSettingsFile "${env:USERPROFILE}\Documents\Azure.publishsettings"
In a future article, we'll explore using Azure AD to authenticate to Azure via Azure PowerShell and the Azure Service Management REST API.
Once we've authenticated to Azure, we'll next select the Azure subscription in which our Azure Virtual Network is provisioned. Many organizations have more than one Azure subscription for different release stages (dev, test, production), applications or business units.
# Select Azure Subscription $subscriptionName = (Get-AzureSubscription).SubscriptionName | Out-GridView -Title "Select Azure Subscription" -PassThru Select-AzureSubscription -SubscriptionName $subscriptionName
# Select Azure Subscription
$subscriptionName = (Get-AzureSubscription).SubscriptionName | Out-GridView -Title "Select Azure Subscription" -PassThru
Select-AzureSubscription -SubscriptionName $subscriptionName
After selecting the appropriate Azure subscription, we'll need to grab the subscription ID and the management certificate thumbprint we used when authenticating to Azure. We'll need these values to authenticate to Azure via the Azure Service Management REST API later in this article.
# Get Azure subscription information $subscription = Get-AzureSubscription $subscriptionName -ExtendedDetails $certificate = $subscription.Certificate $subscriptionId = $subscription.SubscriptionId
# Get Azure subscription information
$subscription = Get-AzureSubscription $subscriptionName -ExtendedDetails
$certificate = $subscription.Certificate
$subscriptionId = $subscription.SubscriptionId
Some organizations may have more than one Azure Virtual Network provisioned within their Azure subscription. In this step, we'll select the Azure Virtual Network that has the Point-to-Site VPN Gateway provisioned within it.
# Select Azure VNet for which to manage VPN certificates $azureVNet = (Get-AzureVNetSite).Name | Out-GridView -Title "Select Azure VNet" -PassThru
# Select Azure VNet for which to manage VPN certificates
$azureVNet = (Get-AzureVNetSite).Name | Out-GridView -Title "Select Azure VNet" -PassThru
Now, we can choose the VPN client certificate that's associated with the user that we wish to disable. When initially provisioning VPN client certificates for your users, be sure to use a certificate naming convention that makes it easy to identify each certificate based on username. Also, be sure to save a copy of each certificate in a safe location so that you can easily access them later, if needed.
# Import saved copy of user's VPN client certificate $certPassword = Read-Host "Enter VPN client certificate password" -AsSecureString Import-PfxCertificate -FilePath "${env:USERPROFILE}\Documents\Azure\P2S VPN\VPN01Client.pfx" -CertStoreLocation Cert:CurrentUser\My -Exportable -Password $certPassword # Select VPN client certificate to Revoke $vpnCertThumbprint = (Get-ChildItem Cert:\CurrentUser\My | Out-GridView -Title "Select VPN certificate to revoke" -PassThru).Thumbprint
# Import saved copy of user's VPN client certificate
$certPassword = Read-Host "Enter VPN client certificate password" -AsSecureString
Import-PfxCertificate -FilePath "${env:USERPROFILE}\Documents\Azure\P2S VPN\VPN01Client.pfx" -CertStoreLocation Cert:CurrentUser\My -Exportable -Password $certPassword
# Select VPN client certificate to Revoke
$vpnCertThumbprint = (Get-ChildItem Cert:\CurrentUser\My | Out-GridView -Title "Select VPN certificate to revoke" -PassThru).Thumbprint
We've selected all the relevant values we'll need when revoking a Point-to-Site VPN client certificate, so now we can call the Azure Service Management REST API to perform the actual revoke process. When we call this API, we'll pass along the relevant values that we've collected above.
# Build web request header $requestHeader = @{"x-ms-version" = "2012-03-01"} # Revoke a VPN Client Certificate $revokeVPNCertUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates/$vpnCertThumbprint" $response = Invoke-RestMethod -Uri $revokeVPNCertUri -Certificate $certificate -Method Post -Headers $requestHeader # Confirm Revoked VPN Client Certificates $listRevokedVPNCertUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates" $response = Invoke-RestMethod -Uri $listRevokedVPNCertUri -Certificate $certificate -Method Get -Headers $requestHeader $response.ClientCertificates.Thumbprint
# Build web request header
$requestHeader = @{"x-ms-version" = "2012-03-01"}
# Revoke a VPN Client Certificate
$revokeVPNCertUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates/$vpnCertThumbprint"
$response = Invoke-RestMethod -Uri $revokeVPNCertUri -Certificate $certificate -Method Post -Headers $requestHeader
# Confirm Revoked VPN Client Certificates
$listRevokedVPNCertUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates"
$response = Invoke-RestMethod -Uri $listRevokedVPNCertUri -Certificate $certificate -Method Get -Headers $requestHeader
$response.ClientCertificates.Thumbprint
After a user's VPN client certificate is revoked, if they should attempt to connect to the Point-to-Site VPN Gateway, their connection will not be successfully authenticated and they will receive the below error message.
In some cases, you may find that you need to later reinstate a revoked VPN client certificate. Luckily, we can use the same Azure API to reinstate certificates that were previously revoked by using the code snippet below.
# Reinstate a VPN Client Certificate $reinstateVPNCertUri = https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates/$vpnCertThumbprint $response = Invoke-RestMethod -Uri $reinstateVPNCertUri -Certificate $certificate -Method Delete -Headers $requestHeader
# Reinstate a VPN Client Certificate
$reinstateVPNCertUri = https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/clientcertificates/$vpnCertThumbprint
$response = Invoke-RestMethod -Uri $reinstateVPNCertUri -Certificate $certificate -Method Delete -Headers $requestHeader
Microsoft Azure provides secure access to cloud-based VMs for developers and IT operations teams via Point-to-Site VPN (aka. Client VPN) connectivity. This solution uses SSTP (Secure Socket Tunneling Protocol) to provide a secure, firewall-friendly solution that uses the native VPN client built-in with Windows 7 and later. In a future article, we'll also look at a cross-platform Client VPN connectivity option to Azure for Linux and Mac OS X clients.
After configuring Point-to-Site VPN connectivity in Azure, it's pretty easy to see the overall connection status on the Virtual Networks Dashboard page of the Azure Management Portal, as shown below.
Azure Management Portal: Virtual Network Dashboard page
BUT ... what if we want to see the details of each individual client IP address that is currently connected to the VPN? Luckily, with a bit a PowerShell and the Azure Service Management REST API, we can fetch those details as well!
The PowerShell snippet below prompts to select an Azure subscription and Virtual Network, and then calls the List Connections operation via the REST API to display a list of currently connected client IP addresses. Hope you find it helpful!
# Download Azure Publish Settings fileGet-AzurePublishSettingsFile
# Import Azure Publish Settings fileImport-AzurePublishSettingsFile "$env:USERPROFILE\Documents\Azure.publishsettings"
# Select Azure subscription$subscriptionName = (Get-AzureSubscription).SubscriptionName | Out-GridView -Title "Select Azure Subscription" -PassThru
# Get Azure subscription ID and certificate$subscription = Get-AzureSubscription $subscriptionName -ExtendedDetails$certificate = $subscription.Certificate$subscriptionId = $subscription.SubscriptionId
# Select Azure Virtual Network$azureVNet = (Get-AzureVNetSite).Name | Out-GridView -Title "Select Azure VNet" -PassThru
# Build request header and body$requestHeader = @{"x-ms-version" = "2012-03-01"}
# Call the Azure REST API$listVPNConnectionsUri = "https://management.core.windows.net/$subscriptionId/services/networking/$azureVNet/gateway/connections"$VPNConnections = Invoke-RestMethod -Uri $listVPNConnectionsUri -Certificate $certificate -Method Get -Headers $requestHeader
# List active VPN client connections$VPNConnections.Connections.Connection.AllocatedIPAddresses.String
There's lots of tools that can be leveraged for automating Linux workloads on Microsoft Azure, including Azure Automation, PowerShell DSC for Linux, VM Agent Custom Scripts, Cloud-Init, XPlat CLI for Azure, Vagrant, Docker and third-party tools such as Chef and Puppet. Azure provides a wide variety of automation options so that you can choose the tools with which you're most familiar and, in some cases, may already have an existing investment.
In Part 1 of this two-part article series, we stepped through the process for getting our Linux admin workstation setup for Azure cloud automation using the XPlat-CLI and Cloud-Init.
This article is Part 2 of this series. In this article, we'll leverage these tools for automatically provisioning an end-to-end highly available Linux server farm environment, including storage, networking, load-balancing, virtual machines and application workloads. As we proceed through this article, we'll be build a Linux shell script that implements this provisioning logic.
Before stepping through this article, be sure to complete Part 1 of this two-part series to setup your Linux admin workstation for Azure cloud automation.
You may also be interested in these additional Linux / Open Source cloud resources:
When provisioning new Linux workloads in the cloud, there's several values that need to be specified, such as Azure subscription, datacenter region, number of VMs, and resource names, that need to be specified for the process to be successful. To promote reusability, I'm a big fan of using input parameters in shell scripts, so we'll start our script with defining the input parameters for provisioning our environment.
#!/bin/sh # Set variable values based on parameters passedazureloginuname="$1" # Azure AD login IDazureloginpass="$2" # Azure AD passwordazuresubname="$3" # Azure subscription nameazureregion="$4" # Azure datacenter regionazureprefix="$5" # Unique prefix for Azure resource namesazurevmuname="$6" # Admin username for new VMsazurevmpass="$7" # Admin password for new VMsazurevmtotal="$8" # Number of VMs to provisionazurecloudinit="$9" # Cloud-Init config file
#!/bin/sh
# Set variable values based on parameters passedazureloginuname="$1" # Azure AD login IDazureloginpass="$2" # Azure AD passwordazuresubname="$3" # Azure subscription nameazureregion="$4" # Azure datacenter regionazureprefix="$5" # Unique prefix for Azure resource namesazurevmuname="$6" # Admin username for new VMsazurevmpass="$7" # Admin password for new VMsazurevmtotal="$8" # Number of VMs to provisionazurecloudinit="$9" # Cloud-Init config file
newlinuxonazure.sh script - Input parameters
With these input parameters defined, we'll be able to use this script to provision different environments in the Azure cloud just by varying the input parameter values when calling the finished script.
Before our script can perform any provisioning steps, we'll first need to sign-in to our Azure account. When signing in, we'll need to specify an Azure Active Directory login ID that has been delegated service administrator or co-administrator access to the Azure subscription with which we'll be working. In our script, we can sign-in with the provided Azure AD login ID and password using the azure login command from the XPlat-CLI.
# Sign-in to Azure account with Azure AD credentials azure login --user "$azureloginuname" --password "$azureloginpass" # Confirm that Azure account sign-in was successful if [ "$?" != "0" ]; then echo "Error: login to Azure account failed" exit 1fi
newlinuxonazure.sh script - Sign-in to Azure account
In Azure, an account may be associated with multiple subscriptions, so we'll next need to use the azure account set command to select the specific Azure subscription in which we'll be provisioning new workloads.
# Select Azure subscription azure account set "$azuresubname" # Confirm that subscription is now default azuresubdefault=$(azure account show --json "$azuresubname" | jsawk 'return this.isDefault')if [ "$azuresubdefault" != "true" ]; then echo "Error: Azure subscription ${azuresubdefault} not found as default subscription" exit 1fi
newlinuxonazure.sh script - Select Azure subscription
In the snippet above, we're confirming that the correct Azure subscription has been selected by returning output from the azure account show command in JSON format, and then piping that output to jsawk to return the isDefault value. We'll be using JSON formatted output and jsawk throughout our script to provide additional intelligence and error handling.
In Azure, Affinity Groups help to reduce latency and improve performance between provisioned resources within an Azure datacenter region by keeping them located reasonably "close together". We can define Affinity Groups using the azure account affinity-group create command.
# Define Azure affinity group azureagname="${azureprefix}ag"azure account affinity-group create --location "$azureregion" --label "$azureagname" "$azureagname" # Confirm that Azure affinity group exists azureagexist=$(azure account affinity-group list --json | jsawk 'return true' -q "[?name=\"$azureagname\"]")if [ $azureagexist != [true] ]; then echo "Error: Azure affinity group ${azureagname} not found" exit 1fi
newlinuxonazure.sh script - Define an Affinity Group
In the snippet above, we've provided a unique name for the new Affinity Group by leveraging the $azureprefix value that was supplied as an input parameter earlier in the script. In addition, we've tied the Affinity Group to a particular Azure datacenter region by referencing the $azureregion value that was also provided as a script parameter.
Azure Storage Accounts are used to provide blob storage for storing persistent virtual disks for Azure virtual machines. Our script can create a new storage account for storing the VM disks we'll be provisioning by calling the azure storage account create command.
# Create Azure storage account azurestoragename="${azureprefix}stor"azure storage account create --affinity-group "$azureagname" --label "$azurestoragename" --geoReplication "$azurestoragename" # Confirm that Azure storage account exists azurestorageexist=$(azure storage account list --json | jsawk 'return true' -q "[?name=\"$azurestoragename\"]")if [ $azurestorageexist != [true] ]; then echo "Error: Azure storage account ${azurestoragename} not found" exit 1fi
newlinuxonazure.sh script - Create an Azure Storage Account
In the snippet above, we're also specifying the --geoReplication option to create our Azure Storage Account with built-in asynchronous Storage Geo-Replication between Azure datacenter regions for additional disaster recovery protection.
Azure Virtual Networks provide an isolated IP address namespace in the cloud that can optionally also connect to on-premises servers and workstations via site-to-site and point-to-site VPN tunnels. Multiple Azure virtual machines can be co-located on a common Azure virtual network to provide an internally routable IP address range that VMs can use to communicate directly with one another - just as if those VMs were running on an internal physical network. Our script can provision a new Azure Virtual Network by using the azure network vnet create command.
# Create Azure virtual network azurevnetname="${azureprefix}net"azure network vnet create --affinity-group "$azureagname" "$azurevnetname" # Confirm that Azure virtual network exists azurevnetexist=$(azure network vnet list --json | jsawk 'return true' -q "[?name=\"$azurevnetname\"]")if [ $azurevnetexist != [true] ]; then echo "Error: Azure virtual network ${azurevnetname} not found" exit 1fi
newlinuxonazure.sh script - Create Azure Virtual Network
Note: In the snippet above, we're specifying the --affinity-group option when creating the Azure Virtual Network. While this is currently a valid approach, Azure Virtual Networks are moving to a new Regional Virtual Network model that offers improved networking capabilities. After the Azure XPlat-CLI is updated to support Regional Virtual Networks, you'll be able to supply the --location option as an alternative to specifying an Azure affinity group when creating a new Azure Virtual Network so that you'll be able to take advantage of these new networking capabilities. In the meantime, if you wish to create a new Regional Virtual Network, you can certainly do so via the Azure Management Portal.
When provisioning our new Azure Virtual Machines, we'll need to specify the base VM image from which our new VMs will be built. This VM image can be one of the standard Linux platform images provided in the Microsoft Azure Marketplace, or it could be a custom Linux VM Image that you've created and uploaded to your Azure subscription. Our script can select the appropriate Linux VM image by calling the azure vm image list command.
# Select Linux VM image azurevmimage=$(azure vm image list --json | jsawk -n 'out(this.name)' -q "[?name=\"*Ubuntu-14_04_1-LTS-amd64-server*\"]" | sort | tail -n 1) # Confirm that valid Linux VM Image is selected if [ "$azurevmimage" = "" ]; then echo "Error: Azure VM image not found" exit 1fi
newlinuxonazure.sh script - Select Linux VM Image
In the snippet above, we're using jsawk to query the list of available images based on Ubuntu 14.04 LTS, and then we select the most recent image in the returned results for use within our script.
We're now ready to provision our Linux virtual machines. First, we'll define a few variables that we'll use during the VM provisioning process ...
# Set variables for provisioning Linux VMs azurednsname="${azureprefix}app" # DNS hostname for Cloud Serviceazurevmsize='Small' # Azure VM instance sizeazureavailabilityset="${azureprefix}as" # Availability Set nameazureendpointport='80' # Port to Load-balanceazureendpointprot='tcp' # Protocol to Load-balanceazureendpointdsr='false' # Direct Server Return, usually falseazureloadbalanceset="${azureprefix}lb" # Load-balanced Set name
newlinuxonazure.sh script - Set variables for provisioning Linux VMs
... then, in the snippet below, we'll use the azure vm create command to create each new VM. We'll also use the azure vm endpoint command to configure load-balanced firewall endpoints that permit inbound web traffic.
# Provision Linux VMs # Initialize Azure VM counter azurevmcount=1 # Loop through provisioning each VMwhile [ $azurevmcount -le $azurevmtotal ]do # Set Linux VM hostname azurevmname="${azureprefix}app${azurevmcount}" # Create Linux VM - if first VM, also create Azure Cloud Service if [ $azurevmcount -eq 1 ]; then azure vm create --vm-name "$azurevmname" --affinity-group "$azureagname" --virtual-network-name "$azurevnetname" --availability-set "$azureavailabilityset" --ssh 22 --custom-data "$azurecloudinit" --vm-size "$azurevmsize" "$azurednsname" "$azurevmimage" "$azurevmuname" "$azurevmpass" else azure vm create --vm-name "$azurevmname" --affinity-group "$azureagname" --virtual-network-name "$azurevnetname" --availability-set "$azureavailabilityset" --ssh $((22+($azurevmcount-1))) --custom-data "$azurecloudinit" --vm-size "$azurevmsize" --connect "$azurednsname" "$azurevmimage" "$azurevmuname" "$azurevmpass" fi # Confirm that VM creation was successfully submitted if [ "$?" != "0" ]; then echo "Error: provisioning VM ${azurevmname} failed" exit 1 fi # Define load-balancing for incoming web traffic on each VM azure vm endpoint create-multiple "$azurevmname" $azureendpointport:$azureendpointport:$azureendpointprot:$azureendpointdsr:$azureloadbalanceset:$azureendpointprot:$azureendpointport # Confirm that load-balancing config was successfully submitted if [ "$?" != "0" ]; then echo "Error: provisioning endpoints for VM ${azurevmname} failed" exit 1 fi # Wait until new VM is in a Running state azurevmstatus='None' while [ "$azurevmstatus" != "ReadyRole" ] do sleep 30s azurevmstatus=$(azure vm show --json --dns-name "$azurednsname" "$azurevmname" | jsawk 'return this.InstanceStatus') echo "Provisioning: ${azurevmname} status is ${azurevmstatus}" done # Increment VM counter for next VM azurevmcount=$((azurevmcount+1)) done
newlinuxonazure.sh script - Provision Linux VMs
There's quite a bit occurring in this last script snippet, so let's step back and take a closer look ...
As part of the VM provisioning process, our script also configures the application workloads running inside each VM. When configuring application workloads, there's several options that we can use, including Cloud-Init, Custom Scripts, Docker and PowerShell DSC for Linux, as well as third-party tools such as Chef and Puppet. In our script snippet above, we're supplying a Cloud-Init config file using the --custom-data option on the azure vm create command.
#cloud-config # Install additional packages on first boot## Default: none## if packages are specified, this apt_update will be set to true## packages may be supplied as a single package name or as a list# with the format [<package>, <version>] wherein the specifc# package version will be installed.packages: - apache2
#cloud-config
# Install additional packages on first boot## Default: none## if packages are specified, this apt_update will be set to true## packages may be supplied as a single package name or as a list# with the format [<package>, <version>] wherein the specifc# package version will be installed.packages: - apache2
cloudinit-apache.txt - Install Apache2 package inside Linux VMs
Cloud-Init provides lots of flexible options in configuring application workloads inside VMs (see the Cloud-Init documentation for more details), but in our example above we're using just a simple configuration file that ensures that the necessary package is installed for supporting web workloads in each of our Linux VMs.
At the end of our script, we can clean-up our admin environment and automatically sign-out of our Azure account using the azure logout command.
# End of script echo "Success: Azure provisioning for ${azurednsname} completed"azure logout "$azureloginuname"
newlinuxonazure.sh script - Sign-out of Azure account
After we've saved on script file on our Linux admin workstation, we can flag the script as executable with the standard Linux chmod command ...
chmod 755 ./newlinuxonazure.sh
... and, then run our new script with our desired parameter values to test provisioning a new highly available Linux web server farm on the Azure cloud platform!
./newlinuxonazure.sh "[email protected]" "password" "your-azure-subscription-name" "azure-region" "unique-azure-prefix" "vm-admin-name" "vm-admin-password" total-number-of-vms "path-to-cloud-init-config-file"
After a few minutes, our script completes and our new highly available Linux web server farm is now up and running on the Azure cloud, ready for us to begin using ...
Microsoft Azure Management Portal - https://manage.windowsazure.com
.... and we can browse to our new load-balanced web service using the provisioned DNS hostname to confirm that it's available ...
Since previously publishing the Quick Start Guide for Building Highly Available Linux Servers in the Cloud on Microsoft Azure, several people have asked me about ways in which Linux workload provisioning can be automated with Azure.
There's lots of tools that can be leveraged for automating Linux workloads on Microsoft Azure, including Azure Automation, PowerShell DSC for Linux, VM Agent Custom Scripts, Cloud-Init, XPlat CLI for Azure, Vagrant, Docker and third-party tools such as Chef and Puppet. The Azure team provides a wide variety of automation options so that you can choose the tools with which you're most familiar and, in some cases, may already have an existing investment.
This article is part 1 of a two-part series. In this article, we'll step through the process for getting our Linux admin workstation setup for Azure cloud automation using the XPlat-CLI for Azure and Cloud-Init.
In part 2 of this series, we'll leverage these tools for automatically provisioning a highly available Linux server farm environment using the scenario outlined in the Quick Start Guide referenced above.
The XPlat CLI is a cross-platform Azure command-line interface for Linux, Mac and Windows administrators. If you're familiar with writing shell scripts, the XPlat CLI for Azure provides an easy way to get started with end-to-end automation of Linux environments on Azure. Using the XPlat CLI, you can easily provision Azure fabric resources, such as storage, networking and VMs, along with OS and application configurations inside each VM.
The XPlat CLI is written in JavaScript and is implemented using the Azure SDK for Node.js. It's been released under an Apache 2.0 license and the project repository is located at https://github.com/Azure/azure-xplat-cli.
To prepare for following along with this article, be sure to complete the following steps:
The XPlat CLI for Azure requires node.js and npm, so we'll need to install those first. On Ubuntu 14.04, we'll also need to install the nodejs-legacy package.
sudo apt-get updatesudo apt-get install -y nodejs nodejs-legacy npm
After installation, you can confirm the versions of node and npm that is installed by using the following commands:
node --versionnpm --version
My admin machine is running node v0.10.25 and npm v1.3.10. If you're running a very old version of node and/or npm, be sure to update to the latest versions of each before continuing.
After the nodejs and npm packages are installed, we can install the XPlat CLI for Azure using npm.
sudo npm install azure-cli --global
After the azure-cli package is installed, you can check the version of the XPlat CLI using the following command:
azure --version
The XPlat CLI is updated on a regular basis. Check the ChangeLog to make sure that you're using the latest version. If you find that you need to update the azure-cli package, you can easily do so with the following command:
sudo npm update azure-cli --global
After installing the azure-cli package, you may wish to enable auto-completion of command lines to make it easier to work with this CLI tool. You can enable auto-complete each time you login by using these commands:
azure --completion >> ~/azure.completion.shecho 'source ~/azure.completion.sh' >> .bash_profile
To enable command line auto-completion for your current session without needing to logout/login, run this command:
source ~/azure.completion.sh
The XPlat CLI includes some pretty extensive built-in help for the various CLI commands and options. To get help on the list of available commands, you can run:
azure --help
To get help on the various actions and options available for each command, simply run the command with the --help option specified at the end of the command line. For example, to see help on creating VM's via the CLI, you could run:
azure vm --help or azure vm create --help
azure vm --help
or
azure vm create --help
You may have noticed in the help ouput that the XPlat CLI includes a --json option to output information in JSON format. This brings us to the next step ...
After installing the XPlat CLI, you may also wish to install a JSON command line tool, such as jsawk or jq. The XPlat CLI can return information in JSON format when using the --json option, and it's helpful to have command line tools that can easily parse JSON ouput when building shell scripts. In this article series, we'll be using jsawk.
Before installing jsawk, we'll first need to install the spidermonkey-bin package, which jsawk depends upon. Use these commands to download, build and install the spidermonkey-bin package.
sudo apt-get install mercurial autoconf2.13 -yhg clone http://hg.mozilla.org/mozilla-central/ cd mozilla-central/js/srcautoconf2.13./configuremakesudo make install
After you've completed these steps, you can confirm that the spidermonkey-bin js interpreter is correctly installed by running this command:
js --help
Now, we can install jsawk with the following commands:
curl -L http://github.com/micha/jsawk/raw/master/jsawk > jsawkchmod 755 jsawksudo mv jsawk /usr/bin/
We can confirm that the jsawk command line tool is properly installed by running this command:
echo | jsawk 'return "jsawk is installed"'
Our Linux workstation is now prepared with the tools necessary to automate Linux workload provisioning on Azure. In part 2 of this article series, we will continue with creating a script that will authenticate to our Azure subscription and build the highly available Linux server farm environment depicted in our Quick Start Guide.
Stay tuned for more in the Clouds!
Keith
We can assign static internal IP addresses for Azure Virtual Machines on a Virtual Network using either PowerShell or the new Azure Preview Portal. This is a useful capability for provisioning VM workloads that may require fixed IP address assignments, such as DNS servers.
Provisioning a VM with a Static internal IP address using Azure Preview Portal
Question: After provisioning a set of VM's with static internal IP addresses, how can I display a list of all VMs with static addresses in my subscription?
Answer: You can list all Azure VM's configured with static internal IP addresses in your Azure subscription with the following one-line PowerShell code snippet that leverages the Azure PowerShell Module.
Get-AzureVM | Select-Object -Property Name, @{Name='StaticIP';Expression={(Get-AzureStaticVNetIP -VM $_ ).IPAddress}}
Thanks for attending my presentation today at the Columbus SQLPASS User Group chapter on SQL Server Options in the Cloud with Microsoft Azure.
We discussed various hybrid cloud options for leveraging Microsoft Azure as part of a SQL Server deployment, including the following scenarios:
In this article, I've included a downloadable copy of our session deck along with a list of additional resources to help you continue your evaluation of these key scenarios.
Download a copy of this deck for offline review.
To help you with next steps in evaluating SQL Server scenarios with the Microsoft Azure cloud platform, I've included several technical resources below ...
When managing Microsoft Azure Virtual Networks via the Azure Management Portal, we can easily see a list of IaaS Virtual Machines and/or PaaS web/worker roles that are connected to a particular virtual network, as shown below.
List of resources connected to Azure Virtual Network via Management Portal
Question: How can I determine this same type of list when using PowerShell to manage my Azure subscription?
Answer: Virtual networks are bound to Azure cloud service deployments for IaaS Virtual Machines and PaaS web/worker roles. Use the following PowerShell code snippet to display the list of cloud services, roles and instances that are connected to a particular Azure Virtual Network.
(Get-AzureService | Get-AzureDeployment | Where-Object ` -Property VNetName ` -EQ "enter-vnet-name") | %{ Get-AzureRole ` -ServiceName $_.ServiceName ` -InstanceDetails | Select-Object ` -Property ServiceName, InstanceName, RoleName, IPAddress }
After successfully provisioning new IaaS virtual machines or PaaS cloud services in Microsoft Azure, the focus often turns to workload monitoring for ensuring the continued health of the solutions we've deployed. Microsoft Azure includes native monitoring and email alerting capabilities for deployed workloads, and you can certainly extend monitoring to more granular levels with additional tools, such as Azure Automation, Application Insights, System Center 2012 R2 Operations Manager, or other 3rd party tools like New Relic.
However, manually configuring monitoring alert rules for a large number of workloads can take a lot of time. Unfortunately, the Azure PowerShell module doesn't currently provide direct scripting support to automate alert rule definition, BUT ... the Azure Service Management REST API does provide this capability, and we can easily leverage that API via PowerShell with a bit of creativity!
In this article, we'll step through the process of creating our own PowerShell function, named New-AzureAlert, to help us automate the provisioning of new Azure monitoring alert rules using the Azure Service Management REST API.
Before getting started in this article, you'll first need a few items:
After you've collected everything you'll need to get started, let's proceed to the next step ...
To authenticate to the Azure Service Management REST API endpoints, we'll be passing the subscription ID and management certificate for your Azure subscription. To obtain your subscription ID and management certificate, you can use the following snippet of code:
# Download Azure Publish Settings File Get-AzurePublishSettingsFile # Import Azure Publish Settings File Import-AzurePublishSettingsFile 'path-to-publish-settings-file' # Get your Azure subscription ID and certificate $subscriptionName = 'your-subscription-name' $subscription = Get-AzureSubscription ` -SubscriptionName $subscriptionName ` -ExtendedDetails $certificate = $subscription.Certificate $subscriptionId = $subscription.SubscriptionId
# Download Azure Publish Settings File
# Import Azure Publish Settings File
Import-AzurePublishSettingsFile 'path-to-publish-settings-file'
# Get your Azure subscription ID and certificate
$subscriptionName = 'your-subscription-name'
$subscription = Get-AzureSubscription ` -SubscriptionName $subscriptionName ` -ExtendedDetails
Tip! If you've previously authenticated to your Azure subscription via Azure AD credentials using the Add-AzureAccount cmdlet, you may first need to remove the Azure subscription information cached in your local subscription data file by using the Remove-AzureSubscription cmdlet. If you do not perform this step, the management certificate may not be properly returned when calling the Get-AzureSubscription cmdlet above.
Now that you've run through the lines above, you should have your Azure subscription ID stored in the $subscriptionId variable, and your management certificate should be stored in the $certificate variable.
To make it super-easy to add new monitoring alerts via the Azure Service Management REST API, let's define a new function in PowerShell named New-AzureAlert. When defining this function, we'll include input parameters for each of the key values needed to define a new monitoring alert in an Azure subscription. We'll also include comment-based help, so that others who are calling this function can easily learn how to use it via the Get-Help cmdlet.
Tip! See my prior Scripts-to-Tools article for a complete walk-through on each of the components of a PowerShell function.
Here's the code that we'll use to define the New-AzureAlert function:
function New-AzureAlert { <# .SYNOPSIS New-AzureAlert defines a new monitoring alert to an existing Cloud Service deployment. .DESCRIPTION New-AzureAlert defines a new monitoring alert to an existing Cloud Service deployment for IaaS Virtual Machines or PaaS Web/Worker roles. For demonstration purposes only. No support or warranty is supplied or inferred. Use at your own risk. .PARAMETER subscriptionId The Id of the Azure Subscription in which the Cloud Service is deployed .PARAMETER certificate Certificate used for authenticating to Azure subscription Id .PARAMETER cloudServiceName The name of an existing Cloud Service, as reported by Get-AzureService .PARAMETER deploymentName The name of an existing deployment within a Cloud Service, as reported by Get-AzureDeployment .PARAMETER roleName The name of an existing role within a Cloud Service deployment, as reported by Get-AzureDeployment .PARAMETER alertName The name for the new Alert to be added. The name can contain only letters, numbers, commas, and periods. The name can be up to 32 characters long. .PARAMETER alertDescription Optional description for the new Alert to be added. The description can contain only letters, numbers, commas, and periods. The description can be up to 128 characters long. .PARAMETER metricName Name of the metric on which to associate an alert rule. Valid metricName values include: "Percentage CPU" "Disk Read Bytes/Sec" "Disk Write Bytes/Sec" "Network In" "Network Out" .PARAMETER metricWindowSize Rolling timeframe across which metric should be evaluated against threshold. Valid metricWindowSize values include: "PT5M" (5 min) "PT15M" (15 min) "PT30M" (30 min) "PT45M" (45 min) "PT60M" (60 min) .PARAMETER metricOperator Operator used to compare metricName against metricThreshold. Value metricOperator values include: "GreaterThan" "GreaterThanOrEqual" "LessThan" "LessThanOrEqual" .PARAMETER metricThreshold Numeric value to which metricName is compared to determine if alert should be issued. .PARAMETER alertAdmins Indicates whether subscription administrators and co-administrators should be alerted via email. Valid alertAdmins values include: True, False .PARAMETER alertOther Email address for additional application administrator that should be alerted via email. .INPUTS Parameters above. .OUTPUTS json output for alert rule configuration that was successfully provisioned. .NOTES Version: 1.0 Creation Date: Nov 8, 2014 Author: Keith Mayer ( http://KeithMayer.com ) Change: Initial function development #> [CmdletBinding()] param ( [string]$subscriptionId, [object]$certificate, [string]$cloudServiceName, [string]$deploymentName, [string]$roleName, [string]$alertName, [string]$alertDescription, [string]$metricName, [string]$metricWindowSize, [string]$metricOperator, [decimal]$metricThreshold, [boolean]$alertAdmins, [string]$alertOther ) begin { $requestHeader = @{ "x-ms-version" = "2013-10-01"; "Accept" = "application/json" } $contentType = "application/json;charset=utf-8" $alertEnabled = "true" if ($alertAdmins) { $alertAdminsValue = "true" } else { $alertAdminsValue = "false" } } process { $alertId = ([GUID]::NewGuid()).Guid $alertManagementUri = "https://management.core.windows.net/$subscriptionId /services/monitoring/alertrules/$alertID" $alertRequest = @" { "Id": "$alertID", "Name": "$alertName", "IsEnabled": $alertEnabled, "Condition": { "odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.ThresholdRuleCondition", "DataSource": { "odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleMetricDataSource", "ResourceId": "/hostedservices/$cloudServiceName/deployments/$deploymentName/roles/$roleName", "MetricNamespace": "", "MetricName": "$metricName" }, "Operator": "$metricOperator", "Threshold": $metricThreshold, "WindowSize": "$metricWindowSize" }, "Actions": [ { "odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleEmailAction", "SendToServiceOwners": $alertAdminsValue, "CustomEmails": [ "$alertOther" ] } ] }"@ [byte[]]$requestBody = [System.Text.Encoding]::UTF8.GetBytes($alertRequest) $alertResponse = Invoke-RestMethod ` -Uri $alertManagementUri ` -Certificate $certificate ` -Method Put ` -Headers $requestHeader ` -Body $requestBody ` -ContentType $contentType } end { $alertListUri = "https://management.core.windows.net/$subscriptionID /services/monitoring/alertrules" $alerts = Invoke-RestMethod ` -Uri $alertListUri ` -Certificate $certificate ` -Method Get ` -Headers $requestHeader ` -ContentType $contentType $alerts.Value | ConvertTo-Json } }
function New-AzureAlert {
<# .SYNOPSIS New-AzureAlert defines a new monitoring alert to an existing Cloud Service deployment. .DESCRIPTION New-AzureAlert defines a new monitoring alert to an existing Cloud Service deployment for IaaS Virtual Machines or PaaS Web/Worker roles. For demonstration purposes only. No support or warranty is supplied or inferred. Use at your own risk. .PARAMETER subscriptionId The Id of the Azure Subscription in which the Cloud Service is deployed .PARAMETER certificate Certificate used for authenticating to Azure subscription Id .PARAMETER cloudServiceName The name of an existing Cloud Service, as reported by Get-AzureService .PARAMETER deploymentName The name of an existing deployment within a Cloud Service, as reported by Get-AzureDeployment .PARAMETER roleName The name of an existing role within a Cloud Service deployment, as reported by Get-AzureDeployment .PARAMETER alertName The name for the new Alert to be added. The name can contain only letters, numbers, commas, and periods. The name can be up to 32 characters long. .PARAMETER alertDescription Optional description for the new Alert to be added. The description can contain only letters, numbers, commas, and periods. The description can be up to 128 characters long. .PARAMETER metricName Name of the metric on which to associate an alert rule. Valid metricName values include: "Percentage CPU" "Disk Read Bytes/Sec" "Disk Write Bytes/Sec" "Network In" "Network Out" .PARAMETER metricWindowSize Rolling timeframe across which metric should be evaluated against threshold. Valid metricWindowSize values include: "PT5M" (5 min) "PT15M" (15 min) "PT30M" (30 min) "PT45M" (45 min) "PT60M" (60 min) .PARAMETER metricOperator Operator used to compare metricName against metricThreshold. Value metricOperator values include: "GreaterThan" "GreaterThanOrEqual" "LessThan" "LessThanOrEqual" .PARAMETER metricThreshold Numeric value to which metricName is compared to determine if alert should be issued. .PARAMETER alertAdmins Indicates whether subscription administrators and co-administrators should be alerted via email. Valid alertAdmins values include: True, False .PARAMETER alertOther Email address for additional application administrator that should be alerted via email. .INPUTS Parameters above. .OUTPUTS json output for alert rule configuration that was successfully provisioned. .NOTES Version: 1.0 Creation Date: Nov 8, 2014 Author: Keith Mayer ( http://KeithMayer.com ) Change: Initial function development #>
[CmdletBinding()] param ( [string]$subscriptionId, [object]$certificate, [string]$cloudServiceName, [string]$deploymentName, [string]$roleName, [string]$alertName, [string]$alertDescription, [string]$metricName, [string]$metricWindowSize, [string]$metricOperator, [decimal]$metricThreshold, [boolean]$alertAdmins, [string]$alertOther )
begin {
$requestHeader = @{ "x-ms-version" = "2013-10-01"; "Accept" = "application/json" } $contentType = "application/json;charset=utf-8" $alertEnabled = "true"
if ($alertAdmins) { $alertAdminsValue = "true" } else { $alertAdminsValue = "false" } }
process {
$alertId = ([GUID]::NewGuid()).Guid
$alertManagementUri = "https://management.core.windows.net/$subscriptionId /services/monitoring/alertrules/$alertID"
$alertRequest = @" { "Id": "$alertID", "Name": "$alertName", "IsEnabled": $alertEnabled, "Condition": { "odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.ThresholdRuleCondition", "DataSource": { "odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleMetricDataSource", "ResourceId": "/hostedservices/$cloudServiceName/deployments/$deploymentName/roles/$roleName", "MetricNamespace": "", "MetricName": "$metricName" }, "Operator": "$metricOperator", "Threshold": $metricThreshold, "WindowSize": "$metricWindowSize" }, "Actions": [ { "odata.type": "Microsoft.WindowsAzure.Management.Monitoring.Alerts.Models.RuleEmailAction", "SendToServiceOwners": $alertAdminsValue, "CustomEmails": [ "$alertOther" ] } ] }"@
[byte[]]$requestBody = [System.Text.Encoding]::UTF8.GetBytes($alertRequest)
$alertResponse = Invoke-RestMethod ` -Uri $alertManagementUri ` -Certificate $certificate ` -Method Put ` -Headers $requestHeader ` -Body $requestBody ` -ContentType $contentType
}
end {
$alertListUri = "https://management.core.windows.net/$subscriptionID /services/monitoring/alertrules"
$alerts = Invoke-RestMethod ` -Uri $alertListUri ` -Certificate $certificate ` -Method Get ` -Headers $requestHeader ` -ContentType $contentType
$alerts.Value | ConvertTo-Json
} }
Note that in this function definition, the requests for defining and confirming a new monitoring alert are submitted to the Azure Service Management REST API by calling the Invoke-RestMethod cmdlet in the highlighted code blocks above. This cmdlet was introduced as a new feature in PowerShell 4.0.
Our New-AzureAlert function is defined and ready to be used! We can easily call this function to define each monitoring alert as part of a larger provisioning script.
$alertRule = New-AzureAlert ` -alertName "High CPU" ` -alertDescription "Higher than 80% CPU utilization" ` -subscriptionId $subscriptionId ` -certificate $certificate ` -cloudServiceName "insert-cloud-service-name" ` -deploymentName "insert-deployment-name" ` -roleName "insert-VM-role-name" ` -metricName "Percentage CPU" ` -metricWindowSize "PT15M" ` -metricOperator "GreaterThan" ` -metricThreshold 80.0 ` -alertAdmins $true ` -alertOther "[email protected]"
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.
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.
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!
To complete the scenario presented in this article, you'll want to be sure to download the following components:
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") } } }
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.
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 AzureAdd-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
# Authenticate to AzureAdd-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.
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 configurationNew-AzureVM ` -VMs $vm ` -ServiceName $Using:vmServiceName ` -VnetName $Using:vNetName ` -AffinityGroup $Using:affinityGroupName ` -WaitForBoot ...
...
# 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 configurationNew-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".
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:
In prior articles, we've discussed Azure Automation, Azure VM Agent extensions and PowerShell Desired State Configuration (DSC) as individual tools and approaches for automated workload provisioning. I'm frequently asked about how these tools can be used together to orchestrate end-to-end provisioning of cloud workloads, including fabric, OS and application components.
This article is Part 1 of a two-part series.
In this article, I'll provide an example of leveraging Azure Automation runbooks and PowerShell Workflows in a concerted approach to fully automate all aspects of provisioning new IaaS workloads on the Microsoft Azure cloud platform.
In Part 2 of this series, 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 application components running inside each VM as part of the provisioning process.
We certainly don't have a lack of automation technologies these days! In fact, one could argue that we have so many different tools for automation, that sometimes it can be confusing to know which tools to leverage for a particular scenario. As I've been helping customers with automated provisioning sequences, here's an approach that I've found works well:
In the near future, Azure Resource Manager (ARM) will also be worthwhile including in your automation toolkit to manage cloud resources as a related group of dependencies. However, currently automation of ARM is limited to a subset of Azure PaaS resources. Azure IaaS support is coming soon, so be sure to watch this space for updates!
In the next few sections of this article, I'll step through the details around steps #1 and #2 above. In part 2 of this two-part series, I'll finish-up with coverage of steps #3, #4 and #5.
The example in this article assumes that you already have a few basic IaaS components provisioned in your Azure subscription with a consistent naming convention, including:
When provisioning these components, replace xxx with your unique initials to arrive at a consistent naming convention that provides globally unique names for the storage account and cloud service for the Windows Server Active Directory domain controller VM. If you need help provisioning these IaaS components, check out the following resources to help you get started:
Azure Automation provides a reliable, scalable platform service for orchestrating long-running processes that potentially touch several services and resources. Automation sequences are built as runbooks that include PowerShell Workflow activities. By leveraging PowerShell Workflows, Azure Automation runbooks can be suspended, resumed and recover from unexpected occurences while preserving current state of completed activities within the runbook.
If you haven't yet setup Azure Automation in your Microsoft Azure subscription or need some help with the basics of creating runbooks, check out this step-by-step article to walk through the process for getting started ...
Once your Azure Automation account is setup and ready to go, let's create a new Azure Automation runbook for provisioning our new cloud application, which we'll call MyWebApp in this article.
workflow New-MyWebAppDeployment{ }
workflow New-MyWebAppDeployment{
As mentioned above, Azure Automation runbooks leverage PowerShell Workflows, which is why we're defining our new runbook with the workflow keyword above.
In an effort to make this runbook reusable for a variety of provisioning scenarios, I'll define a set of parameter inputs at the top of the workflow. Azure Automation will prompt for user input for each defined parameter when manually starting this runbook, or you can supply these parameter values when programmatically invoking this runbook from another runbook or PowerShell script.
workflow New-MyWebAppDeployment{ param( [parameter(Mandatory=$true)] [String] $subscriptionName, [parameter(Mandatory=$true)] [String] $deploymentPrefix, [parameter(Mandatory=$true)] [Int] $numberOfVMs, [parameter(Mandatory=$true)] [String] $vmInstanceSize, [parameter(Mandatory=$true)] [String] $vmDomain, [parameter(Mandatory=$true)] [String] $vmDomainNetBIOS ) }
workflow New-MyWebAppDeployment{ param( [parameter(Mandatory=$true)] [String] $subscriptionName, [parameter(Mandatory=$true)] [String] $deploymentPrefix, [parameter(Mandatory=$true)] [Int] $numberOfVMs, [parameter(Mandatory=$true)] [String] $vmInstanceSize, [parameter(Mandatory=$true)] [String] $vmDomain, [parameter(Mandatory=$true)] [String] $vmDomainNetBIOS )
Let's also declare a set of variables near the top of our workflow for common values that will be used when provisioning virtual machines,
workflow New-MyWebAppDeployment{ ... continued from above ... # Get Azure credential for authenticating to Azure subscriptions $cred = Get-AutomationPSCredential -Name 'AzureAutomationAccount' # Get vmAdmin credential for admin access inside each VM $vmAdmin = Get-AutomationPSCredential -Name 'AzureAdmin' # Set common variable values for provisioning each VM $storageName = $deploymentPrefix + 'stor01' $vmServiceName = $deploymentPrefix +'app' $affinityGroupName = $deploymentPrefix + 'ag01' $availabilitySetName = $deploymentPrefix + 'app' $vNetName = $deploymentPrefix + 'net01' $subnetName ='Subnet-1' $dscArchive = 'AADSCWebConfig.ps1.zip' $dscConfigName = 'WebSiteConfig'}
... continued from above ...
# Get Azure credential for authenticating to Azure subscriptions $cred = Get-AutomationPSCredential -Name 'AzureAutomationAccount'
# Get vmAdmin credential for admin access inside each VM $vmAdmin = Get-AutomationPSCredential -Name 'AzureAdmin' # Set common variable values for provisioning each VM $storageName = $deploymentPrefix + 'stor01' $vmServiceName = $deploymentPrefix +'app' $affinityGroupName = $deploymentPrefix + 'ag01' $availabilitySetName = $deploymentPrefix + 'app' $vNetName = $deploymentPrefix + 'net01' $subnetName ='Subnet-1' $dscArchive = 'AADSCWebConfig.ps1.zip' $dscConfigName = 'WebSiteConfig'}
Now that we've got the initial portion of our runbook created, let's save it as a draft and continue with adding the code that will provision our VM and application.
In the param section of our runbook workflow above, you'll note that we defined a $numberOfVMs parameter to accept, as input, the number of load-balanced VMs that we'd like to provision for our application. To provide flexibility in provisioning a variable number of VMs, we'll add a for loop in our workflow that will handle the provisioning for each VM.
workflow New-MyWebAppDeployment{ ... continued from above ... for ($i=1; $i -le $numberOfVMs; $i++) { } }
for ($i=1; $i -le $numberOfVMs; $i++) {
As each iteration of the for loop above begins, we'll add code to checkpoint current workflow state and connect to the desired Azure subscription.
workflow New-MyWebAppDeployment{ ... continued from above ... for ($i=1; $i -le $numberOfVMs; $i++) { # Save current state of workflow Checkpoint-Workflow # Connect to Azure subscription Add-AzureAccount -Credential $cred Select-AzureSubscription ` -SubscriptionName $subscriptionName # Set current Azure Storage Account Set-AzureSubscription ` -SubscriptionName $subscriptionName ` -CurrentStorageAccountName $storageName } }
# Save current state of workflow Checkpoint-Workflow # Connect to Azure subscription Add-AzureAccount -Credential $cred
Select-AzureSubscription ` -SubscriptionName $subscriptionName # Set current Azure Storage Account Set-AzureSubscription ` -SubscriptionName $subscriptionName ` -CurrentStorageAccountName $storageName
Cloud workload provisioning tasks could involve many different cloud resources and be relatively long-running sequences. Taking the above approach of checkpointing workflow state and reconnecting to the desired Azure subscription with each iteration of our for loop will provide the ability for this runbook to gracefully resume in the event that the workflow was suspended or unexpectedly interrupted.
Next, let's add our code for provisioning each VM inside the for loop we've defined above. Since provisioning a new Azure VM can involve several individual activities to build the desired VM configuration, we'll group all of these related steps into a single InlineScript workflow activity.
workflow New-MyWebAppDeployment{ ... continued from above ... for ($i=1; $i -le $numberOfVMs; $i++) { Checkpoint-Workflow # Connect to Azure subscription Add-AzureAccount -Credential $cred Select-AzureSubscription ` -SubscriptionName $subscriptionName # Set current Azure Storage Account Set-AzureSubscription ` -SubscriptionName $subscriptionName ` -CurrentStorageAccountName $storageName # Provision VM InlineScript { $currentVM = "{0:D2}" -f $Using:i $vmName = $Using:deploymentPrefix + 'app' + $currentVM $vmImage = @((Get-AzureVMImage | Where-Object Label -like ` "Windows Server 2012 R2 Datacenter*").ImageName)[-1] $vmAdmin = $Using:vmAdmin # Specify VM name, image and size $vm = New-AzureVMConfig ` -Name $vmName ` -ImageName $vmImage ` -InstanceSize $Using:vmInstanceSize # Specify VM local admin and domain join creds $vm = Add-AzureProvisioningConfig ` -VM $vm ` -WindowsDomain ` -AdminUserName $vmAdmin.Username ` -Password $vmAdmin.GetNetworkCredential().Password ` -JoinDomain $Using:vmDomain ` -Domain $Using:vmDomainNetBIOS ` -DomainUserName $vmAdmin.Username ` -DomainPassword ` $vmAdmin.GetNetworkCredential().Password # Specify load-balanced firewall endpoint for HTTPS $vm = Add-AzureEndpoint ` -VM $vm ` -Name 'WebHTTPS' ` -LBSetName 'LBWebHTTPS' ` -DefaultProbe ` -Protocol tcp ` -LocalPort 443 ` -PublicPort 443 # Specify VNet Subnet for VM $vm = Set-AzureSubnet ` -VM $vm ` -SubnetNames $Using:subnetName # Specify HA Availability Set for VM $vm = Set-AzureAvailabilitySet ` -VM $vm ` -AvailabilitySetName $Using:availabilitySetName # Provision new VM with specified configuration New-AzureVM ` -VMs $vm ` -ServiceName $Using:vmServiceName ` -VnetName $Using:vNetName ` -AffinityGroup $Using:affinityGroupName ` -WaitForBoot } } }
Checkpoint-Workflow # Connect to Azure subscription Add-AzureAccount -Credential $cred
# Provision VM InlineScript { $currentVM = "{0:D2}" -f $Using:i $vmName = $Using:deploymentPrefix + 'app' + $currentVM $vmImage = @((Get-AzureVMImage | Where-Object Label -like ` "Windows Server 2012 R2 Datacenter*").ImageName)[-1] $vmAdmin = $Using:vmAdmin # Specify VM name, image and size $vm = New-AzureVMConfig ` -Name $vmName ` -ImageName $vmImage ` -InstanceSize $Using:vmInstanceSize # Specify VM local admin and domain join creds $vm = Add-AzureProvisioningConfig ` -VM $vm ` -WindowsDomain ` -AdminUserName $vmAdmin.Username ` -Password $vmAdmin.GetNetworkCredential().Password ` -JoinDomain $Using:vmDomain ` -Domain $Using:vmDomainNetBIOS ` -DomainUserName $vmAdmin.Username ` -DomainPassword ` $vmAdmin.GetNetworkCredential().Password # Specify load-balanced firewall endpoint for HTTPS $vm = Add-AzureEndpoint ` -VM $vm ` -Name 'WebHTTPS' ` -LBSetName 'LBWebHTTPS' ` -DefaultProbe ` -Protocol tcp ` -LocalPort 443 ` -PublicPort 443 # Specify VNet Subnet for VM $vm = Set-AzureSubnet ` -VM $vm ` -SubnetNames $Using:subnetName # Specify HA Availability Set for VM $vm = Set-AzureAvailabilitySet ` -VM $vm ` -AvailabilitySetName $Using:availabilitySetName # Provision new VM with specified configuration New-AzureVM ` -VMs $vm ` -ServiceName $Using:vmServiceName ` -VnetName $Using:vNetName ` -AffinityGroup $Using:affinityGroupName ` -WaitForBoot }
At this point, you can save and test your new runbook. When testing the runbook, you'll be prompted to input values for each parameter we defined. When prompted for a DeploymentPrefix, enter xxxlab, where xxx is your unique initials used at the top of this article. This prefix will be prepended to the Azure resource names used within the runbook to reference your unique naming convention.
After the runbook completes, you will have multiple VMs in the specified Azure subscription, storage account, affinity group and virtual network. Assuming you have a Windows Server Active Directory domain controller VM running on that same virtual network, each new VM will also be joined as a member server to the specified Active Directory domain.
In Part 2 of this series, we'll walk through wiring in PowerShell DSC to configure the operating system and applications inside the VM as part of the provisioning process ...
Thank you to those who attended my talk at CloudDevelop 2014 on Disaster Recovery to the Cloud with Azure Site Recovery today. We had some great discussions on disaster recovery planning scenarios! I'm providing a copy of the deck we used for our session, as well as a set of additional resources that may be helpful when planning your disaster recovery approach with Azure Site Recovery.
Continue your learning with these additional study materials ...
- Keith
Thank you to those who attended my webcast event on Open Source + Microsoft Azure last week. It was a great opportunity to discuss and demonstrate the broad support that's available on the Azure cloud platform for Open Source software solutions! In this article, I'm providing a copy of the deck we used for our session, as well as a set of additional resources that may be helpful in your continued learning and preparation around Open Source scenarios with Azure.
Continue your learning with these additional hands-on study materials ...
Thank you to those who attended my IT Camp event on Modernizing Your Infrastructure with Hybrid Cloud today in Chicago IL. I certainly enjoyed discussing cloud migration scenarios with everyone! In this article, I'm providing a copy of the deck we used for our sessions today, as well as a set of additional resources that may be helpful in your continued learning and preparation around Hybrid Cloud scenarios.
Continue your learning on Hybrid Cloud with these additional hands-on study materials ...
See you in the clouds!
A short time ago, I assisted an organization with defining a process for migrating web applications and data running on Ubuntu Linux virtual machines to the Microsoft Azure cloud platform from Amazon AWS. In this article, I’m documenting the general steps we used in an attempt to help other organizations that may be planning a similar migration approach.
NOTE: These steps were performed to migrate virtual machines running applications on Ubuntu Linux 14.04 and Apache2 to Microsoft Azure. The specific steps presented in this article may vary based on Linux operating system version as well as installed applications and packages. Use at your own discretion.
The migration process presented in this article makes minimal changes to the source virtual machines to prepare them for a successful migration. However, as with all migrations, performing and verifying a complete system backup is recommended to ensure that you can easily revert back to the original application environment, if necessary.
For the migration to be successful, the same Linux operating system distribution and version should be used for both source and target virtual machines. Others have successfully migrated between particular distros or versions, but the migration process for such a migration often requires an intimate knowledge of the source and target operating system configurations and can involve several additional tasks that are unique to each operating system version in use.
On each source VM, you can confirm the operating system distro and version with the following commands:
cat /etc/issue uname --all
cat /etc/issue
uname --all
Based on the information collected above in Task 2, provision new target virtual machines on the Microsoft Azure cloud platform using the same operating system distribution and version as the source virtual machines. I've recently published a Quick Start Guide which can be used to step through this process.
To help ensure that platform images between cloud providers are running the same version of key operating system packages, update these packages to the latest versions on both source and target virtual machines.
sudo apt-get update sudo apt-get upgrade
sudo apt-get update
sudo apt-get upgrade
The migration of application packages and files in this process will use rsync over ssh between source and target virtual machines. The actual transfer of files between virtual machines can take some time, so I also recommend using screen so that you can easily re-attach to an in-progress migration session if you are inadvertently disconnected.
Ensure that rsync and screen packages are installed on both the source and target virtual machines with these commands:
sudo apt-get install rsync sudo apt-get install screen
sudo apt-get install rsync
sudo apt-get install screen
To facilitate the migration process, ensure that you have a consistent user account configured on both source and target virtual machines with sudo enabled. The newly provisioned target virtual machines from Task 3 already include a user named azureuser with sudo enabled. To configure this same user on each source virtual machine, use the following commands:
sudo groupadd -g 500 azureuser sudo useradd -u 500 -g 500 -m -s /bin/bash azureuser sudo passwd azureuser
sudo groupadd -g 500 azureuser
sudo useradd -u 500 -g 500 -m -s /bin/bash azureuser
sudo passwd azureuser
When prompted for a new password for azureuser, enter the same password used when provisioning the target virtual machines in Task 3.
On the source virtual machine, enter a new screen session for the migration by using the following command:
sudo screen -S AzureMigration
If you are disconnected from the source virtual machine during the migration process, you can reconnect to the detached screen session by using the following command after signing in again to the source virtual machine:
sudo screen -r
During the migration, we want to be careful to skip any files that include configuration information relating to the identity of the source virtual machines, such as IP addresses, hostnames, ssh keys, etc. For the Ubuntu-based virtual machines that we migrated, we used the following commands on each source virtual machine to build our list of directories and files to exclude from the migration process:
EXCLUDEFILE=/tmp/exclude.file EXCLUDELIST='/boot /etc/fstab /etc/hostname /etc/issue /etc/hosts/etc/sudoers /etc/networks /etc/network/* /etc/resolv.conf /etc/ssh/* /etc/sysctl.conf /etc/mtab /etc/udev/rules.d/* /lock /net /tmp' EXCLUDEPATH=$(echo $EXCLUDELIST | sed 's/\ /\\n/g') echo -e $EXCLUDEPATH > $EXCLUDEFILE find / -name '*cloud-init*' >> $EXCLUDEFILE find / -name '*cloud-config*' >> $EXCLUDEFILE find / -name '*cloud-final*' >> $EXCLUDEFILE
EXCLUDEFILE=/tmp/exclude.file
EXCLUDELIST='/boot /etc/fstab /etc/hostname /etc/issue /etc/hosts/etc/sudoers /etc/networks /etc/network/* /etc/resolv.conf /etc/ssh/* /etc/sysctl.conf /etc/mtab /etc/udev/rules.d/* /lock /net /tmp'
EXCLUDEPATH=$(echo $EXCLUDELIST | sed 's/\ /\\n/g')
echo -e $EXCLUDEPATH > $EXCLUDEFILE
find / -name '*cloud-init*' >> $EXCLUDEFILE
find / -name '*cloud-config*' >> $EXCLUDEFILE
find / -name '*cloud-final*' >> $EXCLUDEFILE
The actual list of directories and files that you exclude may vary from this list, based on the Linux distro version, packages and applications that you are migrating.
Credits: Kudos to Kevin Carter who wrote a great article a couple years ago that provided a useful starting point for building a list of directories and files to consider excluding as part of a Linux-to-Linux migration process!
To minimize application data changes from occurring during the migration process, stop the related applications and daemons on the source virtual machines. The application that we migrated was a web application built using Apache2, so we simply stopped the related Apache2 daemon.
sudo service stop apache2
From each source virtual machine, migrate application files and data using two rsync passes over ssh. The first pass performs the bulk of the data transfer, whereas the second pass uses checksums to confirm that all files were transferred successfully.
TARGETVM="insert_target_vm_public_ip_address" rsync -e "ssh" -rlpEAXogDtSzh -P -x --exclude-from="$EXCLUDEFILE" --rsync-path="sudo rsync" --verbose --progress / azureuser@$TARGETVM:/ rsync -e "ssh" -crlpEAXogDtSzh -P -x --exclude-from="$EXCLUDEFILE" --rsync-path="sudo rsync" --verbose --progress / azureuser@$TARGETVM:/
TARGETVM="insert_target_vm_public_ip_address"
rsync -e "ssh" -rlpEAXogDtSzh -P -x --exclude-from="$EXCLUDEFILE" --rsync-path="sudo rsync" --verbose --progress / azureuser@$TARGETVM:/
rsync -e "ssh" -crlpEAXogDtSzh -P -x --exclude-from="$EXCLUDEFILE" --rsync-path="sudo rsync" --verbose --progress / azureuser@$TARGETVM:/
After both rsync passes have completed, restart each target virtual machine to complete the migration process.
ssh azureuser@$TARGETVM shutdown -r now
ssh azureuser@$TARGETVM
shutdown -r now
Do you have a different migration scenario from what's been presented in this article? If so, feel free to leave the details for your scenario in the Comments section below for us to consider documenting in a future article.
I’m frequently asked about templates, stencils and shapes that are available for documenting the architecture of cloud-based solutions on Microsoft Azure, Azure Pack and Office 365. Using the tools described in this article, you can quickly build professional architecture diagrams for cloud scenarios. These tools are also useful when creating presentation decks, training materials, whitepapers and infographics.
Sample LOB App Architecture on Azure IaaS
Several completed examples using these tools are available on the MSDN Azure Architecture Blueprints page, such as the Line of Business Applications IaaS diagram above (click on it to zoom in).
Azure symbol/icon/shape sets are available for download in PowerPoint, Visio and PNG formats.
Official Microsoft Azure Symbol Sets
Visio shapes for documenting Office 365, Exchange Server 2013, SharePoint Server 2013 and Lync Server 2013 deployments are also available as a free download. This set of stencils includes more than 300 icons and shapes.
Office Visio Stencil for Office 365, Exchange 2013, SharePoint 2013 and Lync 2013
In addition to the “official” templates above, Microsoft MVP Kevin Greene has done an outstanding job in building an “unofficial” set of Visio stencils for System Center and Azure Pack. These stencils are super-useful when documenting Private Cloud and Hybrid Cloud architectures.
Have you found additional templates, shapes and tools that you use when documenting the architecture of cloud solutions? Feel free to share any tools that you’ve found helpful in the Comments area below!
Linux is certainly a first-class workload on the Microsoft Azure cloud platform, and it's super-easy to get started with Linux + Azure to build a highly available and scalable solution in just a few minutes.
To help jump-start your skills on the steps for building Linux server solutions with Azure, I've prepared a Quick Start Guide that you can download, follow, and share with others in your community ...
Download a copy of this Quick Start Guide for viewing offline.
After you've stepped through this guide, be sure to check out our VMDepot repository containing hundreds of other pre-built Linux virtual machine images that you can quickly provision on the Microsoft Azure cloud platform.
With all of the buzz this week around the recently announced Windows 10 Technical Preview, you may have missed this announcement that a Technical Preview for the next version of Windows Server and System Center is also now available.
Windows Server Technical Preview – Server Manager and Start Menu
The Windows Server technical preview bits are now available as a virtual machine image on the Microsoft Azure cloud platform. Using this VM image on Microsoft Azure, you can spin-up your own test lab environment in the cloud in just a couple minutes – faster than you can download the installation bits from the TechNet Evaluation Center or MSDN Subscription Downloads.
In this article, I’ll provide the steps for provisioning your own Windows Server Technical Preview test lab environment on the Microsoft Azure cloud platform. Keep in mind that these bits contain an early pre-release build of the next version of Windows Server; these bits are not intended for running in a production environment.
To follow along with the steps in this article, you will need an active subscription for Microsoft Azure. If you don’t yet have an active subscription, you can sign-up for your own FREE Microsoft Azure trial subscription using the link below.
Now you have your own active Microsoft Azure subscription, follow these steps to build your own Windows Server Technical Preview test lab in the cloud:
Congratulations! You’ve completed the provisioning of a new test lab in the cloud for Windows Server Technical Preview using Microsoft Azure!
We’ll be blogging more about Windows Server Technical Preview in the coming weeks. In the meantime, here’s some additional resources that you may wish to check-out to continue your evaluation of Microsoft Azure and Windows Server Technical Preview …
Thank you for attending my breakout sessions at Dog Food Conference 2014 on Azure Automation and Hybrid Cloud. It was great meeting you all and discussing your scenarios with the Microsoft Azure cloud platform! For your convenience, I've included my decks below for each session. At the end of each deck, links to additional resources for learning more on each topic area are provided.
Download this deck for offline viewing.
To assist in your continued exploration of Hybrid Cloud Management, I'm also providing a free copy of my ebook on Cloud Management with System Center 2012 R2 App Controller.
I hope to see you again next year at Dog Food Conference 2015!
This article is Part 24 in the Modernizing Your Infrastructure with Hybrid Cloud series by our US IT Pro team. After you read this article, be sure to catch the full series for more information and resources.
When migrating to Hybrid Cloud, developing automated standards for provisioning and managing application workloads is key to accelerating the predictable deployment of new business solutions. As you begin developing scripts and workflows, being able to do so with consistency across on-premises datacenters and cloud platforms is important to promote reusability and agility when migrating these workloads.
Earlier this week in our Modernizing Your Infrastructure with Hybrid Cloud series, Yung Chou and I demonstrated the ability to leverage Windows PowerShell and the Azure PowerShell module as an easy way to get started with automation tasks for both Azure Pack private clouds and Microsoft Azure public clouds via the tenant service management API and PowerShell cmdlets.
So that you can follow along with this step-by-step demo, I’ve included the PowerShell snippets that we walked through in the section below.
To use the snippets below, you’ll need the following items to be setup in your environment:
After you’ve confirmed that you’ve met these requirements, open your Windows PowerShell ISE and copy/paste the snippet below to follow along with the step-by-step demo referenced above.
# Display version of Azure PowerShell moduleGet-Module -Name Azure # Display Azure environments availableGet-AzureEnvironment # Authenticate to Azure Add-AzureAccount # Show available Azure subscriptions(Get-AzureSubscription).SubscriptionName # List provisioned Azure VMsGet-AzureVM # Add new Azure environment for Azure PackAdd-AzureEnvironment ` -Name "AzurePackOnPrem" ` -PublishSettingsFileUrl "https://kemlabwap01.kemlabdom01.keithmayer.com:30081/publishsettings" # Authenticate to Azure PackGet-AzurePublishSettingsFile ` -Environment "AzurePackOnPrem"Import-AzurePublishSettingsFile ` -PublishSettingsFile "E:\INSTALL\Developer Plan.publishsettings" # Show available Azure subscriptions(Get-AzureSubscription).SubscriptionName # Select the Azure subscription associated with the Developer PlanSelect-AzureSubscription ` -SubscriptionName "Developer Plan" # Get Windows Azure Pack VM names(Get-WAPackVM).Name # Manage Windows Azure Pack resources$vm = Get-WAPackVM -Name "dev02vm"Stop-WAPackVM -VM $vmStart-WAPackVM -VM $vm # Provision new Azure Pack resources(Get-WAPackVNet).Name$vNet = Get-WAPackVNet ` -Name "kemlabdom01"(Get-WAPackVMTemplate).Name$vmTemplate = Get-WAPackVMTemplate ` -Name "DB Server"$creds = Get-CredentialNew-WAPackVM ` -Name "DB01" ` -Template $vmTemplate ` -VMCredential $Credentials ` -Windows ` -VNet $vNet
# Display version of Azure PowerShell moduleGet-Module -Name Azure
# Display Azure environments availableGet-AzureEnvironment
# Authenticate to Azure Add-AzureAccount
# Show available Azure subscriptions(Get-AzureSubscription).SubscriptionName
# List provisioned Azure VMsGet-AzureVM
# Add new Azure environment for Azure PackAdd-AzureEnvironment ` -Name "AzurePackOnPrem" ` -PublishSettingsFileUrl "https://kemlabwap01.kemlabdom01.keithmayer.com:30081/publishsettings"
# Authenticate to Azure PackGet-AzurePublishSettingsFile ` -Environment "AzurePackOnPrem"Import-AzurePublishSettingsFile ` -PublishSettingsFile "E:\INSTALL\Developer Plan.publishsettings"
# Select the Azure subscription associated with the Developer PlanSelect-AzureSubscription ` -SubscriptionName "Developer Plan"
# Get Windows Azure Pack VM names(Get-WAPackVM).Name
# Manage Windows Azure Pack resources$vm = Get-WAPackVM -Name "dev02vm"Stop-WAPackVM -VM $vmStart-WAPackVM -VM $vm
# Provision new Azure Pack resources(Get-WAPackVNet).Name$vNet = Get-WAPackVNet ` -Name "kemlabdom01"(Get-WAPackVMTemplate).Name$vmTemplate = Get-WAPackVMTemplate ` -Name "DB Server"$creds = Get-CredentialNew-WAPackVM ` -Name "DB01" ` -Template $vmTemplate ` -VMCredential $Credentials ` -Windows ` -VNet $vNet
Once you’ve completed this example for getting started with Hybrid Cloud automation, learn more with these additional resources:
UPDATE: Azure Automation has been updated to support Azure Active Directory authentication to simplify the steps for getting started! As an alternative to the steps below for configuring certificate-based authentication, check out this article by Joe Levy, Program Manager on the Azure Automation team, for getting started with Azure AD with Azure Automation..
Earlier this week, Microsoft Azure Automation was made available on the Microsoft Azure cloud platform as a public preview. This new feature allows you to automate the creation, monitoring, deployment and management of cloud resources in your Microsoft Azure subscription using a highly-available workflow execution engine. Azure Automation provides an orchestration feature set for public cloud resources that is similar to what the Service Management Automation (SMA) engine provides for on-premises private cloud resources via the Windows Azure Pack and System Center 2012 R2 Orchestrator.
Azure Automation is super-cool, because it allows us to perform automated cloud provisioning and management without needing to manually build and manage a separate set of automation servers. And … scalability and high availability of the Azure Automation engine is provided natively via the Microsoft Azure cloud platform without any extra configuration steps, which helps to make sure that your scheduled runbooks will always execute when needed.
In this article, I’ll step through the process of getting started with Azure Automation. Along the way, we’ll build a runbook and PowerShell workflow for performing basic automation of Microsoft Azure virtual machines.
To leverage Microsoft Azure Automation, you’ll need an active Azure subscription with the Microsoft Azure Automation preview feature activated.
Azure Automation authenticates to Microsoft Azure subscriptions using certificate-based authentication. You can create and export a new management certificate using the Internet Information Services (IIS) Manager tool from any Windows Server installed with the IIS Web Server role and management tools.
Use the steps below to create and export a new management certificate from a server running Windows Server 2012 or 2012 R2. After creating a new certificate, you will export this certificate as a .CER file for uploading to your Microsoft Azure subscription and also as a .PFX file for uploading to your Azure Automation account.
Now that you have a new management certificate created and exported, you’ll need to upload the exported .CER file to your Microsoft Azure subscription.
For your Azure Automation account to be able to authenticate to your Microsoft Azure subscription, you’ll also need to upload the certificate .PFX file. You’ll upload this certificate as an Asset in your Azure Automation account so that it can be consistently leveraged across multiple runbooks.
You can also define the connection information for your Microsoft Azure subscription as an Asset in your Azure Automation account. Doing so allows you to easily relate your Microsoft Azure subscription name, subscription ID and management certificate together as a centralized definition for use in all of your runbooks.
There's a few lines of code that are used to connect a runbook to your Microsoft Azure subscription using the management certificate asset and connection asset that were previously defined. To promote easy maintenance of runbooks, we recommend centralizing this code into one Connect-Azure runbook that other runbooks can reference.
Luckily, the Azure Automation team has made this approach super-easy by providing us with a standard runbook template on the Azure Automation Script Center.
We’re ready to create a runbook for automating the provisioning and management of cloud resources in your Microsoft Azure subscription. In this article, the runbook we’ll create will be used to automate the safe shutdown of on-demand lab virtual machines at the end of each day. This runbook will stop and deallocate each specified virtual machine so that compute charges for these lab VMs do not continue to accrue when they are not being used.
After saving the draft runbook, you can test the new runbook to confirm that it executes successfully.
When you’ve tested the runbook and confirmed that it executes successfully, you can publish the new runbook for running on a scheduled basis.
We want this new runbook to execute at the end of every day, to make sure that our lab VM’s are automatically stopped and deallocated when not being used. To execute a runbook on a scheduled basis, we can link the runbook to a recurring schedule.
In this article, we’ve created a simple Azure Automation runbook to stop and deallocate lab VMs on the Microsoft Azure cloud platform. This runbook provides a great starting point, but it’s just one example of the power of this new preview feature. Azure Automation can leverage any of the Microsoft Azure PowerShell cmdlets for automating more sophisticated cloud tasks, and we can also extend Azure Automation by importing additional PowerShell modules.
When you’re ready to learn more about Azure Automation, be sure to check out the additional resources available on our Microsoft Azure documentation portal:
Are there particular cloud scenarios in which you have interest? Feel free to leave your comments and feedback below, and we’ll try to write-up as many additional scenarios as possible in the coming weeks.
See you in the Clouds!
This article is part 23 in our continuing series on Modernizing Your Infrastructure with Hybrid Cloud by our US IT Pro team. After you've read this article, be sure to catch all of the other articles in our series!
As I’ve been traveling and speaking to IT Pros about the great scalability, resiliency and offerings in our Microsoft Azure public cloud platform, there’s also been lots of interest around deploying our free Windows Azure Pack (WAP) to bring the power and consistency of the same self-service Azure portal user interface to on-demand Private Clouds provisioned in an on-premises datacenter.
Service Management Portal in Windows Azure Pack
In this article, we’ll step through the process of setting up Windows Azure Pack in a lab environment for provisioning and delegating VM private clouds. Along the way, I’ll call out the specific details that I found helpful to successfully build my own lab environment.
For a technical overview of the Windows Azure Pack, check out this great Microsoft TechEd session:
In addition, Thomas Maurer, MVP for Cloud and Virtualization, has written a great article that describes the overall architecture of Windows Azure Pack:
For more detailed training on Azure Pack, attend this free online Microsoft Virtual Academy Jump Start that was recently recorded by Symon Perriman and Andrew Zeller:
Windows Azure Pack certainly has the ability to scale to support very large Private Cloud environments consisting of multiple datacenters. However, in this article, we’ll get started by building a basic lab environment that consists of the following four (4) VMs:
To configure all four (4) VMs in your lab environment, you’ll need a virtualization host with at least 16GB RAM and 300GB available disk space.
Before installing Windows Azure Pack, it’s important to confirm that your on-premises virtualization infrastructure is in-place. Windows Azure Pack leverages System Center 2012 R2 Virtual Machine Manager (VMM) as a private cloud fabric controller for handling on-demand provisioning and management of virtual machines “behind-the-scenes”, so you’ll want to confirm that VMM is setup in your environment and is connected to one or more supported virtualization host platforms for running virtual machines, such as Hyper-V, VMware or Citrix XenServer.
To setup VMM in your lab environment, be sure to review the following resources:
As part of this base configuration, you’ll also install a Microsoft SQL Server that will be used by all components in this lab environment.
After VMM is setup and connected to your virtualization hosts, there’s a few specific configuration tasks to keep in mind when defining Private Clouds and VM Networks as part of your cloud fabric in VMM. These steps are important if you’ll be using Windows Azure Pack, because WAP won’t recognize your fabric resources as being available for on-demand provisioning via the Service Management Portal unless they are configured properly.
You must have a VM network available to which tenant VMs can be associated. This VM network can be created using the VMM Console if you wish to provide a standard VM network that is shared across tenants.
If you wish tenants to be able to create their own on-demand VM Networks in the WAP Service Management Portal for Tenants, you must configure the Logical Network that is associated with your cloud in the steps above for Hyper-V Network Virtualization (HNV). To do this, be sure to select the One Connected Network option, and then select the Allow VM Networks created on this logical network to use network virtualization checkbox in the VMM console when configuring your Logical Network.
If you plan to leverage Hyper-V Network Virtualization (HNV) for your Logical Network and VM Networks, check out these resources for more details and step-by-step guidance:
When configuring Private Clouds in VMM, be sure to follow these TechNet guidelines:
When creating virtual machine templates in VMM that you will use with WAP, follow this TechNet guidance:
For instructions, see How to Create a Virtual Machine Template.
Windows Azure Pack uses Service Provider Foundation (SPF) to communicate with VMM when provisioning and managing VM Clouds. SPF provides an extensible OData web service that the WAP Service Management Portals communicate with to interact with VMM. SPF is a component that is included with System Center 2012 R2 Orchestrator, so you’ll be installing SPF from the Orchestrator media in these steps.
We’re now ready to install the Windows Azure Pack (WAP) components. In this article, we use the Express installation option, where all WAP server components are installed on a single VM that is separate from the SPF server VM. For larger installations involving lots of tenants, there are also options for distributed deployment and high availability.
Now that your lab environment is built, you’re ready to register your SPF server from the Windows Azure Pack admin portal and deploy to VM Clouds!
To continue down this path, be sure to reference these next steps …
So far, we’ve setup the basics of provisioning and managing on-demand Private Clouds using the Windows Azure Pack. In future articles, we’ll work on extending our lab to include the following additional components …
Keith Mayer is a Senior Technical Evangelist at Microsoft, focused on helping ISV partners leverage the Azure cloud platform. Keith has over 20 years of experience as a technical leader of complex IT projects, in diverse roles, such as Network Engineer, IT Manager, Technical Instructor and Consultant. He has consulted and trained thousands of customers and partners worldwide on design of enterprise technology solutions.
Keith is currently certified on several Microsoft technologies, including Private Cloud, System Center, Hyper-V, Windows, Windows Server, SharePoint and Exchange. He also holds other industry certifications from VMware, IBM, Cisco, Citrix, HP, CheckPoint, CompTIA and Interwoven.
You can contact Keith online at http://aka.ms/AskKeith.