lift-and-shift-5

Moving to Microsoft Azure

Every time I dig a little deeper into Azure, I’m amazed at how much there is to know. Having done a few projects with Cloud Services in the past, I thought it would be interesting to see if it was possible to lift and shift a Console Application into an Azure Worker Role.

Lift and Shift: The action of moving a workload to a new environment, without altering the application’s code.

Prerequisites

☁ Tools

Using the Microsoft Web Platform Installer install the latest Microsoft Azure PowerShell with Microsoft Azure SDK.

☁ Microsoft Azure Account

In order to deploy your workload to Microsoft Azure, be sure to have an account. You can create a Free Trial Account on the azure.com website.

Creating a Worker Role without Visual Studio

A Worker Role is a role that is useful for generalized development, and may perform background processing for a Web Role. When you have a need for a background process that performs long running or intermittent tasks, you should use this role.

Let’s fire-up Windows PowerShell ISE and navigate to the folder where you want to create your Cloud Service. For this blog post, I created a new folder, demo-lift-and-shift, in my Documents.

C:\users\<user id>\Documents\demo-lift-and-shift

In the PowerShell console, execute the following commands.

# Create the Cloud Service
New-AzureServiceProject -ServiceName 'console-lift-and-shift' -Verbose

# Create the Worker Role
Add-AzureWorkerRole -Name 'ConsoleWorkerRole' -Instances 1 -Verbose

These two commands will produce the following files and documents. This represents the Cloud Service project. It contains the configurations and the Cloud Service definition.

project

The ServiceDefinition.csdef was created by PowerShell when we executed the New-AzureServiceProject command. Then it was updated when we executed the Add-AzureWorkerRole. The following is the unchanged version of the service definition. Since it is missing a few pieces, I will show you what to change in order to be able to deploy your brand-new service to Microsoft Azure.

The ServiceDefinition.csdef file contains the metadata that is required by the Azure environment for the requirements of your cloud service, including what roles it contains. This file also contains configuration settings that apply to all instances. These configuration settings can be read at runtime using the Azure Service Hosting Runtime API. This file cannot be updated while your service is running in Azure.

<?xml version="1.0" encoding="utf-16"?>
<ServiceDefinition xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   name="console-lift-and-shift"
                   xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WorkerRole name="ConsoleWorkerRole">
    <Startup>
      <Task commandLine="setup_worker.cmd > log.txt" executionContext="elevated">
        <Environment>
          <Variable name="EMULATED">
            <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
          </Variable>
          <Variable name="RUNTIMEID" value="" />
          <Variable name="RUNTIMEURL" value="" />
        </Environment>
      </Task>
      <Task commandLine=".\startup.cmd > startup_log.txt" executionContext="elevated" />
    </Startup>
    <Endpoints>
      <InputEndpoint name="HttpIn" protocol="tcp" port="80" />
    </Endpoints>
    <Runtime>
      <Environment>
        <Variable name="PORT">
          <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/Endpoints/Endpoint[@name='HttpIn']/@port" />
        </Variable>
        <Variable name="EMULATED">
          <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" />
        </Variable>
      </Environment>
      <EntryPoint>
        <ProgramEntryPoint commandLine="worker.cmd" setReadyOnProcessStart="true" />
      </EntryPoint>
    </Runtime>
  </WorkerRole>
</ServiceDefinition>

Specify a Role (Virtual Machine) size

The size of the role determines the number of CPU cores, the memory capacity, and the local file system size that is allocated to a running instance. The following

  • ExtraSmall (1 CPU, 768 MB RAM, 19 GB DISK)
  • Small (1 CPU, 1.75 GB RAM, 224 GB DISK)
  • Medium (2 CPU. 2.5 GB RAM, 489 GB DISK)
  • Large (4 CPU 7 GB RAM, 999 GB DISK)
  • ExtraLarge (8 CPU, 14 GB RAM, 2039 GB DISK)

