irving cordova


What is Eucalyptus?

  • An Amazon Web Services compatible private cloud
  • That implements Compute, Storage and Network virtualization & others
retrieved from:

AWS Compatible?

  • Amazon API moves fast
  • Eucalyptus is always a bit behind
  • Private clouds even more so...

Running on Eucalyptus

a sample application

many moving parts

  • an application made of many different components
  • with complex configuration options
  • running in the cloud
retrieved from:

must run in multiple clouds

  • application must run in different clouds for different teams
  • each team wants multiple environments for testing  
retrieved from:

We need automation!


  • Configuration management tool
  • Written in Ruby
  • With a Ruby DSL
  • And some inspiration from Puppet

Why Chef?

  • Ruby DSL was more powerful than some other alternatives
  • Order matters
  • Idempotent
  • Thin server


we were already familiar with it

bash "compile_redis_source" do
  cwd Chef::Config[:file_cache_path]
  code <<-EOH
    tar zxf redis.tar.gz
    cd antirez-redis-55479a7
    make && make install
  creates "/usr/local/bin/redis-server"

service "redis" do
  provider Chef::Provider::Service::Upstart
  subscribes :restart, resources(:bash => "compile_redis_source")
  supports :restart => true, :start => true, :stop => true

template "redis.conf" do
  path "#{node[:redis][:dir]}/redis.conf"
  source "redis.conf.erb"
  owner "root"
  group "root"
  mode "0644"
  notifies :restart, resources(:service => "redis")
a sample chef recipe

What about all the moving parts?

we need orchestration!

the codification of a complete process

image and quote from:


An expressive toolset for constructing scalable, resilient architectures

  • Basically a Chef extension
  • Built by Infochimps
  • Allows to describe architecture in a DSL similar to Chef's recipes
  • EC2 Compatible
infochimps logo

Time to code


  • Ironfan implementation is successful
  • Application is deployed correctly
  • Runs in multiple environments with different configurations

But not everything is perfect...

  • Team must maintain a Chef server (thin server)
  • A different Chef server in each cloud
  • Recipes blow up with deep Ruby stack traces

Let's share with other teams!

image from:

my ruby version is not compatible!

what is rvm?

why is my modification to the recipe failing?

the Chef server died!

i think i messed up my ironfan config!

so i must push to chef server my modification?

i didn't do anything but my app reconfigured itself!

are there any other solutions out there?

simple to install

my ruby version is not compatible!

what is rvm?

i think i messed up my ironfan config!

server and agent less

the Chef server died!

so i must push to chef server my modification?

i didn't do anything but my app reconfigured itself!

how to make Ansible play nice with Eucalyptus?

step 1: 

can Ansible create servers in an Eucalyptus based clouds?

image from wikipedia
# file: create_server.yml
- hosts: local
  connection: local
  gather_facts: False

  - name: Provision server
    local_action: ec2
      ec2_url={{lookup('env', 'EC2_URL')}}
      aws_access_key={{ lookup('env', 'AWS_ACCESS_KEY_ID') }}
      aws_secret_key={{ lookup('env', 'AWS_SECRET_ACCESS_KEY') }}
      keypair={{lookup('env', 'keypair')}}
      image={{ lookup('env', 'image_centos') }}
      zone={{ lookup('env', 'regions') }}
an ansible task to create a server in eucalyptus

Creating a server:

  • Ansible uses boto on the backend, which is compatible with Eucalyptus
  • Only modification needed is to pass the endpoint for the Eucalyptus API
  • Instance tags are used to assign meaningful names to the server
image from wikipedia

step 2: 

can Ansible access the servers it just created?

image from
#!/usr/bin/env python

EC2 external inventory script

Generates inventory that Ansible can understand by making API request to
AWS EC2 using the Boto library.

NOTE: This script assumes Ansible is being executed where the environment
variables needed for Boto have already been set:
    export AWS_ACCESS_KEY_ID='AK123'
    export AWS_SECRET_ACCESS_KEY='abc123'

This script also assumes there is an ec2.ini file alongside it.  To specify a
different path to ec2.ini, define the EC2_INI_PATH environment variable:

    export EC2_INI_PATH=/path/to/my_ec2.ini

If you're using eucalyptus you need to set the above variables and
you need to define:

    export EC2_URL=http://hostname_of_your_cc:port/services/Eucalyptus

For more details, see:
the ec2 dynamic inventory from ansible

The dynamic EC2 inventory

  • Exporting the EC2_URL variable is sufficient to make the EC2 inventory script connect to Eucalyptus
$ export EC2_URL=
$ ansible -i -u ubuntu us-east-1d -m ping
  • The EC2 inventory groups the servers based on the tags they have
image from:

step 3: 

can Ansible support multiple instances of the app in the same cloud?

# filter out the instances that don't have a cluster tag
cluster = os.environ.get('CLUSTER')
if cluster != None:
  if 'cluster' in instance.tags and instance.tags['cluster'] != cluster:
  if not 'cluster' in instance.tags:
modifying ec2 inventory to only return servers with the correct CLUSTER tag

step 4: 

can Ansible assign different roles to each server?

image from:
  "ec2": [
  "i-942C484F": [
  "local": [
  "tag_role_sample": [
 "type_t1_micro": [
# file: sample_role.yml

- hosts: 'tag_role_sample'
    - sample
tags returned by EC2 inventory
translating tag to roles

step 5: 

what about overriding configuration on a per cluster basis?

image from:
# file: hosts/group_vars/tag_cluster_mycluster
# Properties to override go here

msg: "Overriden!"
overriding variables per cluster

putting it all together

| |____ansible-eucalyptus
| |____sample_cloud.ini
| |
| |____group_vars
| | |____tag_cluster_mycluster
| |____sample.key
| |____create_server.yml
| |____sample_role.yml
| |____roles
| | |____sample
| | | |____defaults
| | | | |____main.yml
| | | |____tasks
| | | | |____main.yml
final tree with all files in place

what is missing?

  • Better key management
  • Putting tags on the nodes to describe a cluster is cumbersome