Understanding Ansible Core Concepts
1. Understanding Control Node
| Concept | Description | Details |
|---|---|---|
| Control Node | Central management server | The machine where Ansible is installed and executed from. It contains the inventory of managed nodes, playbooks, and configuration files. |
| Managed Nodes | Target systems to be configured | Remote machines that are managed by the control node. These can be Linux, Windows, or other systems with SSH or WinRM access. |
| Inventory | List of managed nodes | File (usually hosts.ini or hosts.yml) that defines the managed nodes and their groups. |
| Playbooks | YAML files defining automation tasks | Structured YAML documents that describe the desired state or configuration of managed nodes. |
| Modules | Reusable units of automation logic | Built-in or custom components that perform specific actions like managing files, packages, services, etc. |
| Tasks | Individual actions within playbooks | Units of work that execute a module with specific parameters to achieve a desired outcome. |
Example: Basic Inventory File
[webservers]
web1.example.com
web2.example.com
[databases]
db1.example.com
[all:vars]
ansible_user=ansible
ansible_ssh_private_key_file=~/.ssh/ansible_key
Example: Simple Playbook
- name: Configure web servers
hosts: webservers
tasks:
- name: Ensure Apache is installed
apt:
name: apache2
state: present
- name: Start and enable Apache service
systemd:
name: apache2
state: started
enabled: yes
2. Understanding Managed Nodes
| Property | Description | Example |
|---|---|---|
| ansible_host | IP address or hostname of the managed node | 192.168.1.10 |
| ansible_user | User account to connect as | ubuntu |
| ansible_port | SSH port to connect on | 22 |
| ansible_connection | Connection type to use (local, ssh, winrm) | ssh |
| ansible_become | Use privilege escalation (sudo) | true |
| ansible_ssh_private_key_file | Path to SSH private key file | ~/.ssh/id_rsa |
Example: Inventory configuration for managed nodes
[webservers]
web1 ansible_host=192.168.1.10 ansible_user=ubuntu ansible_port=22
web2 ansible_host=192.168.1.11 ansible_user=ubuntu ansible_port=22
[databases]
db1 ansible_host=192.168.1.20 ansible_user=root ansible_port=22 ansible_become=true
3. Understanding Modules
| Module | Description | Use Case | Notes |
|---|---|---|---|
| ansible.builtin.copy | Copies files from the local machine to the remote host. | Deploying configuration files or templates. | Supports source, content, and mode parameters. |
| ansible.builtin.file | Manages file attributes like permissions, ownership, and type. | Setting up file permissions or creating symbolic links. | Can manage directory structure and file states. |
| ansible.builtin.shell | Executes shell commands on the remote host. | Running custom scripts or one-time command execution. | Use with caution due to security implications. |
| ansible.builtin.uri | Fetches content from a URI or makes HTTP requests. | Checking API status or downloading files over HTTPS. | Supports authentication and response validation. |
| ansible.builtin.yum | Manages packages on Red Hat-based systems. | Installing or updating software packages. | Supports repository management and version control. |
| ansible.builtin.apt | Manages packages on Debian-based systems. | Installing or updating software packages on Ubuntu/Debian. | Supports repository configuration and package state. |
Example: Using the copy module to deploy a config file
- name: Deploy application config
ansible.builtin.copy:
src: app.conf
dest: /etc/app.conf
mode: '0644'
owner: appuser
group: appgroup
Example: Using the shell module to run a command
- name: Run a system check
ansible.builtin.shell: |
df -h
free -m
register: system_info
4. Understanding Plugins
| Plugin Type | Description | Location | Example |
|---|---|---|---|
| Action | Executes tasks on managed nodes | ansible/plugins/action/ |
command, shell |
| Connection | Manages how Ansible connects to managed nodes | ansible/plugins/connection/ |
ssh, winrm |
| Inventory | Defines managed nodes and groups | ansible/plugins/inventory/ |
yaml, ini |
| Lookup | Retrieves data from external sources | ansible/plugins/lookup/ |
file, env |
| Vars | Loads variables from external sources | ansible/plugins/vars/ |
yaml, ini |
| Filter | Modifies variables in templates | ansible/plugins/filter/ |
upper, json_query |
| Test | Used in conditionals and templates | ansible/plugins/test/ |
exists, match |
Example: Using a Custom Filter Plugin
# plugins/filter/custom_filter.py
from ansible.plugins.filter import FilterModule
class FilterModule(FilterModule):
def filters(self):
return {
'to_upper': self.to_upper
}
def to_upper(self, value):
return value.upper()
Example: Using the Filter in a Playbook
- name: Use custom filter
hosts: all
tasks:
- name: Set variable with filter
set_fact:
upper_name: "{{ 'hello world' | to_upper }}"
- name: Display result
debug:
msg: "Uppercase name: {{ upper_name }}"
5. Understanding Collections
Collections are the distribution format for Ansible content, including playbooks, roles, modules, and plugins. They allow you to organize and share Ansible content effectively.
| Collection | Description | Components |
|---|---|---|
| ansible.builtin | Core modules provided by Ansible | Modules, plugins |
| community.general | General-purpose modules maintained by the community | Modules, roles |
| ansible.posix | Modules for POSIX-compliant systems | Modules, plugins |
Example: Using a Collection in a Playbook
- name: Use a module from a collection
hosts: all
tasks:
- name: Install a package using community.general
community.general.yum:
name: httpd
state: present
ansible-galaxy collection install.
Key Features of Collections
- Modular Design: Encapsulate related functionality
- Versioning: Support for versioned releases
- Distribution: Shareable and reusable content
- Namespace: Prevent naming conflicts with other collections
6. Understanding Inventory
| Property | Description | Example |
|---|---|---|
| hosts | List of hosts to include in the inventory | web01 ansible_host=192.168.1.10 |
| ansible_host | IP address or hostname to connect to | web01 ansible_host=192.168.1.10 |
| ansible_port | SSH port to connect on (default 22) | web01 ansible_host=192.168.1.10 ansible_port=2222 |
| ansible_user | User to connect as | web01 ansible_host=192.168.1.10 ansible_user=admin |
| ansible_become | Use privilege escalation (sudo) | web01 ansible_host=192.168.1.10 ansible_become=yes |
| ansible_connection | Connection type (local, ssh, etc.) | web01 ansible_connection=local |
Example: Basic Inventory File
[webservers]
web01 ansible_host=192.168.1.10
web02 ansible_host=192.168.1.11
[databases]
db01 ansible_host=192.168.1.20
[all:vars]
ansible_user=ubuntu
ansible_become=yes
Example: Using Groups
[production]
web01 ansible_host=192.168.1.10
web02 ansible_host=192.168.1.11
[staging]
web03 ansible_host=192.168.1.12
[webservers:children]
production
staging
Inventory Types
- Static: Defined in files (INI, YAML)
- Dynamic: Generated by external tools or scripts
- Cloud: Pull from cloud providers (AWS, GCP, Azure)
7. Understanding Playbooks
A playbook in Ansible is a YAML file that defines a set of tasks to be executed on managed nodes. Playbooks are the primary way to configure, deploy, and orchestrate automation tasks in Ansible.
| Field | Description | Required |
|---|---|---|
| name | Description of the playbook's purpose | Yes |
| hosts | Inventory groups or hosts to target | Yes |
| vars | Variables to use in the playbook | No |
| tasks | List of tasks to execute | Yes |
| roles | List of roles to include | No |
Example: Basic Playbook Structure
---
name: "Deploy web application"
hosts: webservers
vars:
app_port: 8080
tasks:
- name: "Install application dependencies"
apt:
name: "nodejs"
state: "present"
- name: "Start application service"
systemd:
name: "myapp.service"
state: "started"
8. Understanding Tasks
| Property | Description | Example |
|---|---|---|
| name | Human-readable description of the task | "Create directory /opt/myapp" |
| action | Module to execute and its arguments | file: path=/opt/myapp state=directory |
| when | Conditional expression to determine if task runs | when: ansible_os_family == "RedHat" |
| loop | Repeat task for each item in a list | loop: [ "nodejs", "npm" ] |
| register | Store output of a task for later use | register: result |
Example: Creating a Directory
- name: Create directory /opt/myapp
file:
path: /opt/myapp
state: directory
Example: Conditional Task Execution
- name: Install Node.js on RedHat systems
yum:
name: nodejs
state: present
when: ansible_os_family == "RedHat"
Example: Looping Over a List
- name: Install packages
yum:
name: "{{ item }}"
state: present
loop:
- nodejs
- npm
9. Understanding Handlers
Handlers in Ansible are tasks that are executed only when notified by other tasks. They are typically used to restart services or perform actions after configuration changes.
| Property | Description | Example |
|---|---|---|
| name | Unique identifier for the handler | restart nginx |
| notify | Used in tasks to trigger the handler | notify: restart nginx |
| when | Condition to determine if handler should run | when: service_restarted |
Example: Restarting a Service
---
- name: Configure Nginx
hosts: webservers
tasks:
- name: Update nginx config
copy:
src: nginx.conf
dest: /etc/nginx/nginx.conf
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
10. Understanding Facts
| Fact | Description | Example |
|---|---|---|
| ansible_fqdn | Fully qualified domain name of the target host | web01.example.com |
| ansible_hostname | Hostname of the target host | web01 |
| ansible_os_family | Operating system family (e.g., RedHat, Debian) | RedHat |
| ansible_distribution | Operating system distribution name | Ubuntu |
| ansible_distribution_version | Version of the OS distribution | 20.04 |
| ansible_kernel | Kernel version of the target host | 5.4.0-104-generic |
| ansible_memtotal_mb | Total memory in MB | 4096 |
| ansible_processor_count | Number of CPU cores | 4 |
| ansible_default_ipv4 | Default IPv4 address of the host | {"address": "192.168.1.100", "netmask": "255.255.255.0"} |
Example: Using Facts in a Playbook
- name: Display OS Information
hosts: all
tasks:
- name: Show OS family and version
debug:
msg: "OS Family: {{ ansible_os_family }}, Version: {{ ansible_distribution_version }}"
gather_facts: false is set in the playbook or host configuration.
11. Understanding Push vs Pull
| Aspect | Push Model | Pull Model |
|---|---|---|
| Control Node | The control node initiates and manages the execution of tasks. | The managed nodes initiate their own execution and report back to a central system. |
| Agent Deployment | Ansible requires no agents on managed nodes; it uses SSH or WinRM. | Agents must be installed and maintained on managed nodes (e.g., Ansible Tower, AWX). |
| Communication | Control node pushes configuration to managed nodes via SSH or WinRM. | Managed nodes pull configuration from a central server or API endpoint. |
| Scalability | Highly scalable due to lightweight agents (SSH/WinRM). | Scalability depends on agent management and central server capacity. |
| Security | Uses SSH keys or passwords for secure communication. | Relies on secure communication protocols between agents and central server. |
| Use Case | Best for environments where agents cannot be installed or managed. | Best for large-scale deployments with centralized control and visibility. |
Push vs Pull Comparison
- Push: Centralized control, no agent required on managed nodes.
- Pull: Distributed control, agents required for communication.
12. Understanding Idempotency
Idempotency is a fundamental concept in Ansible that ensures operations can be applied multiple times without causing unintended side effects. Each Ansible task is designed to be idempotent, meaning that running the same playbook multiple times will produce the same result as running it once.
| Concept | Description | Example |
|---|---|---|
| Idempotent Operation | An operation that can be applied multiple times without changing the result beyond the initial application. | Ensuring a package is installed using apt or yum will not reinstall it if already present. |
| State Management | Ansible modules manage state to ensure idempotency by checking the current state before applying changes. | Using state: present in a task ensures the resource exists without reapplying changes. |
Example: Idempotent Package Installation
- name: Ensure nginx is installed
apt:
name: nginx
state: present