Ansible is a agentless IT automation platform designed for configuration management, application deployment, infrastructure provisioning, and orchestration of complex workflows—such as rolling updates or zero-downtime deployments. It scales seamlessly from small environments with a handful of servers to large-scale enterprise infrastructures spanning thousands of nodes.
Its core strengths lie in three pillars:
- Simplicity: Minimal learning curve; uses human-readable YAML and requires no client-side daemons or agents.
- Power: Enables full lifecycle automation—from bootstrapping to decommissioning—with idempotent, repeatable operations.
- Security & Predictability: Operates over SSH using standard authentication mechanisms (passwords or key pairs), ensuring auditability and deterministic outcomes.
Initial Setup
Install Ansible on the control node via package manager:
yum install -y ansible
Post-installation, the default configuration resides in /etc/ansible/, containing ansible.cfg and hosts. The inventory file (hosts) defines target systems and logical groupings:
[webservers]
192.168.1.6 ansible_user=webadmin hostname=web1
192.168.1.5 ansible_user=webadmin hostname=web2
[dbservers]
192.168.1.10 ansible_user=dbuser
Custom inventory paths can be specified at runtime: ansible-playbook -i ./production-inventory site.yml.
Connection Methods
Ansible supports two primary connection models:
- Password-based SSH: Define credentials inline (not recommended for production):
192.168.1.5 ansible_user=admin ansible_password='P@ssw0rd'
Then invoke with-kto prompt for SSH password:
ansible webservers -m ping -k - SSH Key Authentication: Generate keys on the control node:
ssh-keygen -t ed25519 -f ~/.ssh/ansible_id -N ""
Distribute the public key to targets:
ssh-copy-id -i ~/.ssh/ansible_id.pub admin@192.168.1.5
Reference the private key in inventory or config:
ansible_ssh_private_key_file=/home/admin/.ssh/ansible_id
Core Command-Line Options
| Flag | Purpose |
|---|---|
-C / --check |
Perform a dry-run without making changes |
-e "key=value" |
Inject extra variables at runtime |
-u / --user |
Specify remote user (defaults to currant local user) |
-b / --become |
Elevate privileges (e.g., via sudo) |
-K / --ask-become-pass |
Prompt for privilege escalation password |
Ad-Hoc Commands
Execute one-off tasks across inventories:
ansible webservers -m ping
ansible dbservers -m shell -a "df -h && uptime"
The shell module executes arbitrary shell commands, while safer alternatives like command avoid shell interpretation.
Built-in Modules
Modules are Ansible’s execution units. List all available modules:
ansible-doc -l
View usage details for a specific module:
ansible-doc copy
Commonly used modules include:
copy: Transfer files with checksum validationfile: Manage file attributes, permissions, and state (state=directory,state=absent)yum/dnf: Install/remove RPM packagessystemd: Control services (state=started,enabled=yes)unarchive: Extract archives (supports tar, zip, gz)debug: Print variables or diagnostic messages
Playbooks: Declarative Automation
Playbooks define infrastructure-as-code using YAML. A minimal playbook structure:
---
- name: Configure web servers
hosts: webservers
gather_facts: false
become: true
vars:
app_port: 8080
tasks:
- name: Ensure Nginx is installed
yum:
name: nginx
state: present
- name: Start and enable Nginx service
systemd:
name: nginx
state: started
enabled: true
Key directives:
hosts: Target host group(s) from inventorybecome: Enable privilege escalation (equivalent tosudo)gather_facts: Disable automatic fact collection for performance in large environmentsvars: Inline variable definitions scoped to the play
Variable Management
Variables can be defined at multiple levels:
- Inventory-level: In
hostsor dedicatedgroup_vars/andhost_vars/directories
Example:group_vars/webservers.yml:
nginx_version: "1.24.0"
log_level: "warn"
- Playbook-level: Under
vars:orvars_files: - Runtime: Via
-e "var=value"flag
Reference variables using {{ variable_name }}. To capture task output:
- name: Test connectivity
ping:
register: ping_result
- name: Display result
debug:
var: ping_result
Control Flow
Tags allow selective execution:
- name: Deploy frontend assets
copy:
src: ./dist/
dest: /var/www/html/
tags: deploy,frontend
Run only tagged tasks:
ansible-playbook site.yml --tags "deploy"
Conditional execution with when:
- name: Restart Nginx only on CentOS
systemd:
name: nginx
state: restarted
when: ansible_facts['distribution'] == "CentOS"
Loops simplify repetitive tasks:
- name: Create log directories
file:
path: "/var/log/{{ item }}"
state: directory
mode: '0755'
loop:
- app
- api
- cache
Other loop constructs enclude loop: "{{ groups['dbservers'] }}" for dynamic host iteration.
Templates with Jinja2
The template module renders dynamic configuration files using Jinja2 syntax:
- name: Deploy Nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/conf.d/app.conf
In nginx.conf.j2:
server {
listen {{ app_port }};
server_name {{ domain_name | default('localhost') }};
location / {
proxy_pass http://backend;
}
}
Jinja2 filters (e.g., | default) enhance flexibility and safety.
Roles for Reusability
Roles enforce modular, reusable automation logic. Directory layout:
roles/
├── nginx/
│ ├── defaults/
│ ├── files/
│ ├── handlers/
│ ├── meta/
│ ├── tasks/
│ │ └── main.yml
│ ├── templates/
│ └── vars/
└── mysql/
└── ...
A top-level playbook consumes roles:
---
- name: Deploy web stack
hosts: webservers
roles:
- nginx
- app-deploy
- name: Provision database layer
hosts: dbservers
roles:
- mysql
This pattern promotes separation of concerns, version control compatibility, and community sharing via Ansible Galaxy.