DEV Community

Maksym
Maksym

Posted on

Complete Ansible Guide

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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: 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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" 
Enter fullscreen mode Exit fullscreen mode

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 } 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

Variables and Templates

Variable Precedence (highest to lowest)

  1. Command line values (-e)
  2. Role defaults
  3. Inventory file variables
  4. Host facts
  5. Play variables
  6. Role variables
  7. Block variables
  8. 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; } } 
Enter fullscreen mode Exit fullscreen mode

Using the template:

- name: Deploy nginx config template: src: nginx.conf.j2 dest: /etc/nginx/conf.d/default.conf notify: restart nginx 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

Using Roles in Playbooks

--- - name: Configure web servers hosts: webservers roles: - common - webserver - { role: monitoring, when: monitoring_enabled } 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 --check mode for dry runs
  • Test on non-production first
  • Use ansible-lint for 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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode
# Run only tagged tasks ansible-playbook site.yml --tags packages # Skip tagged tasks ansible-playbook site.yml --skip-tags config 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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 
Enter fullscreen mode Exit fullscreen mode

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)