⚙️ Ansible
The Basics

Updated at 2017-03-22 01:46

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.

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
    http_port: 80
    max_clients: 200
  - 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
    - restart apache
  - name: ensure apache is running (and enable it at boot)
    service: name=httpd state=started enabled=yes
    - name: restart apache
      service: name=httpd state=restarted

- hosts: database
  remote_user: root
  - 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              # 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
  webserver/            # same as "common"
  database/             # same as "common"
  monitoring/           # same as "common"
  common/               # this hierarchy represents the common "role"
    templates/      # <-- templates for use with the `template` module
      bar.txt       # <-- files for use with the `copy` module        # <-- script files for use with the `script` module
      main.yml      # <-- variables associated with this role
      main.yml      # <-- default lower priority variables for this role
      main.yml      # <-- role dependencies
    library/        # <-- role-specific custom modules