Ansible is an open-source software for infrastructure management i.e. configuring and managing computers. Ansible is agent-less: a single controlling machine manages nodes over SSH connection; those nodes do not require additional software nor any background daemons. It has minimal software requirements i.e. Python 2.4 or later. It uses YAML as a description language which makes it self-documenting and easier to read than custom DSLs (additional layer of abstraction). In result, it is easier to use than similar, but older tools such as Puppet, Chef or Saltstack.
Install
You need Python 2.4 or later. The best way to install is through pip package manager.
pip install ansibleHands-on
Make a directory
mkdir foo && cd fooCreate an inventory file
# ~/foo/hosts
[local]
127.0.0.1Create a playbook
# ~/foo/playbook.yml
- hosts: local
user: root
tasks:
- name: install curl
apt: pkg=curl state=present
- name: write to a file
shell: echo hello > /tmp/fooRun the playbook (Debian/Ubuntu specific)
ansible-playbook -i hosts playbook.ymlConcepts
Playbooks are collections of steps, i.e. configuration policies to be applied to defined groups of hosts, written in YAML and executed in order they are written.
Playbooks are declarative and idempotent while shell scripts are imperative. It’s difficult to replay a shell script because it is very hard to write idempotent commands. Contrarily, Ansible only performs the tasks in the playbook that need to be performed: if the condition is already satisfied, there's nothing to do.
---
- hosts: localhost
connection: local
vars:
- foo: Hello
tasks:
- command: echo “{{foo}}”An inventory defines a list of hosts; they can be defined on a system level with /etc/ansible/hosts or with the environment variable ANSIBLE_HOSTS=<path-to-inventory>, or per invocation with -i <path-to-inventory> parameter.
An inventory file can define host groups using square brackets. If you declare a host in the inventory by hostname, it must be resolvable either in your /etc/hosts file, or by a DNS lookup. E.g.
[webservers]
192.168.100.1 set_hostname=foo # how to set per-host variables.
[dbservers]
dbserver-1Modules control system resources: services, files, commands e.g. apt/yum, file/copy, command/shell/script, service, ec2, etc.
---
- name: Install Python PIP & boto library
user: ubuntu
sudo: true
hosts: all
tasks:
- name: Install python-pip
apt: pkg=python-pip state=latest
- name: Install boto w/ PIP
pip: name=boto state=latestUsage
Task Mode
In task mode, an Ansible module command is executed on a target node. A module is specified with -m parameter along with its arguments specified with -a parameter.
ansible web -m copy -a “src=script.sh dest=/usr/bin/script owner=root group=root mode=0755”
ansible web -m service -a “name=nginx state=restarted”Groups can be combined
A:Bdesignates the union of groups A and BA:&Bdesignates the intersection of groups A and BA:!Bdesignates the difference, all from A without those in B
ansible -m ping web
ansible -m ping web:db
ansible -m ping web:&db
ansible -m ping web:!dbPlaybook Mode
In playbook mode, commands are executed according to specified playbook. When Ansible runs a playbook, it will execute the tasks in the order they appear in that playbook - the process is meant to be repeated without differences.
For better organisation, a playbook should be composed of smaller, reusable parts. Those parts can be combined into a playbook either using include statement or with roles.
An include statement specifies a file with plays to include into that playbook.
# site.yml
---
- name: Install Python PIP & boto library
user: ubuntu
sudo: true
hosts: all
tasks:
- include: install-python.yml# install-python.yml
- name: install python-pip
apt: pkg=python-pip state=latest
- name: install boot with PIP
pip: name=boto state=latestRoles are built around include statement (file references handling and opinionated structure) and provide the best way to organise playbooks. They encapsulate configuration/management steps related to a single thing. In general, a role consists of the following subdirectories, "files", “vars”, "handlers", "meta", "tasks" and "templates”.
# site.yml
---
- name: Install Redis
user: ubuntu
sudo: true
hosts: all
roles:
- redis# roles/redis/tasks/main.yml
---
- name: Add the Redis PPA
apt_repository: repo='ppa:rwky/redis' update_cache=yes
- name: Install Redis from PPA
apt: pkg=redis-server state=installed
- name: Start Redis
service: name=redis state=startedLoop-like abstraction
with_item allows to pass a list of elements into a module.
- name: install default packages
apt: pkg={{ item }} state=installed
with_items:
- curl
- vim
- htopPrivate key
A private key used to log in into nodes can be specified with —private-key parameter.
ansible-playbook acme.yml --private-key=/home/smith/.ssh/acme.priv