Complete Guide to Ansible
Table of Contents
- What is Ansible?
- Key Concepts
- Installation
- Getting Started
- Inventory Management
- Playbooks
- Modules
- Variables and Facts
- Handlers
- Roles
- Best Practices
- Common Use Cases
- Troubleshooting
What is Ansible?
Ansible is an open-source automation platform that simplifies cloud provisioning, configuration management, application deployment, intra-service orchestration, and many other IT needs. It uses a simple, human-readable language (YAML) to describe automation jobs.
Key Features
- Agentless: No need to install agents on managed nodes
- Simple: Uses SSH for communication and YAML for configuration
- Powerful: Can manage complex multi-tier deployments
- Flexible: Works with existing tools and infrastructure
- Secure: Uses SSH and requires no additional ports or daemons
Key Concepts
Control Node
The machine where Ansible is installed and from which all tasks and playbooks are executed.
Managed Nodes
The network devices and servers you manage with Ansible. Also called "hosts."
Inventory
A list of managed nodes. An inventory file is also sometimes called a "hostfile."
Modules
Units of code Ansible executes. Each module has a particular use, from administering users to managing VLAN interfaces on network devices.
Tasks
Units of action in Ansible. You can execute a single task once with an ad-hoc command.
Playbooks
Ordered lists of tasks, saved so you can run those tasks in that order repeatedly.
Installation
Prerequisites
- Python 3.8 or newer
- SSH access to managed nodes
- Python on managed nodes
Installation Methods
Using pip (Recommended)
pip install ansible
Using package managers
Ubuntu/Debian:
sudo apt update
sudo apt install ansible
CentOS/RHEL/Fedora:
sudo dnf install ansible
# or
sudo yum install ansible
Verify Installation
ansible --version
Getting Started
Basic Command Structure
ansible <host-pattern> -m <module> -a <arguments>
Simple Ad-hoc Commands
# Check connectivity
ansible all -m ping
# Run shell commands
ansible all -m shell -a "uptime"
# Copy files
ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts"
# Install packages
ansible all -m apt -a "name=nginx state=present" --become
Inventory Management
Static Inventory
Basic INI Format (/etc/ansible/hosts):
[webservers]
web1.example.com
web2.example.com
[databases]
db1.example.com
db2.example.com
[production:children]
webservers
databases
YAML Format:
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
databases:
hosts:
db1.example.com:
db2.example.com:
production:
children:
webservers:
databases:
Host Variables
[webservers]
web1.example.com http_port=80 maxRequestsPerChild=808
web2.example.com http_port=303 maxRequestsPerChild=909
Group Variables
[webservers]
web1.example.com
web2.example.com
[webservers:vars]
ntp_server=ntp.atlanta.example.com
proxy=proxy.atlanta.example.com
Dynamic Inventory
Ansible can work with dynamic inventory sources like AWS EC2, Google Cloud, Azure, etc.
# Using AWS EC2 plugin
ansible-inventory -i inventory_aws_ec2.yml --list
Playbooks
Basic Playbook Structure
---
- name: Configure web servers
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: Install Apache
apt:
name: apache2
state: present
- name: Start Apache service
service:
name: apache2
state: started
enabled: yes
- name: Copy configuration file
template:
src: httpd.conf.j2
dest: /etc/apache2/apache2.conf
notify: restart apache
handlers:
- name: restart apache
service:
name: apache2
state: restarted
Running Playbooks
# Run a playbook
ansible-playbook playbook.yml
# Run with specific inventory
ansible-playbook -i inventory.ini playbook.yml
# Run with extra variables
ansible-playbook playbook.yml --extra-vars "version=1.23.45 other_variable=foo"
# Dry run (check mode)
ansible-playbook playbook.yml --check
# Run with increased verbosity
ansible-playbook playbook.yml -v
Modules
Common Modules
System Modules
# File operations
- name: Create a directory
file:
path: /opt/myapp
state: directory
mode: '0755'
# Copy files
- name: Copy configuration
copy:
src: app.conf
dest: /etc/myapp/app.conf
backup: yes
# Template files
- name: Generate configuration from template
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
Package Management
# APT (Debian/Ubuntu)
- name: Install packages
apt:
name: ['nginx', 'mysql-server', 'php']
state: present
update_cache: yes
# YUM/DNF (RHEL/CentOS/Fedora)
- name: Install packages
yum:
name: ['httpd', 'mariadb-server']
state: present
Service Management
- name: Start and enable service
service:
name: nginx
state: started
enabled: yes
User Management
- name: Create user
user:
name: myuser
group: mygroup
shell: /bin/bash
home: /home/myuser
create_home: yes
Variables and Facts
Defining Variables
In Playbooks:
---
- hosts: webservers
vars:
http_port: 80
server_name: web.example.com
In Separate Files:
# vars/main.yml
http_port: 80
server_name: web.example.com
Using Variable Files:
---
- hosts: webservers
vars_files:
- vars/main.yml
Variable Precedence (Highest to Lowest)
- Extra vars (
-ein command line) - Task vars
- Block vars
- Role and include vars
- Play vars_files
- Play vars_prompt
- Play vars
- Host facts
- Playbook host_vars
- Playbook group_vars
- Inventory host_vars
- Inventory group_vars
- Inventory vars
- Role defaults
Using Variables
- name: Install {{ package_name }}
apt:
name: "{{ package_name }}"
state: present
- name: Print variable
debug:
msg: "The value is {{ my_variable }}"
Facts
Ansible automatically gathers facts about managed hosts:
- name: Display facts
debug:
var: ansible_facts
- name: Use specific fact
debug:
msg: "OS family is {{ ansible_os_family }}"
Handlers
Handlers are tasks that run only when notified by other tasks:
tasks:
- name: Copy configuration
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
Roles
Roles provide a way to group related tasks, variables, files, templates, and handlers.
Role Directory Structure
roles/
webserver/
tasks/
main.yml
handlers/
main.yml
templates/
nginx.conf.j2
files/
index.html
vars/
main.yml
defaults/
main.yml
meta/
main.yml
Creating a Role
ansible-galaxy init webserver
Using Roles in Playbooks
---
- hosts: webservers
roles:
- webserver
- database
- monitoring
Role with Parameters
---
- hosts: webservers
roles:
- role: webserver
http_port: 8080
server_name: custom.example.com
Best Practices
1. Directory Organization
project/
├── ansible.cfg
├── inventories/
│ ├── production/
│ │ ├── hosts.yml
│ │ └── group_vars/
│ └── staging/
│ ├── hosts.yml
│ └── group_vars/
├── playbooks/
├── roles/
└── vars/
2. Use Version Control
Always keep your Ansible code in version control (Git).
3. Name Tasks Descriptively
# Good
- name: Install and start Apache web server
apt:
name: apache2
state: present
# Bad
- apt:
name: apache2
state: present
4. Use Tags
- name: Install packages
apt:
name: "{{ item }}"
state: present
loop: "{{ packages }}"
tags: ['packages', 'setup']
Run specific tags:
ansible-playbook playbook.yml --tags "packages"
5. Use Vault for Sensitive Data
# Create encrypted file
ansible-vault create secrets.yml
# Edit encrypted file
ansible-vault edit secrets.yml
# Run playbook with vault
ansible-playbook playbook.yml --ask-vault-pass
6. Use Check Mode
ansible-playbook playbook.yml --check --diff
7. Handle Failures Gracefully
- name: Start service
service:
name: myservice
state: started
ignore_errors: yes
- name: Alternative approach
service:
name: myservice
state: started
failed_when: false
Common Use Cases
1. Web Server Setup
---
- name: Configure web servers
hosts: webservers
become: yes
tasks:
- name: Install nginx
apt:
name: nginx
state: present
- name: Start nginx
service:
name: nginx
state: started
enabled: yes
- name: Copy website files
copy:
src: website/
dest: /var/www/html/
mode: '0644'
2. Database Configuration
---
- name: Configure MySQL
hosts: databases
become: yes
tasks:
- name: Install MySQL
apt:
name: mysql-server
state: present
- name: Start MySQL
service:
name: mysql
state: started
enabled: yes
- name: Create database
mysql_db:
name: myapp
state: present
3. User Management
---
- name: Manage users
hosts: all
become: yes
tasks:
- name: Create users
user:
name: "{{ item }}"
state: present
groups: sudo
shell: /bin/bash
loop:
- alice
- bob
- charlie
4. System Updates
---
- name: Update systems
hosts: all
become: yes
tasks:
- name: Update package cache
apt:
update_cache: yes
when: ansible_os_family == "Debian"
- name: Upgrade packages
apt:
upgrade: dist
when: ansible_os_family == "Debian"
Troubleshooting
Common Issues and Solutions
1. SSH Connection Issues
# Test SSH connectivity
ansible all -m ping
# Use specific SSH key
ansible all -m ping --private-key=/path/to/key
# Skip host key checking (not recommended for production)
export ANSIBLE_HOST_KEY_CHECKING=False
2. Permission Issues
# Use become (sudo)
ansible all -m shell -a "whoami" --become
# Specify become user
ansible all -m shell -a "whoami" --become --become-user=root
3. Debug Information
- name: Debug variable
debug:
var: my_variable
- name: Debug with message
debug:
msg: "Variable value is {{ my_variable }}"
4. Verbose Output
# Different levels of verbosity
ansible-playbook playbook.yml -v # verbose
ansible-playbook playbook.yml -vv # more verbose
ansible-playbook playbook.yml -vvv # very verbose
ansible-playbook playbook.yml -vvvv # extremely verbose
5. Ansible Configuration
# ansible.cfg
[defaults]
inventory = inventory.ini
host_key_checking = False
retry_files_enabled = False
gathering = smart
fact_caching = memory
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
pipelining = True
Useful Commands
# List all hosts
ansible all --list-hosts
# Check syntax
ansible-playbook playbook.yml --syntax-check
# List tasks
ansible-playbook playbook.yml --list-tasks
# List tags
ansible-playbook playbook.yml --list-tags
# Start at specific task
ansible-playbook playbook.yml --start-at-task="Install packages"
# Limit to specific hosts
ansible-playbook playbook.yml --limit webservers
Conclusion
Ansible is a powerful automation tool that can significantly simplify infrastructure management, application deployment, and configuration management. Its agentless architecture and human-readable YAML syntax make it accessible to both developers and system administrators.
Key takeaways:
- Start simple with ad-hoc commands
- Use playbooks for repeatable automation
- Organize code with roles for reusability
- Follow best practices for maintainable automation
- Use version control and testing
- Leverage the extensive module ecosystem
For more information, refer to the official Ansible documentation.