Files
ansible/intro.md

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:

  1. Explore playbooks and roles
  2. Run ad-hoc commands
  3. Debug playbook execution
  4. Manage inventory files
  5. Test YAML syntax
ansible-navigator run playbook.yml
ansible-navigator explore
ansible-navigator shell
  1. Install: pip install ansible
  2. Create inventory file
  3. Write playbook
  4. 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

  1. Use roles - Organize tasks into reusable roles
  2. Minimize shell/command - Prefer modules for idempotency
  3. Use check_mode - Test changes before applying
  4. Encrypt secrets - Always use Ansible Vault for sensitive data
  5. Use tags - Enable selective execution
  6. Define handlers - Trigger actions only on changes
  7. Validate syntax - Run ansible-playbook --syntax-check before execution