Why use Ansible?
Before Ansible I knew three ways of how to (remotely) manage a server:
- Using shell scripts and SSH.
- MCollective
- 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 heavyweight for my taste considering smaller ad-hoc installations.
That is where Ansible fits in perfectly: easy and fast to set up, and easy to scale if an installation grows.
In this post I will show how to set up Ansible and perform some tasks with it.
Preparing the Playground
Create two Vagrant boxes that have a fixed IP:
# -*- 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
endI am using my own base box here, which I called “centos_70”. 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.
ssh-keygen -t rsa
eval "$(ssh-agent -s)"
ssh-add /vagrant/id_rsaPut 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:
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 ansibleOn box “foo” edit the file /etc/ansible/hosts so it contains the IP address of box bar:
192.168.10.20A first Test
Now, if everything is correct, you can try the following test on foo:
ansible 192.168.10.20 -m pingThe result should be something like:
192.168.10.20 | success >> {
"changed": false,
"ping": "pong"
}A real-world Example (more or less…)
Let’s create a fictitious deployment process that consists of the following two steps:
- Copy the “deployment artifact” from the deployment server
footo the deployment targetbar. - Execute a script on the deployment target
bar.
My little deployment playbook deploy.yml looks like:
- 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}}"The only thing that the script hello_world.sh does is:
#!/usr/bin/bash
printf "Hello World!\n"The file hello.txt is just empty.
Let’s trigger the deployment on foo with:
ansible-playbook deploy.ymlThe resulting output should be:
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=0Nice, very nice!
What’s next?
For those who already have a bunch of scripts and are logging into server after server, using Ansible is a revelation. Integrating those scripts with Ansible’s shell or command modules is a breeze.
After playing around for a while I realized there is one important page I visit all the time: the module index. This page provides a nice general intro about Ansible modules.
Done for today!