Ansible is a free software platform for configuring and managing computers. It combines multi-node software deployment, ad hoc task execution, and configuration management. It manages nodes over SSH or PowerShell and requires Python (2.4 or later) to be installed on them. The system uses YAML to express reusable descriptions of systems.
Installation
Install from PPA
sudo apt-get install software-properties-common
sudo apt-add-repository ppa:ansible/ansible
sudo apt-get update
sudo apt-get install ansible
Install with pip
sudo pip install ansible
Configuration
Add localhost to hosts file
echo "localhost ansible_connection=local" > ~/ansible_hosts
export ANSIBLE_INVENTORY=~/ansible_hosts
Setup SSH-agent
ssh-agent bash
ssh-add ~/.ssh/id_rsa
Inventory
[webservers]
www[01:50].example.com
[databases]
db-[a:f].example.com
[targets]
localhost ansible_connection=local
other1.example.com ansible_connection=ssh ansible_ssh_user=mpdehaan
other2.example.com ansible_connection=ssh ansible_ssh_user=mdehaan
Ad-Hoc Commands
Patterns
ansible <pattern_goes_here> -m <module_name> -a <arguments>
Ping hosts
# ping
ansible all -m ping
# ask ssh password
ansible all -m ping --ask-pass
# as bruce
$ ansible all -m ping -u bruce
# as bruce, sudoing to root
$ ansible all -m ping -u bruce --sudo
# as bruce, sudoing to batman
$ ansible all -m ping -u bruce --sudo --sudo-user batman
Run command
ansible localhost -a "/bin/echo hello"
ansible localhost -a "uname -a"
ansible localhost -m shell -a 'echo $TERM'
Run command in parallel
ansible atlanta -a "/sbin/reboot" -f 10
Run as other user with sudo
ansible atlanta -a "/usr/bin/foo" -u username --sudo [--ask-sudo-pass]
File
# create file and set permissions
ansible webservers -m file -a "dest=/srv/foo/b.txt mode=600 owner=mdehaan group=mdehaan"
# create directory
ansible webservers -m file -a "dest=/path/to/c mode=755 owner=mdehaan group=mdehaan state=directory"
# delete file
ansible webservers -m file -a "dest=/path/to/c state=absent"
Copy
# copy file
ansible atlanta -m copy -a "src=/etc/hosts dest=/tmp/hosts"
ansible atlanta -m copy -a "src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644 backup=yes"
ansible atlanta -m copy -a "src=/mine/sudoers dest=/etc/sudoers validate='visudo -cf %s'"
Fetch
# fetch file from remote node
ansible atlanta -m fetch -a "src=/tmp/somefile dest=/tmp/fetched"
ansible atlanta -m fetch -a "src=/tmp/somefile dest=/tmp/prefix-{{ ansible_hostname }} flat=yes"
Service
ansible webservers -m service -a "name=httpd state=started"
ansible webservers -m service -a "name=httpd state=stopped"
ansible webservers -m service -a "name=httpd state=restarted"
ansible webservers -m service -a "name=httpd enabled=yes"
APT
# update repositories cache and install package
ansible local -m apt -a "name=foo update_cache=yes"
# install latest version of package
ansible local -m apt -a "name=foo state=latest"
# install version '1.00' of package "foo"
ansible local -m apt -a "name=foo=1.00 state=present"
# remove package
ansible local -m apt -a "name=foo state=absent"
# equivalent of "apt-get update"
ansible local -m apt -a "update_cache=yes"
# install local deb file
ansible local -m apt -a "deb=/tmp/mypackage.deb"
APT repository
ansible local -m apt_repository -a "repo='deb http://archive.canonical.com/ubuntu hardy partner' state=present"
ansible local -m apt_repository -a "repo='deb http://archive.canonical.com/ubuntu hardy partner' state=absent"
ansible local -m apt_repository -a "repo='ppa:nginx/stable'"
Shell
# execute the command in remote shell
ansible webserver -m shell -a "somescript.sh >> somelog.txt"
# change the working directory to somedir/ before executing the command.
ansible webserver -m shell -a "somescript.sh >> somelog.txt chdir=somedir/"
INI
ansible webserver -m ini_file -a "dest=/etc/conf section=drinks option=fav value=lemonade mode=0600 backup=yes"
Sysctl
# set vm.swappiness to 5 in /etc/sysctl.conf
ansible webserver -m sysctl 'name=vm.swappiness value=5 state=present'
# remove kernel.panic entry from /etc/sysctl.conf
ansible webserver -m sysctl 'name=kernel.panic state=absent sysctl_file=/etc/sysctl.conf'
# set kernel.panic to 3 in /tmp/test_sysctl.conf
ansible webserver -m sysctl 'name=kernel.panic value=3 sysctl_file=/tmp/test_sysctl.conf reload=no'
# set ip forwarding on in /proc and do not reload the sysctl file
ansible webserver -m sysctl 'name="net.ipv4.ip_forward" value=1 sysctl_set=yes'
# set ip forwarding on in /proc and in the sysctl file and reload if necessary
ansible webserver -m sysctl 'name="net.ipv4.ip_forward" value=1 sysctl_set=yes state=present reload=yes'
Script - Runs a local script on a remote node after transferring it
ansible webserver -m script -a "/some/local/script.sh --some-arguments 1234"
Git
ansible webservers -m git -a "repo=git://foo.example.org/repo.git dest=/srv/myapp version=HEAD"
Assemble - Assembles a configuration file from fragments
ansible webserver -m assemble -a "src=/etc/someapp/fragments dest=/etc/someapp/someapp.conf"
# when a delimiter is specified, it will be inserted in between each fragment
ansible webserver -m assemble -a "src=/etc/someapp/fragments dest=/etc/someapp/someapp.conf delimiter='### START FRAGMENT ###'"
LineInFile
ansible webserver -m lineinfile -a 'dest=/etc/sudoers state=absent regexp="^%wheel"'
ansible webserver -m lineinfile -a 'dest=/etc/httpd/conf/httpd.conf regexp="^Listen " insertafter="^#Listen " line="Listen 8080"'
ansible webserver -m lineinfile -a 'dest=/etc/services regexp="^# port for http" insertbefore="^www.*80/tcp" line="# port for http by default"'
ansible webserver -m lineinfile -a 'dest=/tmp/testfile line="192.168.1.99 foo.lab.net foo"'
Playbooks
Examples
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
---
- hosts: webservers
vars:
http_port: 80
max_clients: 200
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum:
pkg: httpd
state: latest
- name: write the apache config file
template:
src: /srv/httpd.j2
dest: /etc/httpd.conf
notify:
- restart apache
- name: ensure apache is running
service:
name: httpd
state: started
handlers:
- name: restart apache
service:
name: httpd
state: restarted
---
- hosts: webservers
remote_user: root
tasks:
- name: ensure apache is at the latest version
yum: pkg=httpd state=latest
- name: write the apache config file
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
- hosts: databases
remote_user: root
tasks:
- name: ensure postgresql is at the latest version
yum: name=postgresql state=latest
- name: ensure that postgresql is started
service: name=postgresql state=running