Ansible
+
Eucalyptus
irving cordova
What is Eucalyptus?
- An Amazon Web Services compatible private cloud
- That implements Compute, Storage and Network virtualization & others
retrieved from: https://www.eucalyptus.com/eucalyptus-cloud/iaas
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: http://arnoldit.com/wordpress/2012/03/01/datasift-architecture/
must run in multiple clouds
- application must run in different clouds for different teams
- each team wants multiple environments for testing
retrieved from: http://www.dbta.com/Editorial/News-Flashes/IBM-Announces-Cloud-of-Clouds-Approach-to-Data-Migration-and-Storage-94054.aspx
We need automation!
Chef
- 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
EOH
creates "/usr/local/bin/redis-server"
end
service "redis" do
provider Chef::Provider::Service::Upstart
subscribes :restart, resources(:bash => "compile_redis_source")
supports :restart => true, :start => true, :stop => true
end
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")
end
a sample chef recipe
What about all the moving parts?
we need orchestration!
the codification of a complete process
image and quote from: https://devcentral.f5.com/articles/wils-automation-versus-orchestration
Ironfan
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: http://availagility.co.uk/2012/04/21/linking-flow-value-and-capability/multiple-teams-jpg/
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
tasks:
- 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')}}
instance_type=t1.micro
image={{ lookup('env', 'image_centos') }}
zone={{ lookup('env', 'regions') }}
instance_tags='{"Name":"sample_server"}'
wait=true
count=1
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 http://aws.amazon.com/ec2/
#!/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: http://docs.pythonboto.org/en/latest/boto_config_tut.html
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=http://127.0.0.1:8773/services/Eucalyptus
$ ansible -i ec2.py -u ubuntu us-east-1d -m ping
- The EC2 inventory groups the servers based on the tags they have
image from: http://www.clker.com/clipart-server-farm.html
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:
return
if not 'cluster' in instance.tags:
return
modifying ec2 inventory to only return servers with the correct CLUSTER tag
step 4:
can Ansible assign different roles to each server?
image from: http://www.nytimes.com/2008/12/04/fashion/04roles.html
{
"ec2": [
"euca-127-0-0-1.eucalyptus.cloud.net"
],
"i-942C484F": [
"euca-127-0-0-1.eucalyptus.cloud.net"
],
"local": [
"localhost"
],
"tag_role_sample": [
"euca-127-0-0-1.eucalyptus.cloud.net"
],
"type_t1_micro": [
"euca-127-0-0-1.eucalyptus.cloud.net"
]
}
# file: sample_role.yml
- hosts: 'tag_role_sample'
roles:
- sample
tags returned by EC2 inventory
translating tag to roles
step 5:
what about overriding configuration on a per cluster basis?
image from: https://www.arbfile.org/webapp/pgStatic/content/EBulletinArbitrators/2013/pgEBulletinArbs_May2013.jsp
# file: hosts/group_vars/tag_cluster_mycluster
# Properties to override go here
msg: "Overriden!"
overriding variables per cluster
putting it all together
____ansible.cfg
|____bin
| |____ansible-eucalyptus
|____clouds
| |____sample_cloud.ini
|____hosts
| |____ec2.py
| |____group_vars
| | |____tag_cluster_mycluster
|____keys
| |____sample.key
|____tasks
| |____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
questions?
irving@irvingc.com
ansible + eucalyptus
By Irving Cordova
ansible + eucalyptus
- 2,120