Introduction to Ansible
Ansible is an open-source automation tool that simplifies configuration management, application deployment, and task automation. Unlike other configuration management tools, Ansible uses a simple, agentless architecture powered by SSH.
What is Ansible?
Ansible is:
- Configuration Management: Maintain consistent system configurations
- Application Deployment: Automate application deployments
- Orchestration: Coordinate multi-machine deployments
- Provisioning: Set up infrastructure and services
Why Ansible?
Key Benefits:
- Agentless: No agents to install on managed nodes
- Simple: Uses YAML for configuration
- Powerful: Complex automation with minimal code
- Reliable: Idempotent operations ensure consistency
- Fast: Parallel execution across multiple hosts
Installing Ansible
Installation Methods
1. pip (Python Package Manager):
pip install ansible2. Package Managers:
macOS:
brew install ansibleUbuntu/Debian:
sudo apt update
sudo apt install ansibleRHEL/CentOS:
sudo yum install ansible3. pipx (Recommended for development):
pipx install ansibleVerifying Installation
ansible --version
ansible 2.15.0
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules']
ansible python module location = /usr/lib/python3/dist-packages/ansible
ansible collection location = /home/user/.ansible/collectionsAnsible Architecture
Control Node vs Managed Nodes
Control Node:
- Runs Ansible
- Manages configuration
- Executes playbooks
Managed Nodes:
- Systems being configured
- Only require Python and SSH
- No agent installation needed
Architecture Diagram
┌──────────────┐ SSH ┌──────────────┐
│ Control Node │ ─────────────────────▶│ Managed Node │
│ │ SSH Keys/Password │ │
│ - Ansible │ │ - Python │
│ - Playbooks │ │ - Services │
│ - Modules │◀───────────────────── │ │
└──────────────┘ Connection └──────────────┘
EstablishedInventory
What is Inventory?
Inventory defines the hosts that Ansible manages. It's a list of target systems grouped logically.
INI Format Inventory
# inventory.ini
[webservers]
web1.example.com
web2.example.com
web3.example.com
[dbservers]
db1.example.com
db2.example.com
[production]
web1.example.com
db1.example.com
[staging]
web2.example.com
db2.example.com
[all:vars]
ansible_user=ubuntu
ansible_ssh_private_key_file=~/.ssh/id_rsaYAML Format Inventory
# inventory.yaml
all:
children:
webservers:
hosts:
web1.example.com:
web2.example.com:
web3.example.com:
dbservers:
hosts:
db1.example.com:
db2.example.com:
production:
children:
webservers:
dbservers:
vars:
ansible_user: ubuntu
ansible_ssh_private_key_file: ~/.ssh/id_rsaDynamic Inventory
# AWS EC2 dynamic inventory
ansible-inventory -i ec2.yaml --list
# Kubernetes dynamic inventory
ansible-inventory -i kubernetes.yaml --listAd-Hoc Commands
Basic Syntax
ansible [pattern] -m [module] -a "[module arguments]"Common Ad-Hoc Commands
1. Ping Check:
ansible all -m ping2. Check Uptime:
ansible webservers -m command -a "uptime"3. Install Package:
ansible webservers -m apt -a "name=nginx state=present" -b4. Start Service:
ansible webservers -m service -a "name=nginx state=started" -b5. Copy Files:
ansible webservers -m copy -a "src=./index.html dest=/var/www/html/" -b6. Gather Facts:
ansible all -m setup
ansible webservers -m setup -a "filter=ansible_distribution*"Useful Modules
Command Modules:
command: Execute commands (default)shell: Execute shell commands with pipes/redirectionraw: Execute via SSH without Python
File Modules:
copy: Copy files to hostsfile: Set file attributesfetch: Copy files from hoststemplate: Deploy template files
Package Modules:
apt: Debian/Ubuntu packagesyum: RHEL/CentOS packagesdnf: Fedora packagespip: Python packages
Service Modules:
service: Manage servicessystemd: Manage systemd services
Modules
Understanding Modules
Modules are the building blocks of Ansible. Each module performs a specific task.
Using Modules
1. Command Module:
ansible webservers -m command -a "ls -l /var/www"2. Shell Module:
ansible all -m shell -a "echo $HOME >> /tmp/test.txt"3. Copy Module:
ansible webservers -m copy -a \
"src=/etc/hosts dest=/tmp/hosts backup=yes"4. Template Module:
ansible webservers -m template -a \
"src=index.j2 dest=/var/www/html/index.html"5. File Module:
ansible all -m file -a \
"path=/tmp/myfile state=touch mode=0600"6. Service Module:
ansible webservers -m service -a \
"name=nginx state=started enabled=yes"7. Apt Module:
ansible webservers -m apt -a \
"name=nginx state=present update_cache=yes"8. User Module:
ansible all -m user -a \
"name=john state=present shell=/bin/bash groups=sudo"9. Git Module:
ansible webservers -m git -a \
"repo=https://github.com/user/repo.git dest=/var/www/myapp version=main"10. Cron Module:
ansible all -m cron -a \
"name='daily backup' job='/backup.sh' hour=2 minute=0"Configuration
ansible.cfg
# ansible.cfg
[defaults]
# Inventory location
inventory = ./inventory
# Remote user
remote_user = ubuntu
# Private key file
private_key_file = ~/.ssh/id_rsa
# Host key checking
host_key_checking = False
# Timeout
timeout = 30
# Number of parallel processes
forks = 5
# Display task timing
callback_whitelist = timer, profile_tasks
# Gather facts
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/facts_cache
fact_caching_timeout = 86400
# Disable retry files
retry_files_enabled = False
# Log path
log_path = ./ansible.log
[inventory]
# Enable inventory plugins
enable_plugins = host_list, script, auto, yaml, ini, toml
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[ssh_connection]
# SSH connection settings
pipelining = True
control_path = /tmp/ansible-ssh-%%h-%%p-%%rEnvironment Variables
export ANSIBLE_HOST_KEY_CHECKING=False
export ANSIBLE_INVENTORY=./inventory
export ANSIBLE_REMOTE_USER=ubuntu
export ANSIBLE_PRIVATE_KEY_FILE=~/.ssh/id_rsaSSH Setup
SSH Key Authentication
1. Generate SSH Key:
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"2. Copy Public Key to Managed Nodes:
ssh-copy-id ubuntu@web1.example.com
ssh-copy-id ubuntu@web2.example.com3. Test Connection:
ssh ubuntu@web1.example.comSSH Agent
# Start SSH agent
eval "$(ssh-agent -s)"
# Add key to agent
ssh-add ~/.ssh/id_rsa
# Test with Ansible
ansible all -m pingSSH Config
Host *.example.com
User ubuntu
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
UserKnownHostsFile=/dev/nullFacts Gathering
What are Facts?
Facts are system information collected by Ansible from managed nodes.
Disabling Facts
---
- name: Play without facts
hosts: webservers
gather_facts: no
tasks:
- name: Task without facts
debug:
msg: "Facts gathering disabled"Gathering Specific Facts
---
- name: Play with specific facts
hosts: webservers
gather_facts: yes
vars:
ansible_facts_modules:
- setup
- ansible.builtin.setup
tasks:
- name: Use gathered facts
debug:
msg: "OS: {{ ansible_distribution }}"Fact Caching
# ansible.cfg
[defaults]
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/facts_cache
fact_caching_timeout = 86400Idempotency
Understanding Idempotency
Idempotency ensures that running the same task multiple times produces the same result without side effects.
Idempotent Example
- name: Ensure nginx is installed
apt:
name: nginx
state: present
become: yesThis task:
- Installs nginx if not present
- Does nothing if already installed
- Never attempts to reinstall
Non-Idempotent Commands
Avoid:
- name: Bad example
command: apt-get install nginxPrefer:
- name: Good example
apt:
name: nginx
state: presentBest Practices
1. Use Version Control
git init
git add .
git commit -m "Initial Ansible setup"2. Organize Playbooks
project/
├── inventory/
│ ├── production
│ └── staging
├── playbooks/
│ ├── web.yml
│ └── db.yml
├── roles/
│ ├── web/
│ └── db/
├── files/
├── templates/
└── ansible.cfg3. Use Inventory Groups
[webservers]
web1.example.com
web2.example.com
[dbservers]
db1.example.com
db2.example.com
[production:children]
webservers
dbservers4. Enable Verbosity for Debugging
ansible-playbook playbook.yml -v # Verbose
ansible-playbook playbook.yml -vv # More verbose
ansible-playbook playbook.yml -vvv # Debug5. Use Check Mode
ansible-playbook playbook.yml --check6. Run on Specific Hosts
ansible-playbook playbook.yml -l webservers
ansible-playbook playbook.yml -l web1.example.com7. Use Tags
ansible-playbook playbook.yml --tags "nginx,mysql"
ansible-playbook playbook.yml --skip-tags "debug"8. Enable Diff Output
ansible-playbook playbook.yml --diffCommon Tasks
System Updates
---
- name: Update all packages
hosts: all
become: yes
tasks:
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Upgrade all packages
apt:
upgrade: distUser Management
---
- name: Manage users
hosts: all
become: yes
tasks:
- name: Create user
user:
name: deploy
shell: /bin/bash
groups: sudo,docker
append: yes
- name: Add SSH key
authorized_key:
user: deploy
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"File Management
---
- name: Manage files
hosts: all
become: yes
tasks:
- name: Create directory
file:
path: /opt/myapp
state: directory
mode: '0755'
- name: Copy configuration
copy:
src: config.ini
dest: /opt/myapp/config.ini
mode: '0644'
- name: Create symlink
file:
src: /opt/myapp/config.ini
dest: /etc/myapp.conf
state: linkTroubleshooting
Common Issues
1. Connection Issues:
# Check SSH connection
ssh ubuntu@web1.example.com
# Verbose output
ansible webservers -m ping -vvv2. Permission Issues:
# Use become for privilege escalation
ansible-playbook playbook.yml -b
# Specify sudo user
ansible-playbook playbook.yml -b --become-user=root3. Python Issues:
# Specify Python interpreter
ansible-playbook playbook.yml -e "ansible_python_interpreter=/usr/bin/python3"Debug Mode
- name: Debug task
debug:
msg: "Variable value: {{ my_variable }}"
verbosity: 1Next Steps
Now that you understand Ansible basics, explore:
- Playbooks for complex automation
- Roles for reusability
- Ansible Galaxy for sharing
- Ansible Vault for secrets
- Advanced patterns and best practices
Ansible basics provide the foundation for automating your infrastructure efficiently and reliably.