438 lines
8.4 KiB
Markdown
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
|