Skip to main content

Server Orchestration with Ansible

·3 mins

Why use Ansible? #

Before Ansible I knew three ways of how to (remotely) manage a server:

  1. Using shell scripts and SSH.
  2. MCollective
  3. Using a configuration management tool like Puppet or Chef.

While using the first with many servers quickly can become chaotic, the second and third options are just too heavy weight for my taste considering smaller ad-hoc installations.

That is where Ansible fits in perfectly. Easy and fast to setup. Easy to scale in case an installation grows bigger.

In this post I will show how to set up Ansible and perform some tasks with it.

Preparing the Playground #

Create two Vagrantboxes that have a fixed IP:

{% highlight none %}

-- mode: ruby -- #

vi: set ft=ruby : #

VAGRANTFILE_API_VERSION = “2”

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| config.vm.box = “centos_70” config.vm.define “foo” do |foo| foo.vm.network “private_network”, ip: “192.168.10.10” end

config.vm.define “bar” do |bar| bar.vm.network “private_network”, ip: “192.168.10.20” end end {% endhighlight %}

I am using my own base box here, that I called “centos_7”. Feel free to roll your own. You can find a guide here.

Start both of them with vagrant up. You can access the Vagrant boxes individually with vagrant ssh foo and vagrant ssh bar respectively.

An SSH key-pair is needed, because all Ansible communication goes via SSH.

{% highlight none %} ssh-keygen -t rsa eval ‘ssh-agent -s’ ssh-add /vagrant/id_rsa {% endhighlight %}

Put the private key file into /home/vagrant/.ssh/id_rsa on foo , and on bar, copy and paste the public key into /home/vagrant/.ssh/authorized_keys.

Install and Configure Ansible #

Let’s deal with Ansible itself now.

Install it with:

{% highlight none %} cd /tmp wget https://dl.fedoraproject.org/pub/epel/7/x86_64/e/epel-release-7-5.noarch.rpm yum install epel-release-7-5.noarch.rpm yum -y install ansible {% endhighlight %}

On box “foo” edit the file /etc/ansible/hosts so it contains the IP-address of box bar.

{% highlight none %} 192.160.10.20 {% endhighlight %}

A first Test #

Now, if everything is correct, you could try the following test on foo.

{% highlight none %} ansible 192.168.10.20 -m ping {% endhighlight %}

The result should be something like:

{% highlight none %} 192.168.10.20 | success » { “changed”: false, “ping”: “pong” } {% endhighlight %}

A real-world Example (more or less …) #

Let’s create a fictitious deployment process that consists of the following two steps:

  1. Copy the “deployment artifact” from the deployment server foo to the deployment target bar
  2. Execute a script on the deployment target bar.

My little deployment playbook deploy.yml looks like:

{% highlight none %} {% raw %}

  • hosts: 192.168.10.20 tasks:
    • name: copies a file from a to b copy: src=/vagrant/hello.txt dest=/home/vagrant

    • name: executes a script command: /home/vagrant/hello_world.sh register: hello

    • debug: msg="{{hello.stdout}}" {% endraw %} {% endhighlight %}

The only thing that the script hello_world.sh does is

{% highlight none %} #!/usr/bin/bash printf “Hello World!\n” {% endhighlight %}

The file hello.txt is just empty.

Lets’s trigger the deployment on foo with

{% highlight none %} ansible-playbook deploy.yml {% endhighlight %}

The resulting output should be :

{% highlight none %} PLAY [192.168.10.20] **********************************************************

GATHERING FACTS *************************************************************** ok: [192.168.10.20]

TASK: [copies a file from a to b] ********************************************* ok: [192.168.10.20]

TASK: [executes a script] ***************************************************** changed: [192.168.10.20]

TASK: [debug msg="{{hello.stdout}}"] ****************************************** ok: [192.168.10.20] => { “msg”: “Hello World!” }

PLAY RECAP ******************************************************************** 192.168.10.20 : ok=4 changed=1 unreachable=0 failed=0 {% endhighlight %}

Nice, very nice!

What’s next? #

Now, for those who already have a bunch of scripts and that are logging into server after server, using Ansible is a revelation! Integrating those scripts with Ansibles shell or command modules is a breeze.

After playing around for a while I have realized there is one important page that I visit all the time, it is the module index. This page provides a nice general intro about Ansible modules.

Done for today!