Considerations to help you decide on the correct size for your workload

  1. Instances can now be configured to use a D-series VM. These are designed to run applications that demand higher compute power and temporary disk performance. D-series VMs provide faster processors, a higher memory-to-core ratio, and a solid-state drive (SSD) for the temporary disk. For details, see the announcement on the Azure blog, New D-Series Virtual Machine Sizes.
  2. Web roles and worker roles require more temporary disk space than Azure Virtual Machines because of system requirements. The system files reserve 4 GB of space for the Windows page file, and 2 GB of space for the Windows dump file.
  3. The OS disk contains the Windows guest OS and includes the Program Files folder (including installations done via startup tasks unless you specify another disk), registry changes, the System32 folder, and the .NET framework.
  4. The local resource disk contains Azure logs and configuration files, Azure Diagnostics (which includes your IIS logs), and any local storage resources you define.
  5. The apps (application) disk is where your .cspkg is extracted and includes your website, binaries, role host process, startup tasks, web.config, and so on.

More details about Virtual Machine and Cloud Service Sizes for Azure can be found in the official Azure documentation.

For this example we will use a Medium sized role (Virtual Machine) for our Cloud Service.

Replace

<WorkerRole name="ConsoleWorkerRole">

By

<WorkerRole name="ConsoleWorkerRole" vmsize="Medium">

Specify a Guest OS Version

Guest OS families and versions have a release date, a disabled date, and an expiration date. As of the release date, a Guest OS version can be manually selected in the management portal. A Guest OS is removed from the management portal on or after its “disabled” date. It is then “in transition” but is supported with limited ability to update a deployment. The expiration date is when a version or family is scheduled to be removed from the Azure system completely. Cloud services still running on a version when it expires will be stopped, deleted or force upgraded to a newer version, as detailed in the Azure Guest OS Supportability and Retirement Policy. Microsoft supports at least two recent versions of each supported Guest OS family.

Available Families as of December 2014

  • FAMILY 4
    Windows Server 2012 R2
    Supports .NET 4.0, 4.5, 4.5.1, 4.5.2
  • FAMILY 3
    Windows Server 2012
    Supports .NET 4.0, 4.5
  • FAMILY 2
    Windows Server 2008 R2 SP1
    Supports .NET 3.5, 4.0

More details about Azure Guest OS Releases can be found in the official Azure documentation.

project

The ServiceConfiguration.{Environment}.cscfg was created by PowerShell when we executed the Add-AzureWorkerRole PowerShell command.

The configuration of the settings for your cloud service is determined by the values in the ServiceConfiguration.cscfg file. You specify the number of instances that you want to deploy for each role in this file. The values for the configuration settings that you defined in the service definition file are added to the service configuration file. The thumbprints for any management certificates that are associated with the cloud service are also added to the file. The Azure Service Configuration Schema (.cscfg File) provides the allowable format for a service configuration file.

The following is the unchanged version of the ServiceConfiguration.Cloud.cscfg file. Since it is missing a few pieces, I will show you what to change in order to be able to deploy your brand-new service to Microsoft Azure.

<?xml version="1.0" encoding="utf-16"?>
<ServiceConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      serviceName="console-lift-and-shift"
                      osFamily="2"
                      osVersion="*"
                      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="ConsoleWorkerRole">
    <ConfigurationSettings />
    <Instances count="1" />
    <Certificates />
  </Role>
</ServiceConfiguration>

For this example we will use Family 4 because our Console Application is built using .Net 4.5.

Replace

<ServiceConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      serviceName="console-lift-and-shift"
                      osFamily="2"
                      osVersion="*"
                      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">

By

<ServiceConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      serviceName="console-lift-and-shift"
                      osFamily="4"
                      osVersion="*"
                      xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">

We left osVersion=”*” to allow the Azure Fabric to continuously patch the Guest OS.

Packaging The Console Application as a Cloud Service

The ConsoleWorkerRole folder contains the files and documents that compose our new Azure Worker Role

worker-role

Place the files that compose the Console Application in this folder. The example used for this Blog is an application that writes messages to an Azure Storage Queue.

console-role

Be sure to include the application’s dependencies such that nothing stops the application from running once it is deployed to an Azure Worker Role. If, for some reason, the application does not seem to run as expected, refer to my earlier blog post that shared techniques to investigate and debug Azure Roles.

