Getting started with Ansible
I've been using Puppet for a few years now. Generally it's a great tool for server automation, however like all software it has its share of rough edges.
One edge I've run up against recently is performance on low powered devices. For example running even trivial configuration on my Raspberry Pi takes a long time:
pi@raspberrypi:~ $ time sudo puppet apply -e "service {'sshd': ensure => running }"
Notice: Compiled catalog for raspberrypi.lan in environment production in 3.60 seconds
Notice: Finished catalog run in 0.62 seconds
real 0m38.155s
user 0m34.690s
sys 0m2.450s
With the above in mind I decided to have a look at using Ansible instead. Both because I hoped it would perform better, and because it's always interesting to learn about alternative tools.
Installing Ansible
Unlike Puppet, Ansible is agent-less. Therefore installation is just a case of
getting Ansible installed on a single control host. On CentOS
You can install the ansible
package from EPEL:
yum install ansible
The Ansible docs cover installation on other platforms. It's worth noting that Windows cannot currently be used as a control host, however Ansible can be used to manage Windows systems.
SSH setup
The most common connection method used by Ansible is SSH. Although password authentication can be used it's normally a good idea to setup SSH keys. This requires two steps:
- Generate a public/private SSH key pair using ssh-keygen.
- Copy the public key onto each target host using ssh-copy-id.
After everything is set up the control host should be able to connect to each target host without using a password:
[user@ansible-control ~]$ ssh [email protected] hostname
raspberrypi
Connecting with Ansible
Once SSH keys have been set up Ansible should be able to connect:
[user@ansible-control ~]$ ansible all -i '192.168.1.129,' -u pi -m ping
192.168.1.129 | SUCCESS => {
"changed": false,
"ping": "pong"
}
The command above uses the Ansible ping module to connect to the target host. Once connected the module confirms Ansible has everything it needs to run on the host; namely a suitable python environment.
Inventory
The ping example above can be shortened significantly by using an inventory
file. By default Ansible looks in /etc/ansible/hosts
for host information.
For example the following lines will create a pi group with a single host in
it:
[pi]
192.168.1.129 ansible_user=pi
After the new config has been added to the inventory file, the name of the host group can be used in place of the IP and user name:
[user@ansible-control ~]$ ansible pi -m ping
192.168.1.129 | SUCCESS => {
"changed": false,
"ping": "pong"
}
Root access
By default Ansible will run as the user it connected with:
[user@ansible-control ~]$ ansible pi -m command -a 'whoami'
192.168.1.129 | SUCCESS | rc=0 >>
pi
To become root you can use the --sudo
option:
[user@ansible-control ~]$ ansible pi --sudo -m command -a 'whoami'
192.168.1.129 | SUCCESS | rc=0 >>
root
This can also be set persistently in the inventory config using
ansible_become
:
[pi]
192.168.1.129 ansible_user=pi ansible_become=true
Note: the --sudo
and ansible_become
options will only work if sudo has
been configured on the target host.
Thoughts so far
I'm still very new to Ansible, but I'm quite impressed with what I've seen so far. Getting up and running was pretty straightforward and Ansible is faster than Puppet. Well at least for the slightly contrived example I had at the start of this post:
[user@ansible-control ~]$ time ansible pi -m service -a 'name=sshd state=running'
192.168.1.129 | SUCCESS => {
"changed": false,
"name": "sshd",
"state": "started"
}
real 0m2.769s
user 0m0.589s
sys 0m0.215s
From here I'm planning to have a go at writing a few Ansible playbooks to actually do something useful. This should give me a better idea of what Ansible is capable of, or at least make me a little less naive when it comes to Ansible.