8.4 KiB
Introduction to Ansible
Ansible is an open-source IT automation tool that automates:
- Configuration management - setting up servers
- Application deployment - deploying software
- Task automation - repetitive operations
Key Features
- Agentless - no software needed on remote servers
- YAML-based - human-readable playbooks
- Idempotent - safe to run multiple times
- SSH-based - uses existing SSH infrastructure
Core Concepts
Inventory
File listing managed hosts (servers):
[webservers]
web1.example.com
web2.example.com
[databases]
db1.example.com
Playbooks
YAML files describing desired state:
- name: Install nginx
hosts: webservers
tasks:
- name: Install nginx
apt:
name: nginx
state: present
Modules
Reusable units of work (apt, yum, copy, service, etc.)
Roles
Organized collections of tasks, handlers, and files
Quick Start
Ansible Navigator
Ansible Navigator is a CLI tool for exploring and interacting with Ansible content. It provides:
- Playbook visualization
- Task execution tracking
- Inventory exploration
- Interactive shell for testing playbooks
- Integration with Ansible Core features
Use ansible-navigator to:
- Explore playbooks and roles
- Run ad-hoc commands
- Debug playbook execution
- Manage inventory files
- Test YAML syntax
ansible-navigator run playbook.yml
ansible-navigator explore
ansible-navigator shell
- Install:
pip install ansible - Create inventory file
- Write playbook
- Run:
ansible-playbook playbook.yml
Ad-Hoc Commands
ansible all -m ping
ansible all -m command -a "uptime"
ansible webserver -m apt -a "name=vim state=present"
Ansible is ideal for orchestrating infrastructure as code across cloud, on-premise, and hybrid environments.
Handlers
Handlers are tasks that only run when notified by other tasks (typically after a change):
- name: Install nginx
hosts: webservers
tasks:
- name: Install nginx
apt:
name: nginx
state: present
notify: Restart nginx
handlers:
- name: Restart nginx
service:
name: nginx
state: restarted
Variables
Define and use variables for flexibility:
- name: Deploy application
hosts: all
vars:
app_version: "2.1.0"
app_port: 8080
tasks:
- name: Deploy app
get_url:
url: "https://example.com/app-{{ app_version }}.tar.gz"
dest: "/opt/app"
Facts
Ansible gathers system facts automatically:
- name: Display system info
hosts: all
tasks:
- name: Show hostname
debug:
msg: "Host {{ ansible_facts.hostname }} has {{ ansible_facts.memtotal_mb }}MB RAM"
Conditionals
Run tasks based on conditions:
tasks:
- name: Install on Debian
apt:
name: apache2
state: present
when: ansible_facts.os_family == "Debian"
- name: Install on RedHat
yum:
name: httpd
state: present
when: ansible_facts.os_family == "RedHat"
Loops
Repeat tasks with different values:
tasks:
- name: Create users
user:
name: "{{ item }}"
state: present
loop:
- alice
- bob
- charlie
- name: Create multiple directories
file:
path: "{{ item.path }}"
state: directory
mode: "{{ item.mode }}"
loop:
- { path: "/opt/app", mode: "0755" }
- { path: "/var/log/app", mode: "0700" }
Templates (Jinja2)
Generate configuration files dynamically:
# templates/nginx.conf.j2
server {
listen {{ nginx_port }};
server_name {{ domain_name }};
root {{ document_root }};
location / {
{% if enable_caching %}
expires {{ cache_duration }};
{% endif %}
}
}
- name: Deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
Ansible Vault
Encrypt sensitive data (passwords, keys, etc.):
# Create encrypted file
ansible-vault create secrets.yml
# Edit encrypted file
ansible-vault edit secrets.yml
# Encrypt existing file
ansible-vault encrypt_string "my_password" --name "db_password"
# Run playbook with vault
ansible-playbook site.yml --ask-vault-pass
ansible-playbook site.yml --vault-password-file ~/.vault_pass
Roles
Organize playbooks into reusable structures:
roles/
common/
tasks/
main.yml
handlers/
main.yml
templates/
files/
vars/
main.yml
defaults/
main.yml
# site.yml
- name: Deploy infrastructure
hosts: webservers
roles:
- common
- nginx
- webapp
Tags
Control which tasks run:
tasks:
- name: Install dependencies
apt:
name: "{{ item }}"
loop:
- python3
- git
tags: [install, setup]
- name: Configure app
template:
src: app.conf.j2
dest: /etc/app.conf
tags: [configure]
- name: Start service
service:
name: app
state: started
tags: [deploy]
ansible-playbook site.yml --tags "install,configure"
ansible-playbook site.yml --skip-tags "deploy"
Delegation
Run tasks on specific hosts:
- name: Load balancer config
hosts: webservers
tasks:
- name: Update load balancer
haproxy:
state: enabled
delegate_to: lb01.example.com
- name: Get facts from database server
setup:
delegate_to: db01.example.com
Async and Parallel Tasks
Run long-running tasks without blocking:
tasks:
- name: Long backup task
command: /usr/local/bin/backup.sh
async: 3600
poll: 0
register: backup_job
- name: Check backup status
async_status:
jid: "{{ backup_job.ansible_job_id }}"
register: backup_result
until: backup_result.finished
retries: 30
Check Mode (Dry Run)
Preview changes without applying them:
ansible-playbook site.yml --check
ansible-playbook site.yml -C # shorthand
Task Error Handling
Control task failure behavior:
tasks:
- name: Ignore errors
command: /opt/risky-script.sh
ignore_errors: yes
- name: Custom failure
command: /opt/check-service.sh
register: result
failed_when: result.rc != 0 and "ERROR" in result.stdout
- name: Block with rescue
block:
- name: Deploy application
include_tasks: deploy.yml
rescue:
- name: Rollback
include_tasks: rollback.yml
always:
- name: Cleanup
file:
path: /tmp/deploy-temp
state: absent
Ansible Galaxy
Download and use community roles:
# Search for roles
ansible-galaxy search nginx
# Install a role
ansible-galaxy install nginx.docker
# Create role skeleton
ansible-galaxy init myrole
# Install from requirements file
ansible-galaxy install -r requirements.yml
Dynamic Inventory
Use dynamic sources for cloud environments:
# AWS EC2
ansible-playbook -i ec2.py site.yml
# Kubernetes
ansible-playbook -i k8s.yml site.yml
# inventory.ini with groups and variables
[webservers]
web1.example.com ansible_host=192.168.1.10
web2.example.com ansible_host=192.168.1.11
[webservers:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_rsa
[databases]
db1.example.com
Useful Modules Reference
| Module | Purpose |
|---|---|
apt / yum / dnf |
Package management |
copy |
Copy files to remote |
template |
Generate files with Jinja2 |
file |
Create files/directories/symlinks |
service |
Manage services |
user |
User account management |
cron |
Schedule tasks |
uri |
Interact with HTTP APIs |
get_url |
Download files |
git / subversion |
Version control |
docker_container |
Container management |
k8s |
Kubernetes operations |
aws_ec2 |
AWS resource management |
shell / command |
Execute commands |
debug |
Print variables |
assert |
Validate conditions |
Best Practices
- Use roles - Organize tasks into reusable roles
- Minimize
shell/command- Prefer modules for idempotency - Use
check_mode- Test changes before applying - Encrypt secrets - Always use Ansible Vault for sensitive data
- Use tags - Enable selective execution
- Define handlers - Trigger actions only on changes
- Validate syntax - Run
ansible-playbook --syntax-checkbefore execution