General Information
Ansible is a tool for performing remote tasks on systems. (either ad-hoc or via “playbooks”)
You will need to use ansible as a user that has ssh keys setup on systems so you are not prompted for passwords during parallel command operations.
If you already have Ansible installed/configured, playbook downloads can be found here.
Checklist
Ansible comes in many distributions repos already.
CentOS 7
yum install ansible
Main Ansible config file
It is highly recommended to put Ansible playbooks, roles, and inventory into version control. (Example: git or svn)
One suggested directory structure/workflow is:
Model content tree under /ansible/ after Ansible's best practices alternative structure.
Inventory setup is the most important configure task.
In order for Ansible to send commands to systems, they must be listed in inventory.
Suggested directory structure (after Ansible's best practices alternative structure)
You will not want to introduce a manual inventory process.
Suggested workflow for auto generating your inventory files:
Examples of Ansible commands.
Note: All host-patterns check the inventory files for matches ONLY. If a system is not in the inventory file(s), Ansible can't send a command to it.
General Ansible command syntax
ansible <host-pattern> [-m module-name] [-a arguments] [options]
Listing hosts matched by the given pattern and do nothing else.
List hosts in the webservers_nginx group from dev inventory
ansible webservers_nginx -i /ansible/inventories/development/hosts --list-hosts
List all hosts from dev inventory
ansible all -i /ansible/inventories/development/hosts --list-hosts
List all hosts in the “webservers_nginx” group (from any inventory)
ansible webservers_nginx --list-hosts
List all hosts matching “web*” pattern (from any inventory)
ansible "web*" --list-hosts
The module 'ping' is not an ICMP echo command; it tests a remote login (ssh) to the system and verifies a working remote python environment.
Test connection to webservers_nginx in dev inventory only
ansible webservers_nginx -i /ansible/inventories/development/hosts -m ping
Test connection to all systems in dev inventory
ansible all -i /ansible/inventories/development/hosts -m ping
Test connection to all webservers_nginx (from any inventory)
ansible webservers_nginx -m ping
Test connection to all systems in the “webservers_nginx” group (from any inventory)
ansible webservers_nginx -m ping
Test connection to systems matching a pattern (from any inventory)
ansible "web*" -m ping
Test connection to all systems (from any inventory)
ansible all -m ping
Ad-hoc commands are for one off commands that are not saved in a playbook.
If no module is specified, the “command” module is used.
Check uptime of the group 'webservers_nginx' from dev only
ansible webservers_nginx -i /ansible/inventories/development/hosts -a 'uptime'
Check uptime of all systems in dev
ansible all -i /ansible/inventories/development/hosts -a 'uptime'
Check uptime of the group 'webservers_nginx' (from any inventory)
ansible webservers_nginx -a 'uptime'
Check the last 10 lines in /var/log/messages (using sudo)
ansible "web*" -a 'tail /var/log/messages' -b
Equivalent command as the above
ansible "web*" -a 'sudo tail /var/log/messages'
Piping example; the shell module must be specified
ansible "web*" -m shell -a 'cat /var/log/messages | grep -i error' -b
Transferring files over scp using Ansible to multiple servers at once.
Copy a local file (src=) to all systems in the 'webservers_nginx' group (dest=)
ansible webservers_nginx -m copy -a "src=/etc/yum.conf dest=/tmp/yum.conf"
Set a file's ownership and permissions
ansible webservers_nginx -m file -a "dest=/tmp/yum.conf mode=750 owner=root group=root"
Remove a file
ansible webservers_nginx -m file -a "dest=/tmp/yum.conf state=absent"
Managing packages with Ansible.
Ensure a package is installed, do not update the package if it is installed
ansible my_group -m yum -a "name=dstat state=present"
Ensure package is the latest version (update if not)
ansible my_group -m yum -a "name=dstat state=latest"
Ensure package is not installed (remove if it is)
ansible my_group -m yum -a "name=dstat state=absent"
Managing system services with Ansible.
Compatible with SysV and Systemd.
Ensure httpd is started (start if not)
ansible my_group -m service -a "name=httpd state=started"
Restart a service
ansible my_group -m service -a "name=httpd state=restarted"
Ensure a service is stopped
ansible my_group -m service -a "name=httpd state=stopped"
“Playbooks are Ansible’s configuration, deployment, and orchestration language. They can describe a policy you want your remote systems to enforce, or a set of steps in a general IT process.”
More Details: http://docs.ansible.com/ansible/playbooks.html
Playbooks should be repo controlled.
Following the examples on this page:
Playbooks map ansible groups to roles
# File: webservers_nginx.yml # Description: Nginx Webservers # Last Updated: 2018-04-08 # Recent Changes:-Initial release # hosts: group_name or 'all' - hosts: webservers_nginx # roles: located in ../roles/ roles: # role: role to assign to hosts, tags: tag(s) to give entire role - { role: webservers-nginx, tags: webservers-nginx } # Gather host facts for this playbook gather_facts: yes
Gather a subset of facts
If you do need to gather facts, consider gathering a subset of facts instead of everything in order to keep the fact collection fast.
# Gather host facts for this playbook gather_facts: yes # Gather only ansible_distribution info (OS attributes) gather_subset: - '!all' - '!min' - 'distribution'
"ansible_distribution": "CentOS", "ansible_distribution_file_parsed": true, "ansible_distribution_file_path": "/etc/redhat-release", "ansible_distribution_file_variety": "RedHat", "ansible_distribution_major_version": "7", "ansible_distribution_release": "Core", "ansible_distribution_version": "7.5.1804", "ansible_os_family": "RedHat",
ansible -m setup -a 'gather_subset=!all,!min,distribution' localhost
Available Fact Subsets:
See the Roles section for what happens next.
Roles contain all of the tasks that will be run when a playbook is executed against it.
Roles should be repo controlled. Top level directory example is:
An example role called “webservers-nginx” is located:
The contents of a role directory are:
How to create a new playbook and role.
External References
cd ${HOME}/repos/ansible/
#git git pull #svn svn update
cd roles/ cp -R template-role/ my-new-role
cd ${HOME}/repos/ansible/playbooks/
cp TEMPLATE_PLAYBOOK.yml my_new_playbook.yml
# File: TEMPLATE_PLAYBOOK.yml # Description: PLAYBOOK DESCRIPTION HERE # Last Updated: 2018-03-15 # Recent Changes:-Initial release # hosts: group_name or 'all' - hosts: - group_name_here # roles: located in ../roles/ roles: # role: role to assign to hosts, tags: tag(s) to give entire role - { role: role-name, tags: tag-name } # Do not gather host facts for this playbook (comment out/remove if you need facts) gather_facts: no
- hosts: my_ansible_group roles: - { role: my-new-role, tags: my-new-role }
Test your playbook before committing it to a repo.
#bash = ~/.bashrc #zsh = ~/.zshrc # Enable Ansible test environment ansible_local_enable(){ export ANSIBLE_INVENTORY="${HOME}/repos/ansible/inventories" export ANSIBLE_ROLES_PATH="${HOME}/repos/ansible/roles" echo -e "Ansible environmental variables set to:" env | grep ANSIBLE } # Disable Ansible test environment ansible_local_disable(){ unset ANSIBLE_INVENTORY unset ANSIBLE_ROLES_PATH echo -e "Ansible environmental variables have been unset. There should be no variable results after this line." env | grep ANSIBLE }
#bash source ~/.bashrc #zsh source ~/.zshrc
ansible_local_enable
ansible-playbook --syntax-check ${HOME}/repos/ansible/playbooks/my_new_playbook.yml
ansible-playbook -b -i ${HOME}/repos/ansible/inventories/development/dev ${HOME}/repos/ansible/playbooks/my_new_playbook.yml --list-tasks
ansible-playbook -b -i ${HOME}/repos/ansible/inventories/development/dev ${HOME}/repos/ansible/playbooks/my_new_playbook.yml --limit mytestsystem
ansible_local_disable
Different methods to run playbooks.
WARNING: If you do NOT specify an inventory file with “-i PATH”, the playbook will run against ALL HOSTS in the group, which is probably not what you want.
NOTE: If you need to use group_vars per inventory type (dev/test/prod), the full path to the inventory file needs to be used. (Example: /ansible/inventories/development/hosts )
After creating a playbook, it is useful to check the syntax before running it to catch obvious errors.
Run a syntax check (will NOT execute the playbook)
ansible-playbook --syntax-check /ansible/playbooks/my_playbook.yml
Playbook commands can get rather long, some useful aliases to shorten them.
Put in your ~/.bashrc or ~/.zshrc file
# Ansible aliases alias apd='ansible-playbook -b -i /ansible/inventories/development/hosts' alias apt='ansible-playbook -b -i /ansible/inventories/systest/hosts' alias app='ansible-playbook -b -i /ansible/inventories/production/hosts'
Additionally, create a symlink to playbooks
ln -s /ansible/playbooks /playbooks
Now, your playbook commands can look like this
# Dev inventory apd /playbooks/myplaybook.yml # Test inventory apt /playbooks/myplaybook.yml # Prod inventory app /playbooks/myplaybook.yml
Preparation/sanity check commands to do before running a playbook.
List what hosts the playbook will run against (from dev inventory)
ansible-playbook -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --list-hosts
List what tasks the playbook will execute (from dev inventory)
ansible-playbook -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --list-tasks
Commands to actually run a playbook. You SHOULD do the list commands first to make sure what you are about to run is expected.
Run playbook (dev env; all in group) against all system groups defined in playbook from dev inventory using sudo for privilege escalation
ansible-playbook -b -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml
Run playbook (dev env; all in group; only configure) against all groups defined in playbook from dev inventory using sudo for privilege escalation, only execute actions with the matched tags “configure”
ansible-playbook -b -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --tags configure
Run playbook (dev env; range of systems) against all groups defined in playbook from dev inventory using sudo for privilege escalation, further limit to hosts web01-05“
ansible-playbook -b -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --limit "$(echo web{01..05})"
Run playbook (dev env; one system) against all groups defined in playbook from dev inventory, limit to a single hostname (MYHOSTNAME)
ansible-playbook -i /ansible/inventories/development/hosts /ansible/playbooks/my_playbook.yml --limit MYHOSTNAME