Files
ansible/intro.md

438 lines
8.4 KiB
Markdown

# 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):
```ini
[webservers]
web1.example.com
web2.example.com
[databases]
db1.example.com
```
### Playbooks
YAML files describing desired state:
```yaml
- 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](https://ansible-navigator.readthedocs.io/en/stable/) 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
```bash
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
```bash
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):
```yaml
- 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:
```yaml
- 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:
```yaml
- 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:
```yaml
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:
```yaml
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:
```jinja2
# templates/nginx.conf.j2
server {
listen {{ nginx_port }};
server_name {{ domain_name }};
root {{ document_root }};
location / {
{% if enable_caching %}
expires {{ cache_duration }};
{% endif %}
}
}
```
```yaml
- name: Deploy nginx config
template:
src: nginx.conf.j2
dest: /etc/nginx/sites-available/default
```
## Ansible Vault
Encrypt sensitive data (passwords, keys, etc.):
```bash
# 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
```
```yaml
# site.yml
- name: Deploy infrastructure
hosts: webservers
roles:
- common
- nginx
- webapp
```
## Tags
Control which tasks run:
```yaml
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]
```
```bash
ansible-playbook site.yml --tags "install,configure"
ansible-playbook site.yml --skip-tags "deploy"
```
## Delegation
Run tasks on specific hosts:
```yaml
- 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:
```yaml
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:
```bash
ansible-playbook site.yml --check
ansible-playbook site.yml -C # shorthand
```
## Task Error Handling
Control task failure behavior:
```yaml
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:
```bash
# 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:
```bash
# AWS EC2
ansible-playbook -i ec2.py site.yml
# Kubernetes
ansible-playbook -i k8s.yml site.yml
```
```ini
# 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