Power of startup tasks in Azure

Premise

Hello rock stars, ready for some hacking? Off course!

Some of us might know that Azure (or for that matter many cloud providers) presents two main implementation paradigms:

  • PaaS : Platform-as-service – is more like renting a serviced apartment. Which means the focus is on implementing requirements. Consumers need *not* think about infrastructure procuring, installing operating system patches etc.Just zip the package and give it to Azure which then manages the show for you.
  • IaaS : Infrastructure-as-service – is like renting a condo. Which means apart from implementing business requirements – it’s consumer’s duty to maintain and manage the virtual infrastructure.

IaaS provides more power for sure, but remember what uncle Ben told to Peter Parker. Great power comes with great responsibilities! 🙂

PaaS world is little different and especially if you are a Dev-Test-Deploy kind of shop it makes sense to invest in PaaS paradigm. But then many have this question that if Microsoft is providing all the software and platform then how do I run my custom software in Azure PaaS? How do I install piece of software that Azure does not provide out of the box? Azure does answer that question in the form of start up tasks.

Idea is – you run a scripted command in form of *.bat or *.cmd in a bootstrap manner. So even if Azure recycles or reimages your machines, the start up task/script always makes sure that things are correctly installed.It is very powerful approach when you have a small task to perform or a tiny custom widget to install . E.g. : you want to install an ISAPI extension, so that you can run PHP on the hosted IIS. Or you want to install your custom diagnostics monitor that records a stream of SLL events and do something about it.

Just to be clear, start up tasks are *not* meant to perform heavy duty operations. E.g if you want install let’s say a SAP instance on Azure – you should go for IaaS and start up tasks are not meant for you.

Breaking shackles

Scenario

We all might know that Azure is offering a distributed Redis cache-as-service. It is true platform as service, wherein consumers need not worry about disaster recovery, business continuity planning etc.  Let’s just say that you want to run and consume your own Redis cache instance as a local cache inside a Azure web role. Let’s see if we can pull it off using start up tasks.

MS Open Tech has forked Redis cache and have ported Redis to Windows. We would be using those bits.

Step 1 : Building the correct file structure

Let’s download the Redis cache bits for windows from MS Open Tech page. We need to add two files at the root of the role that would be used in a start up task.

  • InstallPatch.bat : You can name this file whatever you please. This file is where we would write a command that would be executed by the startup task.
  • Redis-x64.msi  : This is the actual Redis cache windows service executable (msi in this case) we are installing.

Make sure both these files are marked as “copy to output directory”. This is to ensure these two files are copied as part of the package. image

Step 2 : Building a bootstrap command

Let’s build a command that can be used to install the Redis cache windows service (.msi in this case) on the Azure VMs. The idea is – you want to install this MSI in a silent/quite mode since you do not want a GUI to wait for user’s action. After looking into the documentation (that gets downloaded along with the bits) here is how we can achieve it :

As you can see below we can use /quiet switch to msiexec command that makes sure the installation happens silently. Step 1 is going to copy the the command and exe file to the package.

To get to the root of the role we can use an environment variable called %RoleRoot. PORT=6379 parameter makes sure that the Redis cache server starts listening on port 6379 after installation

msiexec /quiet /i %RoleRoot%\AppRoot\Redis-x64.msi PORT=6379 FIREWALL_ON=1
Step 3 : Encapsulating the command in a start up task

Now that command is setup let’s see how to encapsulate this in a start up task. Good news is it is configuration driven. Service definition configuration (csdef) to be specific. Insert following config in your csdef file.

<Startup>
  <Task commandLine="InstallPatch.bat" executionContext="elevated" 
    taskType="background" />
</Startup>

Above config instructs Azure role to run InstallPatch.bat file in an elevated manner (as an Admin) in the background. It executes the command we prepared and makes sure that redis-x64.msi is installed correctly on the Azure VM. Apart from the background, taskType can take following 2 values:

  • foreground : foreground tasks are executed asynchronously like background. The key difference between a foreground and a background task is that a foreground task keeps the role in a running state. Which means a role can not recycle until and unless a foreground task is complete or failed. If the task is background in nature then the role can be recycled even if the task is still running
  • Simple : simple task is run synchronously one at a time
Step 4 : Using the Redis cache

If the startup task described is successfully complete then we have a Redis windows service installed and listening on 6479 port. Let’s see how we can use it in a app.

Let’s pull a nuget package called ServiceStack.Redis.Signed which is a client library to consume the Redis service. There are many Redis clients available for .NET, you can choose any as per your liking. We can do something like below:

using System;
using ServiceStack.Redis;

namespace WebRole1
{
    public partial class Index : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
	    // Creates proxy to Redis service listening on 127.0.0.1:6379
            var client = new RedisClient("127.0.0.1", 6379);

            var key = Guid.NewGuid().ToString();

            // Sets a key-value pair in the cache
	    client.Set(key, Guid.NewGuid().ToString());

	    // Gets the value from the cache
            var val = client.Get(key);

            Response.Write("Cache Value : " + val);
        }
    }
}

Once again, I am not advocating that we should use Redis cache service as described above.  We should actually use the Azure Redis cache service for any cache implementation. I used it just to demonstrate what we can achieve using startup tasks. It’s a little hack, which I am proud off 🙂

Happy coding, hacking!

Advertisements

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 )

Google photo

You are commenting using your Google 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 )

Connecting to %s