Before we package the Azure Cloud Service, we must update the worker.cmd file. This file contains the application loop that is executed by the Azure Worker role. The following is the initial version of the file.

:workerLoop

:: Do work
ping 123.45.67.89 -n 1 -w 1000000 &gt; nul

goto workerLoop

In order to start the application, replace the ping command by a direct call to the application’s executable. Every time the application terminates, it will be restarted. This is the first of many mechanisms in place to ensure that the application is resilient and available.

:workerLoop

:: This EXE will be re-invoked every time it completes it's execution
DemoAppWritingToAQueue.exe

goto workerLoop

Be sure to select the ANSI Encoding then you save your changes. Failing to do so may prevent the CMD script from executing.

encoding

Now that we have the Console Application wired up to the Worker Role, it’s time to package the Cloud Service. In Windows PowerShell ISE and navigate back to the folder that contains the Cloud Service.

The Cloud Service for this blog post is at the following location:

C:\users\<user id>\Documents\demo-lift-and-shift\console-lift-and-shift

In the PowerShell console, execute the following commands.

# Package the Cloud Service
Save-AzureServiceProjectPackage

This produces a package named cloud_package.cspkg, which is required for the service’s deployment.

cloud-service-package

Deploying the Cloud Service

This step has a prerequisite. We must start by importing a publish profile from our Microsoft Azure Subscription. PowerShell will use it to publish our Cloud Service to our Microsoft Azure.

In the PowerShell console, execute the following commands.

# Opens a website that allows us to download the Publish Profile
# associated with our Microsoft Azure Subscription
Get-AzurePublishSettingsFile

Save the publish settings files to your downloads folder then import it using the following command.

Import-AzurePublishSettingsFile -PublishSettingsFile 'C:\Users\<user id>\Downloads\<subscription name>-credentials.publishsettings'

We are now ready to publish our brand-new Cloud Service. The following command will create a new storage account to upload our package. This is the default behavior because we did not provide a storage account for the command. We specified a name for the service, a location (datacenter), a slot (production or staging) and a deployment name. For more information about the Publish-AzureServiceProject command please refer to the official documentation.

Publish-AzureServiceProject -ServiceName 'lift-and-shift-demo' 
                            -Location 'East US' 
                            -Slot 'Production' 
                            -DeploymentName '2014-12-14-15-46' 
                            -Verbose

If the Publish-AzureServiceProject command is executed with the -Verbose flag, it will produce a detailed output that allows you to understand what is happening. It’s also very useful when you need to debug a failed deployment.

WARNING: Publishing lift-and-shift-demo to Microsoft Azure. This may take several minutes...
WARNING: 3:47:10 PM - Preparing runtime deployment for service 'lift-and-shift-demo'
WARNING: 3:47:11 PM - Verifying storage account 'liftx2dandx2dshiftx2ddem'...
WARNING: 3:47:43 PM - Preparing deployment for lift-and-shift-demo with Subscription ID: dfbedef7-xxxx-xxxx-xxxx-650ca03208ee...
WARNING: 3:47:47 PM - Connecting...
WARNING: 3:47:48 PM - Creating...
WARNING: 3:47:49 PM - Created hosted service 'lift-and-shift-demo'.
WARNING: 3:47:49 PM - Uploading Package to storage service liftx2dandx2dshiftx2ddem...
WARNING: 3:47:56 PM - Starting...
WARNING: 3:48:30 PM - Created Deployment ID: 03e36c62a5f74d5f9ebd0a2ec0b16880.
WARNING: 3:48:30 PM - Initializing...
WARNING: 3:51:49 PM - Instance ConsoleWorkerRole_IN_0 of role ConsoleWorkerRole is busy.
WARNING: 3:52:22 PM - Instance ConsoleWorkerRole_IN_0 of role ConsoleWorkerRole is ready.
WARNING: 3:52:23 PM - Created Website URL: http://lift-and-shift-demo.cloudapp.net/.

