Master Ansible Automation: From Beginner to Expert with a Complete Project Walkthrough
This comprehensive guide walks you through every aspect of Ansible configuration automation—from basic concepts and installation on various Linux distributions to advanced topics like inventory management, playbook design, modules, roles, Vault encryption, CI/CD integration, troubleshooting, security hardening, and real‑world enterprise deployment examples—equipping you to become an Ansible expert.
From Zero to Expert: Ansible Configuration Automation Full Guide (with Complete Project Example)
1. Introduction
In modern IT operations, configuration management automation is essential for improving efficiency, ensuring consistency, and reducing human error. Ansible, an open‑source configuration management tool, is popular among ops engineers because it is simple to use and agent‑less. This article provides a complete overview of Ansible automation, covering basic concepts to advanced usage, helping engineers master this powerful tool.
2. Ansible Basics
2.1 What is Ansible?
Ansible is an open‑source automation platform for configuration management, application deployment, task automation, and IT orchestration. It uses a agent‑less architecture, connects to target hosts via SSH, and defines playbooks in YAML, offering low learning cost and simple deployment.
2.2 Core Components
Control Node
Machine where Ansible is installed
Executes playbooks and ad‑hoc commands
Manages the inventory file
Managed Node
Target machines managed by Ansible
SSH service must be enabled
Usually requires a Python environment
Inventory
Defines the list of managed hosts
Supports static and dynamic inventories
Allows host and group variables
Playbook
YAML configuration files
Describe the execution flow of automation tasks
Contain one or more plays
Module
Execution units of Ansible
Perform specific task operations
Include thousands of built‑in modules
Plugin
Components that extend Ansible functionality
Include connection plugins, filter plugins, etc.
3. Installation and Configuration
3.1 Install Ansible
CentOS/RHEL
# Use EPEL repository
yum install epel-release -y
yum install ansible -y
# Or install via pip
pip install ansibleUbuntu/Debian
# Add PPA repository
sudo apt-add-repository ppa:ansible/ansible
sudo apt update
sudo apt install ansible -y
# Or install via pip
pip install ansibleVerify Installation
ansible --version3.2 Configuration File Structure
Ansible searches for configuration files in the following order: $ANSIBLE_CONFIG environment variable ansible.cfg in the current directory ~/.ansible.cfg in the user’s home directory /etc/ansible/ansible.cfg system configuration file
Key configuration items (example):
[defaults]
# Default inventory file path
inventory = /etc/ansible/hosts
# Remote user
remote_user = root
# SSH private key
private_key_file = ~/.ssh/id_rsa
# Disable host key checking
host_key_checking = False
# Number of parallel forks
forks = 20
# Timeout (seconds)
timeout = 30
# Log file
log_path = /var/log/ansible.log
[ssh_connection]
# SSH arguments
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
# Enable pipelining
pipelining = True4. Inventory Management
4.1 Static Inventory
Basic Format
# Single host
web1.example.com
# Host group
[webservers]
web1.example.com
web2.example.com
web3.example.com
[databases]
db1.example.com
db2.example.com
# Host variables
[webservers]
web1.example.com http_port=80 maxRequestsPerChild=808
web2.example.com http_port=8080 maxRequestsPerChild=909
# Group variables
[webservers:vars]
ntp_server=ntp.example.com
proxy=proxy.example.com4.2 Host Ranges
# Numeric range
[webservers]
web[01:50].example.com
# Alphabetic range
[databases]
db[a:f].example.com
# Multiple ranges
[servers]
server[01:20][1:3].example4.3 Dynamic Inventory
Example: AWS EC2 dynamic inventory script (Python)
#!/usr/bin/env python3
import boto3, json
def get_ec2_instances():
ec2 = boto3.client('ec2')
response = ec2.describe_instances()
inventory = {
'_meta': {'hostvars': {}},
'all': {'hosts': []},
'webservers': {'hosts': []},
'databases': {'hosts': []}
}
for reservation in response['Reservations']:
for instance in reservation['Instances']:
if instance['State']['Name'] == 'running':
public_ip = instance.get('PublicIpAddress')
if public_ip:
inventory['all']['hosts'].append(public_ip)
for tag in instance.get('Tags', []):
if tag['Key'] == 'Role':
role = tag['Value']
if role not in inventory:
inventory[role] = {'hosts': []}
inventory[role]['hosts'].append(public_ip)
return inventory
if __name__ == '__main__':
print(json.dumps(get_ec2_instances(), indent=2))5. Ad‑hoc Commands
5.1 Basic Syntax
ansible <pattern> -m <module> -a <arguments>5.2 Common Ad‑hoc Commands
Execute Shell Command
# Run on all hosts
ansible all -m shell -a "uptime"
# Run on a specific group
ansible webservers -m shell -a "systemctl status nginx"
# Use sudo privileges
ansible all -m shell -a "systemctl restart nginx" --becomeFile Operations
# Copy file
ansible all -m copy -a "src=/tmp/test.txt dest=/tmp/test.txt"
# Create directory
ansible all -m file -a "path=/tmp/testdir state=directory"
# Change file permissions
ansible all -m file -a "path=/tmp/test.txt mode=0644"Package Management
# Install package
ansible all -m yum -a "name=nginx state=present"
# Remove package
ansible all -m yum -a "name=nginx state=absent"
# Update all packages
ansible all -m yum -a "name=* state=latest"Service Management
# Start service
ansible all -m service -a "name=nginx state=started"
# Stop service
ansible all -m service -a "name=nginx state=stopped"
# Restart service
ansible all -m service -a "name=nginx state=restarted"6. Writing Playbooks
6.1 Basic Structure
---
- name: Configure Web Server
hosts: webservers
become: yes
vars:
http_port: 80
max_clients: 200
tasks:
- name: Install Nginx
yum:
name: nginx
state: present
- name: Start Nginx service
service:
name: nginx
state: started
enabled: yes6.2 Using Variables
---
- name: Variable Example
hosts: all
vars:
packages:
- nginx
- mysql
- php
user_info:
name: webapp
group: webapp
shell: /bin/bash
tasks:
- name: Install packages
yum:
name: "{{ packages }}"
state: present
- name: Create user
user:
name: "{{ user_info.name }}"
group: "{{ user_info.group }}"
shell: "{{ user_info.shell }}"6.3 Conditional Execution
---
- name: Conditional Example
hosts: all
tasks:
- name: Install Apache on RedHat
yum:
name: httpd
state: present
when: ansible_os_family == "RedHat"
- name: Install Apache on Debian
apt:
name: apache2
state: present
when: ansible_os_family == "Debian"
- name: Check disk space
shell: df -h /
register: disk_usage
- name: Warn if disk usage > 90%
debug:
msg: "Disk space low, please clean up"
when: "'90%' in disk_usage.stdout"6.4 Loops
---
- name: Loop Example
hosts: all
tasks:
- name: Install multiple packages
yum:
name: "{{ item }}"
state: present
loop:
- nginx
- mysql
- php
- redis
- name: Create multiple users
user:
name: "{{ item.name }}"
group: "{{ item.group }}"
state: present
loop:
- { name: 'user1', group: 'web' }
- { name: 'user2', group: 'db' }
- { name: 'user3', group: 'app' }
- name: Process dictionary loop
debug:
msg: "{{ item.key }}: {{ item.value }}"
loop: "{{ lookup('dict', {'a': 1, 'b': 2, 'c': 3}) }}"6.5 Error Handling
---
- name: Error Handling Example
hosts: all
tasks:
- name: Try to start service
service:
name: nginx
state: started
ignore_errors: yes
- name: Capture command error
shell: /bin/false
register: result
failed_when: result.rc != 0
ignore_errors: yes
- name: Act on error result
debug:
msg: "Command failed"
when: result.failed
- name: Rescue block
block:
- name: Potentially failing task
shell: /bin/false
rescue:
- name: Rescue task
debug:
msg: "Rescue operation executed"
always:
- name: Always run task
debug:
msg: "This runs regardless of success or failure"7. Module Details
7.1 System Modules
User Module
- name: Create user
user:
name: webapp
group: webapp
shell: /bin/bash
home: /home/webapp
createhome: yes
password: "{{ 'password' | password_hash('sha512') }}"Group Module
- name: Create group
group:
name: webapp
gid: 1001
state: presentCron Module
- name: Add scheduled task
cron:
name: "backup database"
minute: "0"
hour: "2"
job: "/usr/local/bin/backup.sh"
user: root7.2 File Modules
File Module
- name: Create directory
file:
path: /var/www/html
state: directory
owner: nginx
group: nginx
mode: '0755'
- name: Create symbolic link
file:
src: /var/www/html
dest: /var/www/site
state: linkCopy Module
- name: Copy file
copy:
src: /tmp/source.txt
dest: /tmp/dest.txt
owner: root
group: root
mode: '0644'
backup: yesTemplate Module
- name: Generate configuration file
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: '0644'
notify: restart nginx7.3 Package Modules
Yum Module
- name: Install packages with yum
yum:
name:
- nginx
- mysql-server
- php
state: present
update_cache: yes
- name: Install specific version
yum:
name: nginx-1.18.0
state: presentApt Module
- name: Update apt cache
apt:
update_cache: yes
cache_valid_time: 3600
- name: Install packages with apt
apt:
name: "{{ packages }}"
state: present
vars:
packages:
- nginx
- mysql-server
- php7.4 Service Modules
Service Module
- name: Start and enable service
service:
name: nginx
state: started
enabled: yesSystemd Module
- name: Reload systemd
systemd:
daemon_reload: yes
- name: Start service via systemd
systemd:
name: nginx
state: started
enabled: yes8. Templates and Filters
8.1 Jinja2 Templates
Example nginx.conf.j2:
# nginx.conf.j2
user {{ nginx_user }};
worker_processes {{ ansible_processor_cores }};
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections {{ nginx_worker_connections }};
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
{% for upstream in nginx_upstreams %}
upstream {{ upstream.name }} {
{% for server in upstream.servers %}
server {{ server }};
{% endfor %}
}
{% endfor %}
server {
listen {{ http_port }};
server_name {{ server_name }};
location / {
root {{ document_root }};
index index.html index.htm;
}
}
}8.2 Common Filters
---
- name: Filter examples
hosts: all
vars:
items: [1, 2, 3, 4, 5]
text: "Hello World"
tasks:
- name: Max value filter
debug:
msg: "{{ items | max }}" # 5
- name: Lowercase filter
debug:
msg: "{{ text | lower }}" # hello world
- name: Default value filter
debug:
msg: "{{ undefined_var | default('default_value') }}"
- name: Password hash filter
debug:
msg: "{{ 'password' | password_hash('sha512') }}"
- name: DateTime filter
debug:
msg: "{{ ansible_date_time.iso8601 | to_datetime }}"9. Handlers and Notifications
9.1 Basic Handler Usage
---
- name: Web server configuration
hosts: webservers
tasks:
- name: Install Nginx
yum:
name: nginx
state: present
- name: Configure Nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify:
- restart nginx
- reload nginx
- name: Ensure Nginx is running
service:
name: nginx
state: started
enabled: yes
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
- name: reload nginx
service:
name: nginx
state: reloaded9.2 Conditional Handlers
---
- name: Conditional handler example
hosts: all
tasks:
- name: Check configuration file existence
stat:
path: /etc/nginx/nginx.conf
register: nginx_config
- name: Update configuration if it exists
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
when: nginx_config.stat.exists
notify: restart nginx
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
when: nginx_config.stat.exists10. Roles
10.1 Role Structure
roles/
└── nginx/
├── tasks/
│ └── main.yml
├── handlers/
│ └── main.yml
├── templates/
│ └── nginx.conf.j2
├── files/
│ └── index.html
├── vars/
│ └── main.yml
├── defaults/
│ └── main.yml
├── meta/
│ └── main.yml
└── README.md10.2 Creating a Role
tasks/main.yml
---
- name: Install Nginx
yum:
name: nginx
state: present
- name: Create configuration file
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart nginx
- name: Start Nginx service
service:
name: nginx
state: started
enabled: yeshandlers/main.yml
---
- name: restart nginx
service:
name: nginx
state: restarteddefaults/main.yml
---
nginx_user: nginx
nginx_worker_connections: 1024
http_port: 80
document_root: /usr/share/nginx/htmlmeta/main.yml
---
galaxy_info:
author: your-name
description: Nginx web server role
company: your-company
license: MIT
min_ansible_version: 2.9
platforms:
- name: EL
versions:
- 7
- 8
- name: Ubuntu
versions:
- 18.04
- 20.04
dependencies: []10.3 Using a Role
---
- name: Deploy web servers
hosts: webservers
roles:
- nginx
- mysql
- php
# Passing variables to a role
- name: Deploy web servers with custom vars
hosts: webservers
roles:
- role: nginx
nginx_user: www-data
http_port: 808011. Vault Encryption
11.1 Creating Encrypted Files
# Create encrypted file
ansible-vault create secret.yml
# Edit encrypted file
ansible-vault edit secret.yml
# View encrypted file
ansible-vault view secret.yml
# Encrypt existing file
ansible-vault encrypt existing_file.yml
# Decrypt file
ansible-vault decrypt secret.yml11.2 Using Encrypted Variables
Example vault.yml (encrypted):
---
vault_database_password: secretpassword123
vault_api_key: abc123def456Reference in a playbook:
---
- name: Use encrypted variables
hosts: databases
vars_files:
- vault.yml
tasks:
- name: Create database user
mysql_user:
name: myapp
password: "{{ vault_database_password }}"
priv: "myapp.*:ALL"
state: presentRun with vault password:
ansible-playbook -i inventory site.yml --ask-vault-pass
# Or use a password file
ansible-playbook -i inventory site.yml --vault-password-file ~/.vault_pass12. Advanced Features
12.1 Strategy Control
---
- name: Strategy control example
hosts: all
strategy: free # Free strategy, each host runs independently
tasks:
- name: Long‑running task
shell: sleep 30
- name: Quick task
debug:
msg: "This task finishes quickly"12.2 Delegation and Proxy
---
- name: Delegated execution example
hosts: webservers
tasks:
- name: Check service status on monitoring server
uri:
url: "http://{{ inventory_hostname }}/health"
method: GET
delegate_to: monitor.example.com
- name: Run command locally
shell: echo "Running on control node"
delegate_to: localhost
run_once: true12.3 Rolling Updates
---
- name: Rolling update example
hosts: webservers
serial: 2 # Update two servers at a time
tasks:
- name: Remove from load balancer
uri:
url: "http://lb.example.com/remove/{{ inventory_hostname }}"
method: POST
delegate_to: localhost
- name: Update application
yum:
name: myapp
state: latest
notify: restart myapp
- name: Wait for service to start
wait_for:
port: 8080
delay: 10
- name: Add back to load balancer
uri:
url: "http://lb.example.com/add/{{ inventory_hostname }}"
method: POST
delegate_to: localhost
handlers:
- name: restart myapp
service:
name: myapp
state: restarted12.4 Asynchronous Tasks
---
- name: Asynchronous task example
hosts: all
tasks:
- name: Long‑running task
shell: /opt/long_running_script.sh
async: 3600 # Max runtime (seconds)
poll: 0 # Do not wait for result
register: long_task
- name: Continue with other tasks
debug:
msg: "Continuing with other tasks"
- name: Check async task status
async_status:
jid: "{{ long_task.ansible_job_id }}"
register: job_result
until: job_result.finished
retries: 30
delay: 1013. Best Practices
13.1 Directory Structure
ansible-project/
├── inventories/
│ ├── production/
│ │ ├── hosts
│ │ └── group_vars/
│ └── staging/
│ ├── hosts
│ └── group_vars/
├── roles/
│ ├── common/
│ ├── nginx/
│ └── mysql/
├── playbooks/
│ ├── site.yml
│ ├── webservers.yml
│ └── databases.yml
├── group_vars/
│ └── all.yml
├── host_vars/
├── vault/
│ └── secrets.yml
├── files/
├── templates/
├── library/
├── filter_plugins/
└── ansible.cfg13.2 Naming Conventions
---
# Use descriptive names
- name: Install and configure Nginx web server
hosts: webservers
tasks:
- name: Install Nginx package
yum:
name: nginx
state: present
- name: Create Nginx configuration file
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
notify: restart Nginx service
- name: Start and enable Nginx service
service:
name: nginx
state: started
enabled: yes
handlers:
- name: restart Nginx service
service:
name: nginx
state: restarted13.3 Variable Management
# Use clear variable hierarchy
nginx_config:
user: nginx
worker_processes: auto
worker_connections: 1024
keepalive_timeout: 65
server:
listen: 80
server_name: example.com
root: /var/www/html
index: index.html
upstream:
name: backend
servers:
- 192.168.1.10:8080
- 192.168.1.11:808013.4 Error Handling
---
- name: Robust error handling
hosts: all
tasks:
- name: Verify system requirements
assert:
that:
- ansible_distribution_major_version|int >= 7
- ansible_memtotal_mb >= 1024
fail_msg: "System does not meet minimum requirements"
- name: Backup configuration file
copy:
src: /etc/nginx/nginx.conf
dest: /etc/nginx/nginx.conf.bak
remote_src: yes
ignore_errors: yes
- name: Update configuration
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
validate: nginx -t -c %s
notify: restart nginx14. Monitoring and Logging
14.1 Log Configuration
# ansible.cfg
[defaults]
log_path = /var/log/ansible.log
display_skipped_hosts = False
display_ok_hosts = False14.2 Callback Plugins
# callback_plugins/timer.py
from ansible.plugins.callback import CallbackBase
from datetime import datetime
class CallbackModule(CallbackBase):
def __init__(self):
super(CallbackModule, self).__init__()
self.start_time = datetime.now()
def v2_playbook_on_task_start(self, task, is_conditional):
self.task_start_time = datetime.now()
def v2_runner_on_ok(self, result):
duration = datetime.now() - self.task_start_time
self._display.display(f"Task completed in {duration.total_seconds():.2f}s")14.3 Performance Monitoring
---
- name: Performance monitoring example
hosts: all
tasks:
- name: Gather system information
setup:
gather_subset:
- hardware
- network
- virtual
- name: Record performance metrics
debug:
msg: |
CPU cores: {{ ansible_processor_cores }}
Memory: {{ ansible_memtotal_mb }}MB
Root disk free: {{ ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first }}15. CI/CD Integration
15.1 GitLab CI Integration
# .gitlab-ci.yml
stages:
- test
- deploy
ansible-lint:
stage: test
script:
- ansible-lint playbooks/site.yml
only:
- merge_requests
deploy-staging:
stage: deploy
script:
- ansible-playbook -i inventories/staging/hosts playbooks/site.yml --vault-password-file $VAULT_PASSWORD_FILE
environment:
name: staging
url: https://staging.example.com
only:
- develop
deploy-production:
stage: deploy
script:
- ansible-playbook -i inventories/production/hosts playbooks/site.yml --vault-password-file $VAULT_PASSWORD_FILE
environment:
name: production
url: https://production.example.com
when: manual
only:
- master15.2 Jenkins Integration
// Jenkinsfile
pipeline {
agent any
environment {
ANSIBLE_HOST_KEY_CHECKING = 'False'
VAULT_PASSWORD_FILE = credentials('ansible-vault-password')
}
stages {
stage('Checkout') {
steps { checkout scm }
}
stage('Syntax Check') {
steps { sh 'ansible-playbook --syntax-check playbooks/site.yml' }
}
stage('Lint') {
steps { sh 'ansible-lint playbooks/site.yml' }
}
stage('Deploy Staging') {
steps {
sh '''ansible-playbook -i inventories/staging/hosts playbooks/site.yml --vault-password-file $VAULT_PASSWORD_FILE'''
}
}
stage('Deploy Production') {
when { branch 'master' }
steps {
input message: 'Deploy to Production?'
sh '''ansible-playbook -i inventories/production/hosts playbooks/site.yml --vault-password-file $VAULT_PASSWORD_FILE'''
}
}
}
post {
always { archiveArtifacts artifacts: 'logs/*.log', allowEmptyArchive: true }
failure { emailext subject: "Ansible Deployment Failed: ${env.JOB_NAME} - ${env.BUILD_NUMBER}", body: "Build failed. Check console output at ${env.BUILD_URL}", to: "${env.CHANGE_AUTHOR_EMAIL}" }
}
}15.3 GitHub Actions Integration
# .github/workflows/deploy.yml
name: Deploy with Ansible
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.8'
- name: Install dependencies
run: |
pip install ansible ansible-lint
- name: Run ansible-lint
run: ansible-lint playbooks/site.yml
- name: Syntax check
run: ansible-playbook --syntax-check playbooks/site.yml
deploy-staging:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/develop'
steps:
- uses: actions/checkout@v2
- name: Deploy to Staging
env:
ANSIBLE_HOST_KEY_CHECKING: False
VAULT_PASSWORD: ${{ secrets.VAULT_PASSWORD }}
run: |
echo "$VAULT_PASSWORD" > .vault_pass
ansible-playbook -i inventories/staging/hosts playbooks/site.yml --vault-password-file .vault_pass
rm .vault_pass
deploy-production:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/checkout@v2
- name: Deploy to Production
env:
ANSIBLE_HOST_KEY_CHECKING: False
VAULT_PASSWORD: ${{ secrets.VAULT_PASSWORD }}
run: |
echo "$VAULT_PASSWORD" > .vault_pass
ansible-playbook -i inventories/production/hosts playbooks/site.yml --vault-password-file .vault_pass
rm .vault_pass16. Troubleshooting
16.1 Common Issues and Solutions
SSH Connection Problems
# Test SSH connectivity
ansible all -m ping
# Verbose output
ansible all -m ping -vvv
# Disable host key checking
export ANSIBLE_HOST_KEY_CHECKING=FalsePermission Issues
# Use sudo
ansible all -m shell -a "systemctl status nginx" --become
# Specify sudo user
ansible all -m shell -a "systemctl status nginx" --become-user=rootMissing Modules
# Check module availability
ansible-doc -l | grep module_name
# Install required Python module
pip install required_module16.2 Debugging Tips
---
- name: Debug example
hosts: all
tasks:
- name: Gather facts
setup:
register: facts
- name: Show variable content
debug:
var: facts
verbosity: 2
- name: Conditional debug
debug:
msg: "Disk space low"
when: ansible_mounts | selectattr('mount', 'equalto', '/') | map(attribute='size_available') | first < 1000000000
- name: Pause execution
pause:
prompt: "Check system status and press Enter to continue"
when: debug_mode | default(false)16.3 Performance Optimization
# ansible.cfg optimization
[defaults]
forks = 50 # Increase parallelism
#gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts_cache
fact_caching_timeout = 3600
[ssh_connection]
pipelining = True
ssh_args = -o ControlMaster=auto -o ControlPersist=300s
control_path = /tmp/ansible-ssh-%%h-%%p-%%r17. Security Considerations
17.1 Access Control
---
- name: Security configuration example
hosts: all
become: yes
become_method: sudo
tasks:
- name: Create dedicated user
user:
name: ansible
groups: wheel
shell: /bin/bash
create_home: yes
- name: Configure sudo privileges
lineinfile:
path: /etc/sudoers.d/ansible
line: 'ansible ALL=(ALL) NOPASSWD: ALL'
create: yes
validate: 'visudo -cf %s'
- name: Configure SSH key for ansible user
authorized_key:
user: ansible
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
state: present17.2 Protecting Sensitive Information
---
- name: Sensitive data handling
hosts: all
vars:
sensitive_data: "{{ vault_sensitive_data }}"
tasks:
- name: Use sensitive data
shell: echo "{{ sensitive_data }}"
no_log: true # Prevent logging of sensitive data
- name: Handle password securely
user:
name: dbuser
password: "{{ vault_db_password | password_hash('sha512') }}"
no_log: true17.3 Network Security
---
- name: Network security configuration
hosts: all
tasks:
- name: Configure firewall (firewalld)
firewalld:
service: "{{ item }}"
permanent: yes
state: enabled
immediate: yes
loop:
- ssh
- http
- https
- name: Restrict SSH password authentication
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication no'
notify: restart sshd
- name: Configure SELinux
selinux:
policy: targeted
state: enforcing
handlers:
- name: restart sshd
service:
name: sshd
state: restarted18. Enterprise Deployment Cases
18.1 LAMP Stack Automation
---
- name: Deploy LAMP stack
hosts: webservers
become: yes
vars:
mysql_root_password: "{{ vault_mysql_root_password }}"
app_user: webapp
app_group: webapp
roles:
- common
- apache
- mysql
- php
- application
post_tasks:
- name: Verify deployment
uri:
url: "http://{{ inventory_hostname }}/health"
method: GET
status_code: 200
delegate_to: localhost18.2 Docker Container Deployment
---
- name: Docker container deployment
hosts: docker_hosts
become: yes
tasks:
- name: Install Docker
yum:
name: docker
state: present
- name: Start Docker service
service:
name: docker
state: started
enabled: yes
- name: Pull application image
docker_image:
name: "{{ app_image }}"
tag: "{{ app_version }}"
source: pull
- name: Deploy application container
docker_container:
name: "{{ app_name }}"
image: "{{ app_image }}:{{ app_version }}"
state: started
restart_policy: always
ports:
- "80:8080"
env:
DB_HOST: "{{ db_host }}"
DB_PASSWORD: "{{ vault_db_password }}"
- name: Wait for application to start
wait_for:
port: 80
delay: 10
timeout: 6018.3 Kubernetes Cluster Deployment
---
- name: Deploy Kubernetes cluster
hosts: k8s_masters
become: yes
tasks:
- name: Initialize cluster
shell: kubeadm init --pod-network-cidr=10.244.0.0/16
register: kubeadm_init
run_once: true
- name: Save join command
set_fact:
join_command: "{{ kubeadm_init.stdout_lines | select('match', 'kubeadm join.*') | first }}"
run_once: true
- name: Configure kubectl for root
shell: |
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
run_once: true
- name: Deploy flannel network plugin
shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
run_once: true
- name: Join worker nodes
hosts: k8s_workers
become: yes
tasks:
- name: Join cluster
shell: "{{ hostvars[groups['k8s_masters'][0]]['join_command'] }}"19. Summary
Ansible is a vital tool for modern IT infrastructure automation, offering simplicity, agent‑less operation, a rich module ecosystem, and strong extensibility. It scales from small scripts to enterprise‑level deployments, integrates smoothly with CI/CD pipelines, and supports advanced features like roles, Vault, and strategy control.
To master Ansible, engineers should follow these steps:
Fundamental Learning : Understand core concepts, modules, and playbook syntax.
Practical Application : Start with simple system configuration and progress to multi‑tier architecture automation.
Best Practices : Adopt naming conventions, directory structures, and security hardening.
Advanced Features : Explore roles, Vault, strategy control, and asynchronous tasks.
Integration and Optimization : Embed Ansible into existing DevOps workflows for end‑to‑end automation.
By adhering to these guidelines and leveraging the comprehensive examples provided, ops engineers can significantly improve efficiency, reduce manual errors, and advance their careers toward high‑value SRE/DevOps positions.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Ops Community
A leading IT operations community where professionals share and grow together.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
