Ansible - The Basics
Ansible is configuration management tool like Chef or Puppet. To be more specific, Ansible is a Python 2 only command-line tool.
Ansible is agent-less and uses push-approach so nothing needs to be installed on the managed machines. Most configuration management tools use pull-approach where managed server has software installed to keep itself updated. Ansible just creates SSH connections to managed servers and applies changes through this connection.
Ansible has reusable modules for executing common tasks. Main focus of modules is trying to ensure idempotent execution meaning that if you run the same thing twice you end up in the same final state.
- Modules are like "create EC2 instance", "manage GitHub webhooks", etc.
- Ansible Module Index
- Developing Modules
Installing Ansible:
# Notice that Ansible officially only supports Python 2
pip install ansible
ansible --version
You work with Ansible in two ways: ad-hoc commands and playbooks. Ad-hoc commands are meant to be "fire-and-forget"-type of tasks that you don't want to manage in greater detail. Playbooks are YAML files with collections of modules and predefined tasks to apply.
ansible # ad-hoc commands
ansible-playbook # playbooks
# Run /sbin/reboot on all machines in invetory "hosts"
ansible -i hosts -a "/sbin/reboot"
# Use module "shell" to execute "echo $TERM" on machines in "hosts" inventory
ansible -i hosts -m shell -a 'echo $TERM'
# Note that if you would use double quotes, TERM would be be evaluated on
# the machine you start the command.
ansible -i hosts -m shell -a "echo $TERM"
# Copy a file
ansible -i hosts -m copy -a "src=/etc/hosts dest=/tmp/hosts"
You run playbooks with ansible-playbook
.
ansible-playbook deploy.yml
# To just check for syntax errors
ansible-playbook deploy.yml --syntax-check
# To check which hosts would be applied
ansible-playbook deploy.yml --list-hosts
Example deploy.yml
playbook with two "plays".
---
- hosts: webserver
remote_user: root
vars:
http_port: 80
max_clients: 200
tasks:
- name: ensure apache is at the latest version
yum: name=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: database
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=started
Example how to organize Ansible files. It's good to differentiate staging and production with AWS tags e.g. environment:production
.
ansible.cfg # configuration file
inventory.py # dynamic inventory script, good with cloud providers
site.yml # master playbook that includes next two playbooks
webservers.yml # playbook for webserver tier, maps hosts to roles
dbservers.yml # playbook for dbserver tier, maps hosts to roles
library/ # project-wide custom modules
filter_plugins/ # custom filter plugins
roles/
webserver/ # same as "common"
database/ # same as "common"
monitoring/ # same as "common"
common/ # this hierarchy represents the common "role"
tasks/
main.yml
handlers/
main.yml
templates/ # <-- templates for use with the `template` module
files/
bar.txt # <-- files for use with the `copy` module
foo.sh # <-- script files for use with the `script` module
vars/
main.yml # <-- variables associated with this role
defaults/
main.yml # <-- default lower priority variables for this role
meta/
main.yml # <-- role dependencies
library/ # <-- role-specific custom modules