Cooking up deployments on stacked clouds

Strange title. I know. There are probably a few other ways those words could have been combined, but basically this post is about:

I’ve been using/playing with “cloudy” stuff – Cooper’s Sparkling Ale, Azure,  IBM SmartCloud, AWS – for a long time now, but never really got to look at what needs to happen behind the scenes. Then OpenStack Grizzly came out last year but a lack of time and my grossly under-powered laptop put paid to an effort to set it up. About a month ago I finally got around to sticking a Crucial mSATA SSD and 32GB RAM on my W520 . Bingo: I went from having time to brew and drink my favorite tea ( a Flowery Orange Pekoe from Kolukkumalai Tea Estate) in the time it took to boot up, to barely having time to put the kettle on. Meanwhile OpenStack had moved to Havana, I had moved to the Rational Emerging Technologies team and there is now more motivation to dig into (no, “waft about in” is more appropriate) this cloudy stuff, particularly with UrbanCode playing nicely with the cloud (see Darrell’s posts on this).

The best description of OpenStack I’ve found is here, with a more complex one here.

I first tried Devstack and gave up after a number of attempts when kept restarting my RHEL VM. I later figured out it was due to messagebus restarting in, but by then I’d moved onto Packstack

PackStack I found to be much more user friendly and “tweakable” and after some frustration with a dodgy internet connection, had my own OpenStack setup going with just a Cirros instance running on it.

Maybe an admin’s life in the cloud isn’t meant to be simple: the next challenge was getting Neutron to play nice with my network setup. I could get to the instances from the OpenStack server but not from anywhere else. When in doubt ask Davyd Norris: I’ve known and worked with Davyd since the old Rational days and he came up with the answer for me in a flash.

Now that I was happy with OpenStack, I was able to download a pre-built Ubuntu cloud image , prep it using guestfish (change password, copy-in UrbanCode script package and prerequisites etc) and make it available with Glance.

Next up I started looking at how I could achieve the following with UrbanCode Deploy as the primary interface:

  • Stand up a simple (single server) OpenStack stack.
  • Inject (install) a UCD agent into the new server.
  • Cook a Chef recipe on the new server and deploy an application on the new server.

1. Stand up a simple (single server) OpenStack stack

Using the servers_in_existing_neutron_net.yaml template, the UCD process to create the stack looks like this:


Behind the scenes I’ve created a UCD Component called “infrastructure” with this “Create Stack” process defined as an “Operational (With Version)” process, which is run on the OpenStack server. The component holds the HOT template and the file containing parameter values used by the template. Both these files are downloaded by the “Download Artifacts” step and used in the “Create Stack” step which runs the following Heat command:

heat --os-username ${p:environment/os-username} --os-password ${p:environment/os-password} --os-tenant-name ${p:environment/os-tenant-name} --os-auth-url ${p:environment/os-auth-url} stack-create ${p:environment/stackname} --template-file=${p:environment/template-file} -e ${p:environment/parameterfile}

Assuming the template is valid, stack-create returns in a few seconds if it succeeds with a resource status of CREATE_IN_PROGRESS. The next ‘Wait a while” step runs a Groovy sleep (thanks Ali) command to give the stack time to be created.

The “Show Stack” step runs “heat show-stack” and uses a post-processing script to extract the public IP address for the server from the output (the value of the server1_public_ip output in the YAML template). In the next step this value is added to an environment property (server_ip) which is used later.

Though the stack objects – servers, ports etc. –  are created pretty quickly it takes much longer for the server to actually fire up and be ready for use. So the final step uses “Check Connectivity”  to make sure the instance is up.

Here’s what the stack and network look like in Horizon.


2. Inject (install) an UCD agent into the new server

There are two methods I considered when figuring out how to put the UCD agent on the new server in the stack. One way is to use user_data in the HOT template such that agent is installed when the OpenStack instance boots. The mods to the HOT template would look something like this:

   type: string
   description: UCD Agent name
   type: string
   description: Hostname of UCD server
   type: string
   description: UCD server Port for agent communications
   default: 7918

    type: OS::Nova::Server
      name: { get_param: server_name }
      image: { get_param: image }
      flavor: { get_param: flavor }
      key_name: { get_param: key_name }
        - port: { get_resource: server1_port }
           template: |
              echo "Installing UCD agent..."
              export UCD_Agent_Name=%UCD_Agent_Name%
              export UCD_Hostname=%UCD_Hostname%
              export UCD_Port=%UCD_Port%
              cd /opt/ibm-ucd-agent-script-package
              chmod +x
              %UCD_Agent_Name%: { get_param: UCD_Agent_Name }
              %UCD_Hostname%: { get_param: UCD_Hostname }
              %UCD_Port%: { get_param: UCD_Port }

This assumes the UCD Agent script package is already in the OpenStack image used to create the instance. (Or it could be downloaded by the user_data script).

The second method, the one I use, is with a UCD process “Install Agent and create resources” that looks like this:


The first step installs the agent, taking the IP address from the environment property previously created by the “Create Stack” process. Then an Agent Resource is created, added to an application environment and the necessary Component Resources added. The resources end up looking like so:


The environment for the application ends up looking like this:

environmentI find that using UCD to drive this is much simpler (than using user_data), and I feel much more in control of what happens, particularly with a detailed view into the execution of each step.


3. Cook a Chef recipe on the new server and deploy an application on the new server

An application deployment process could look like this:


Once the stack is ready,  the Chef bits are executed and then the actual application is deployed. Here are the corresponding Component processes.


This is “stock” UCD stuff using the Chef plug-in, with the necessary cookbooks etc downloaded from in the previously mentioned “infrastructure” component.

So I now have a nice set of UCD processes that I can easily reuse. All I need to do to create a new stack with the same HOT file is modify the YAML parameters file and change the name of the stack in the environment property. If I want a modified or different HOT file, I simply change or add it to my SCM system, import them as new versions of the “infrastructure” component, change the environment properties and execute the processes as required.

In terms of time it took to get this all working, by far the biggest chunk went into getting the OpenStack setup done and the image prepared. Proportionally the UCD parts took literally a tiny fraction of the time. I now know way more about Heat, Neutron, Glance, Cinder and prepping images than I probably need to:-) I do need to dig more into cloud-init though as I had problems getting it to play nice on Fedora.

Interesting also is the plethora of names in this space: Nova, Neutron, Cinder, Swift, Glance, Ceilometer, Heat, Keystone,  guestfish, Chef, cookbooks, recipes. The Chef ones didn’t “gel” with me for some reason. My two favourites: Heat (“it makes the Cloud rise“) and “Precise Pangolin“.

Leave a Reply

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

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