PersistentVMDowntime : Microsoft.WindowsAzure.Commands.Utilities.CloudService.Model.PersistentVMDowntimeInfo
Name                 : 2014-12-14-15-46
DeploymentSlot       : Production
PrivateID            : 03e36c62a5f74d5f9ebd0a2ec0b16880
Status               : Running
Label                : lift-and-shift-demo
Url                  : http://lift-and-shift-demo.cloudapp.net/
Configuration        : &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-16&quot;?&gt;&lt;ServiceConfiguration xmlns:xsd=&quot;http://www.w3.org/2001/XMLSchema&quot;
                       xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; serviceName=&quot;lift-and-shift-demo&quot; osFamily=&quot;4&quot; osVersion=&quot;*&quot;
                       xmlns=&quot;http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration&quot;&gt;  &lt;Role name=&quot;ConsoleWorkerRole&quot;&gt;
                       &lt;ConfigurationSettings /&gt;    &lt;Instances count=&quot;1&quot; /&gt;    &lt;Certificates /&gt;  &lt;/Role&gt;&lt;/ServiceConfiguration&gt;
RoleInstanceList     : {ConsoleWorkerRole}
UpgradeStatus        :
UpgradeDomainCount   : 1
RoleList             : {ConsoleWorkerRole}
SdkVersion           : 2.5.6496.10
Locked               : False
RollbackAllowed      : False
VirtualNetworkName   :
CreatedTime          : 2014-12-14 3:47:58 PM
LastModifiedTime     : 2014-12-14 3:52:23 PM
ExtendedProperties   : {}
Dns                  :
VirtualIPs           : {Microsoft.WindowsAzure.Commands.Utilities.CloudService.Model.VirtualIP}

Once the Cloud Service has completed its deployment, you can log into the https://manage.windowsazure.com portal and you will be able to monitor and alter its configurations.

azure-portal

Because this solution does not rely on the .NET Azure SDK and since the CMD script has an infinite loop, I did not see a recycling status for my Azure Worker Role when it wasn’t configured properly. In the previous screen capture, we can observe a high CPU, which is unexpected for my Console Application. This was because I had deployed my Cloud Service on Guest OS Family 2 instead of 4 and that the .NET Framework 4.5 was missing. This cause my Console Application to continuously fail to start. The CMD worker script kept restarting my Console Application and ate up the entire CPU. Consequently, I updated the ServiceConfiguration.Cloud.cscfg file with the correct Guest OS Family and redeployed the Cloud Service.

Out of curiosity, I configured the Remote Desktop Extension through the management portal and peaked into the provisioned instance. I was happy to find my Console Application running normally.

running-console-app

Bringing it All Together

Azure Worker Roles support a surprising variety of scenarios! Here’s a quick recap of the steps taken to Lift & Shift a Console Application to Microsoft Azure.

# Create the Cloud Service
New-AzureServiceProject -ServiceName 'console-lift-and-shift' -Verbose

# Create the Worker Role
Add-AzureWorkerRole -Name 'ConsoleWorkerRole' -Instances 1 -Verbose

Update the configurations files with the appropriate Guest OS Family and with the desired VM Size for your Cloud Service. Then copy the Console Application and its dependencies to the Role’s folder. Don’t forget to update the worker.cmd script file so that it executes the desired Console Application.

# Package the Cloud Service
Save-AzureServiceProjectPackage

# Publish the Package to Microsoft Azure 
Publish-AzureServiceProject -ServiceName 'lift-and-shift-demo' 
                            -Location 'East US' 
                            -Slot 'Production' 
                            -DeploymentName '2014-12-14-15-46' 
                            -Verbose

3 responses to Lift and Shift of a Console Application to Microsoft #Azure

  1. 

    Very nice and informative article Alex

    Liked by 2 people

Trackbacks and Pingbacks:

  1. Deploying an #Azure Cloud Service That Requires Elevated Privileges « Alexandre Brisebois ☁ - February 17, 2015

    […] There are various scenarios that require us to execute applications with elevated privileges. It’s common for this requirement to surface during lift and shift efforts. […]

    Like

  2. Lift and Shift of a Windows Service to Microsoft #Azure « Alexandre Brisebois ☁ - February 22, 2015

    […] written about lifting and shifting a Console Application, I decided to mirror the scenario and describe how a similar method can be used to lift and shift a […]

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s