What is Ansible?
Ansible is an open-source automation platform that simplifies configuration management, application deployment, task automation, and orchestration. It uses a simple, human-readable language (YAML) and operates over SSH without requiring agents on target machines.
Key Benefits
- Agentless: No need to install software on target machines
- Simple: Uses YAML syntax that's easy to read and write
- Powerful: Can manage complex multi-tier deployments
- Idempotent: Safe to run multiple times without side effects
- Secure: Uses SSH and doesn't leave software installed on targets
Core Concepts
Inventory
A list of managed nodes (servers, network devices, etc.) that Ansible controls. Can be static files or dynamic sources.
Playbooks
YAML files containing a series of tasks to execute on target hosts. Think of them as automation scripts.
Tasks
Individual units of work that Ansible executes, like installing packages or copying files.
Modules
Reusable units of code that Ansible executes. Examples: yum, copy, service, user.
Roles
Way to organize playbooks and reuse code. Roles group related tasks, variables, files, and templates.
Variables
Data that can change how playbooks behave. Can be defined in multiple places with different precedence levels.
Installation
On Control Node (where you run Ansible)
Using pip:
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 # macOS brew install ansible Basic Configuration
Ansible Configuration File
Create /etc/ansible/ansible.cfg or ~/.ansible.cfg:
[defaults] inventory = ./inventory 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 Inventory Management
Static Inventory
Basic inventory file (inventory or hosts):
# Individual hosts web1.example.com web2.example.com # Groups [webservers] web1.example.com web2.example.com [databases] db1.example.com db2.example.com # Groups of groups [production:children] webservers databases # Variables [webservers:vars] http_port=80 nginx_version=1.18 YAML inventory format:
all: hosts: web1.example.com: web2.example.com: children: webservers: hosts: web1.example.com: web2.example.com: vars: http_port: 80 databases: hosts: db1.example.com: db2.example.com: Dynamic Inventory
For cloud environments, you can use dynamic inventory scripts or plugins that query cloud APIs.
Ad-hoc Commands
Run single tasks without playbooks:
# Ping all hosts ansible all -m ping # Check uptime ansible webservers -m command -a "uptime" # Install package ansible webservers -m yum -a "name=nginx state=present" --become # Copy file ansible webservers -m copy -a "src=/local/file dest=/remote/file" # Start service ansible webservers -m service -a "name=nginx state=started enabled=yes" --become Playbooks
Basic Playbook Structure
--- - name: Web server setup hosts: webservers become: yes vars: http_port: 80 tasks: - name: Install nginx yum: name: nginx state: present - name: Start and enable nginx service: name: nginx state: started enabled: yes - name: Open firewall for HTTP firewalld: port: "{{ http_port }}/tcp" permanent: yes state: enabled immediate: yes Advanced Playbook Features
Handlers (run when notified):
tasks: - name: Update nginx config template: src: nginx.conf.j2 dest: /etc/nginx/nginx.conf notify: restart nginx handlers: - name: restart nginx service: name: nginx state: restarted Conditionals:
tasks: - name: Install Apache (RedHat family) yum: name: httpd state: present when: ansible_os_family == "RedHat" - name: Install Apache (Debian family) apt: name: apache2 state: present when: ansible_os_family == "Debian" Loops:
tasks: - name: Create users user: name: "{{ item.name }}" group: "{{ item.group }}" shell: "{{ item.shell | default('/bin/bash') }}" loop: - { name: alice, group: admin } - { name: bob, group: users } - { name: charlie, group: users, shell: /bin/zsh } Error handling:
tasks: - name: Attempt risky operation command: /bin/false ignore_errors: yes register: result - name: Handle failure debug: msg: "Previous task failed, but continuing" when: result is failed Variables and Templates
Variable Precedence (highest to lowest)
- Command line values (
-e) - Role defaults
- Inventory file variables
- Host facts
- Play variables
- Role variables
- Block variables
- Task variables
Using Templates (Jinja2)
Template file (templates/nginx.conf.j2):
server { listen {{ http_port }}; server_name {{ ansible_hostname }}; location / { root /var/www/html; index index.html; } } Using the template:
- name: Deploy nginx config template: src: nginx.conf.j2 dest: /etc/nginx/conf.d/default.conf notify: restart nginx Roles
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 Using Roles in Playbooks
--- - name: Configure web servers hosts: webservers roles: - common - webserver - { role: monitoring, when: monitoring_enabled } Creating Roles with Ansible Galaxy
# Create role structure ansible-galaxy init webserver # Install role from Galaxy ansible-galaxy install geerlingguy.nginx # Install from requirements file ansible-galaxy install -r requirements.yml Common Modules
System Modules
-
yum/apt- Package management -
service/systemd- Service management -
user/group- User management -
cron- Crontab management -
mount- Filesystem mounting
File Modules
-
copy- Copy files to remote hosts -
template- Process Jinja2 templates -
file- Set file attributes -
lineinfile- Ensure line in file -
replace- Replace text in files
Command Modules
-
command- Run commands -
shell- Run shell commands -
script- Run local script on remote hosts -
raw- Run raw SSH commands
Cloud Modules
-
ec2- AWS EC2 management -
azure_rm_*- Azure resource management -
gcp_*- Google Cloud Platform
Best Practices
Playbook Organization
- Use descriptive names for plays and tasks
- Keep playbooks focused and modular
- Use roles for reusable code
- Group related functionality together
Variable Management
- Use group_vars and host_vars directories
- Keep sensitive data in Ansible Vault
- Use meaningful variable names
- Document variable purposes
Security
- Use Ansible Vault for sensitive data
- Limit sudo usage with
become_user - Use SSH key authentication
- Regularly update Ansible
Testing
- Use
--checkmode for dry runs - Test on non-production first
- Use
ansible-lintfor syntax checking - Version control your playbooks
Ansible Vault
Encrypting Files
# Create encrypted file ansible-vault create secret.yml # Encrypt existing file ansible-vault encrypt secret.yml # Edit encrypted file ansible-vault edit secret.yml # View encrypted file ansible-vault view secret.yml # Decrypt file ansible-vault decrypt secret.yml Using Vaulted Variables
# Run playbook with vault password ansible-playbook site.yml --ask-vault-pass # Use password file ansible-playbook site.yml --vault-password-file ~/.vault_pass Running Playbooks
Basic Execution
# Run playbook ansible-playbook site.yml # Dry run (check mode) ansible-playbook site.yml --check # Limit to specific hosts ansible-playbook site.yml --limit webservers # Use different inventory ansible-playbook site.yml -i production # Override variables ansible-playbook site.yml -e "http_port=8080" # Increase verbosity ansible-playbook site.yml -vvv Tags
tasks: - name: Install packages yum: name: "{{ item }}" state: present loop: "{{ packages }}" tags: packages - name: Configure service template: src: config.j2 dest: /etc/service/config tags: config # Run only tagged tasks ansible-playbook site.yml --tags packages # Skip tagged tasks ansible-playbook site.yml --skip-tags config Troubleshooting
Common Issues
- SSH connectivity problems
- Permission errors (use
--become) - Python interpreter issues
- Module not found errors
- YAML syntax errors
Debugging Commands
# Verbose output ansible-playbook site.yml -vvv # Debug specific host ansible hostname -m setup # Check inventory ansible-inventory --list # Syntax check ansible-playbook site.yml --syntax-check # List tasks ansible-playbook site.yml --list-tasks Example: Complete Web Server Deployment
--- - name: Deploy web application hosts: webservers become: yes vars: app_name: myapp app_port: 8080 tasks: - name: Update system packages yum: name: "*" state: latest tags: system - name: Install required packages yum: name: - nginx - python3 - git state: present tags: packages - name: Create application user user: name: "{{ app_name }}" system: yes shell: /bin/false home: "/opt/{{ app_name }}" create_home: yes tags: users - name: Clone application repository git: repo: https://github.com/company/myapp.git dest: "/opt/{{ app_name }}/app" version: main become_user: "{{ app_name }}" tags: deploy - name: Install application dependencies pip: requirements: "/opt/{{ app_name }}/app/requirements.txt" virtualenv: "/opt/{{ app_name }}/venv" become_user: "{{ app_name }}" tags: deploy - name: Configure nginx template: src: nginx-app.conf.j2 dest: "/etc/nginx/conf.d/{{ app_name }}.conf" notify: restart nginx tags: config - name: Configure systemd service template: src: app.service.j2 dest: "/etc/systemd/system/{{ app_name }}.service" notify: - reload systemd - restart app tags: config - name: Start and enable services service: name: "{{ item }}" state: started enabled: yes loop: - nginx - "{{ app_name }}" tags: services handlers: - name: restart nginx service: name: nginx state: restarted - name: reload systemd systemd: daemon_reload: yes - name: restart app service: name: "{{ app_name }}" state: restarted This guide covers the fundamentals of Ansible. Start with simple playbooks and gradually incorporate more advanced features as you become comfortable with the basics.
Top comments (0)