Posted on
Scripting for DevOps

Using Bash Scripts to Automate Configuration Management with Ansible

Author
  • User
    Linux Bash
    Posts by this author
    Posts by this author

Automating configuration management with Ansible using Bash scripts can streamline your infrastructure management, ensuring consistency, scalability, and efficiency. This guide will walk you through integrating Bash with Ansible to automate various configuration tasks.


1. Introduction to Ansible and Bash Automation

Ansible is a powerful open-source automation tool used for configuration management, application deployment, and task automation. It uses playbooks, which are YAML files defining the desired state of your systems.

Bash, the Unix shell and command language, can be used to automate the execution of Ansible commands, manage environments, handle variables, and integrate Ansible with other tools and processes.

Combining Bash with Ansible leverages the strengths of both: Ansible’s robust automation capabilities and Bash’s flexibility in scripting and task orchestration.


2. Prerequisites

Before automating Ansible with Bash, ensure you have the following set up:

  1. Ansible Installed:

    sudo apt update
    sudo apt install ansible -y
    
  2. SSH Access: Ensure passwordless SSH access to your target machines is configured.

  3. Inventory File: Ansible uses an inventory file (/etc/ansible/hosts by default) to define the hosts it manages.

  4. Ansible Playbooks: Create or have existing playbooks ready for automation.

  5. Bash Environment: Access to a Unix-like terminal with Bash.


3. Basic Automation: Running Ansible Playbooks via Bash

Automate the execution of Ansible playbooks by encapsulating Ansible commands within Bash scripts.

Example Script: Run a Playbook

#!/bin/bash

# Variables
PLAYBOOK_PATH="/path/to/playbook.yml"
INVENTORY_FILE="/path/to/inventory.ini"
LOG_FILE="/var/log/ansible_run.log"

# Function to run the playbook
run_playbook() {
    echo "Starting Ansible playbook: $(date)" | tee -a "$LOG_FILE"
    ansible-playbook -i "$INVENTORY_FILE" "$PLAYBOOK_PATH" >> "$LOG_FILE" 2>&1

    if [ $? -eq 0 ]; then
        echo "Playbook executed successfully: $(date)" | tee -a "$LOG_FILE"
    else
        echo "Playbook execution failed: $(date)" | tee -a "$LOG_FILE"
        # Optionally, send an alert or take corrective action
    fi
}

# Execute the function
run_playbook

Explanation:

  • Variables: Define paths to your playbook, inventory, and log file.

  • Function run_playbook: Executes the playbook and logs output.

  • Error Handling: Checks the exit status and logs success or failure.

Usage:

  1. Save the script, e.g., run_ansible_playbook.sh.
  2. Make it executable: bash chmod +x run_ansible_playbook.sh
  3. Run the script: bash ./run_ansible_playbook.sh

4. Advanced Automation Techniques

4.1 Dynamic Inventory Management

Instead of static inventory files, use Bash to generate dynamic inventories based on current environments.

Example Script: Generate Dynamic Inventory and Run Playbook

#!/bin/bash

# Variables
DYNAMIC_INVENTORY_SCRIPT="/path/to/generate_inventory.sh"
PLAYBOOK_PATH="/path/to/playbook.yml"
LOG_FILE="/var/log/ansible_dynamic_run.log"

# Generate dynamic inventory
echo "Generating dynamic inventory: $(date)" | tee -a "$LOG_FILE"
"$DYNAMIC_INVENTORY_SCRIPT" > /tmp/dynamic_inventory.json

# Run the playbook with dynamic inventory
echo "Running playbook with dynamic inventory: $(date)" | tee -a "$LOG_FILE"
ansible-playbook -i /tmp/dynamic_inventory.json "$PLAYBOOK_PATH" >> "$LOG_FILE" 2>&1

# Check result
if [ $? -eq 0 ]; then
    echo "Dynamic playbook executed successfully: $(date)" | tee -a "$LOG_FILE"
else
    echo "Dynamic playbook execution failed: $(date)" | tee -a "$LOG_FILE"
    # Handle failure
fi

Explanation:

  • Dynamic Inventory Script: A separate script generates the inventory, which could pull data from cloud providers, databases, etc.

  • Integration: The generated inventory is used to run the playbook.

4.2 Handling Variables and Secrets

Use Bash to pass variables and manage secrets securely.

Example Script: Pass Variables to Playbook

#!/bin/bash

# Variables
PLAYBOOK_PATH="/path/to/playbook.yml"
INVENTORY_FILE="/path/to/inventory.ini"
LOG_FILE="/var/log/ansible_vars_run.log"
ENV_VAR1="value1"
ENV_VAR2="value2"

# Export sensitive variables securely
export ANSIBLE_VAULT_PASSWORD_FILE="/path/to/vault_password.txt"

# Run the playbook with extra variables
ansible-playbook -i "$INVENTORY_FILE" "$PLAYBOOK_PATH" \
    --extra-vars "var1=$ENV_VAR1 var2=$ENV_VAR2" \
    >> "$LOG_FILE" 2>&1

# Check result
if [ $? -eq 0 ]; then
    echo "Playbook with variables executed successfully: $(date)" | tee -a "$LOG_FILE"
else
    echo "Playbook execution with variables failed: $(date)" | tee -a "$LOG_FILE"
fi

Explanation:

  • Extra Variables: Pass variables using --extra-vars.

  • Secrets Management: Use Ansible Vault and reference the password file securely.

4.3 Logging and Reporting

Enhance scripts to provide detailed logs and generate reports.

Example Script: Enhanced Logging

#!/bin/bash

# Variables
PLAYBOOK_PATH="/path/to/playbook.yml"
INVENTORY_FILE="/path/to/inventory.ini"
LOG_DIR="/var/log/ansible"
LOG_FILE="$LOG_DIR/ansible_$(date +%F_%T).log"
REPORT_FILE="$LOG_DIR/report_$(date +%F).txt"

# Ensure log directory exists
mkdir -p "$LOG_DIR"

# Run the playbook with detailed logging
ansible-playbook -i "$INVENTORY_FILE" "$PLAYBOOK_PATH" | tee "$LOG_FILE"

# Generate a summary report
echo "Ansible Playbook Execution Report - $(date)" > "$REPORT_FILE"
echo "----------------------------------------" >> "$REPORT_FILE"
if grep -q "failed=" "$LOG_FILE"; then
    echo "Some tasks failed. Check the log for details." >> "$REPORT_FILE"
else
    echo "All tasks executed successfully." >> "$REPORT_FILE"
fi

Explanation:

  • Timestamped Logs: Each execution logs to a unique file with a timestamp.

  • Report Generation: Parses logs to create a simple success/failure report.


5. Example Scripts

5.1 Automate Deployment

Deploy an application by running Ansible playbooks via Bash.

#!/bin/bash

# Variables
DEPLOY_PLAYBOOK="/playbooks/deploy_app.yml"
INVENTORY="/inventory/production.ini"
LOG_FILE="/logs/deploy_app_$(date +%F).log"

# Function to deploy application
deploy_application() {
    echo "Starting deployment: $(date)" | tee -a "$LOG_FILE"
    ansible-playbook -i "$INVENTORY" "$DEPLOY_PLAYBOOK" >> "$LOG_FILE" 2>&1

    if [ $? -eq 0 ]; then
        echo "Deployment succeeded: $(date)" | tee -a "$LOG_FILE"
        # Optionally, notify stakeholders
    else
        echo "Deployment failed: $(date)" | tee -a "$LOG_FILE"
        # Optionally, trigger rollback or alert
    fi
}

# Execute deployment
deploy_application

5.2 Backup Configuration Files

Use Ansible to backup configuration files and automate the process with Bash.

#!/bin/bash

# Variables
BACKUP_PLAYBOOK="/playbooks/backup_configs.yml"
INVENTORY="/inventory/backup_hosts.ini"
BACKUP_DIR="/backups/$(date +%F)"
LOG_FILE="/logs/backup_configs_$(date +%F).log"

# Create backup directory
mkdir -p "$BACKUP_DIR"

# Run the backup playbook with a specific variable
ansible-playbook -i "$INVENTORY" "$BACKUP_PLAYBOOK" \
    --extra-vars "backup_dir=$BACKUP_DIR" \
    >> "$LOG_FILE" 2>&1

# Check result
if [ $? -eq 0 ]; then
    echo "Backup completed successfully: $(date)" | tee -a "$LOG_FILE"
else
    echo "Backup failed: $(date)" | tee -a "$LOG_FILE"
    # Handle failure
fi

6. Integrating with Version Control

Ensure your Bash scripts and Ansible playbooks are version-controlled using Git.

Example Workflow:

  1. Initialize Git Repository:

    cd /path/to/your/scripts
    git init
    git add .
    git commit -m "Initial commit of Ansible automation scripts"
    
  2. Push to Remote Repository:

    git remote add origin https://github.com/yourusername/ansible-automation.git
    git push -u origin master
    
  3. Automate Deployment on Git Push: Use webhooks or CI/CD tools to trigger Bash scripts when changes are pushed.


7. Scheduling with Cron

Automate the execution of your Bash-Ansible scripts using cron for regular tasks.

Example: Schedule a Daily Deployment Script

  1. Edit Crontab:

    crontab -e
    
  2. Add Cron Job:

    0 2 * * * /path/to/run_ansible_playbook.sh >> /var/log/cron_ansible.log 2>&1
    
    • This schedules the script to run daily at 2 AM.

Tips:

  • Environment Variables: Ensure the script has access to necessary environment variables or source them within the script.

  • Logging: Direct cron job outputs to log files for monitoring.


8. Best Practices

  1. Modular Scripts: Break down scripts into reusable functions for better maintenance.
  2. Error Handling: Implement robust error checking and handling to manage failures gracefully.
  3. Secure Credentials:
    • Use Ansible Vault for sensitive data.
    • Restrict access to scripts and log files.
  4. Logging and Monitoring:
    • Maintain detailed logs for auditing and troubleshooting.
    • Integrate with monitoring tools to track script executions.
  5. Idempotency: Ensure Ansible playbooks are idempotent to prevent unintended side effects.
  6. Version Control: Keep all scripts and playbooks under version control for tracking changes and collaboration.
  7. Documentation: Document scripts and playbooks for clarity and ease of use.
  8. Testing:
    • Test scripts in staging environments before production.
    • Use Ansible’s --check mode to preview changes.
  9. Use Absolute Paths: Avoid issues with relative paths by using absolute paths in scripts.
  10. Scheduling Considerations:
    • Avoid overlapping executions.
    • Use locking mechanisms if necessary.

9. Example: Comprehensive Automation Script

Here’s a more comprehensive example that includes environment setup, running a playbook, error handling, and notifications.

#!/bin/bash

# Variables
PLAYBOOK_PATH="/playbooks/deploy_app.yml"
INVENTORY_FILE="/inventory/production.ini"
LOG_DIR="/var/log/ansible"
LOG_FILE="$LOG_DIR/deploy_$(date +%F_%T).log"
NOTIFY_EMAIL="admin@example.com"

# Ensure log directory exists
mkdir -p "$LOG_DIR"

# Function to send email notifications
send_notification() {
    local subject=$1
    local message=$2
    echo "$message" | mail -s "$subject" "$NOTIFY_EMAIL"
}

# Function to run the playbook
run_playbook() {
    echo "Executing Ansible playbook: $(date)" | tee -a "$LOG_FILE"
    ansible-playbook -i "$INVENTORY_FILE" "$PLAYBOOK_PATH" >> "$LOG_FILE" 2>&1

    return $?
}

# Execute the playbook
run_playbook
RESULT=$?

# Check the result and notify
if [ $RESULT -eq 0 ]; then
    echo "Playbook executed successfully." | tee -a "$LOG_FILE"
    send_notification "Ansible Deployment Success" "The deployment playbook ran successfully on $(hostname) at $(date)."
else
    echo "Playbook execution failed." | tee -a "$LOG_FILE"
    send_notification "Ansible Deployment Failure" "The deployment playbook failed on $(hostname) at $(date). Check the logs at $LOG_FILE for details."
    # Optionally, exit or trigger remediation
    exit 1
fi

Explanation:

  • Notification Function: Sends email alerts based on the execution outcome.

  • Comprehensive Logging: Logs all activities and outcomes.

  • Error Handling: Differentiates between success and failure, taking appropriate actions.


10. Conclusion

Automating configuration management with Ansible using Bash scripts enhances your ability to manage infrastructure efficiently. By leveraging Bash’s scripting capabilities alongside Ansible’s powerful automation features, you can create robust, scalable, and maintainable automation workflows.

Next Steps:

  • Explore Ansible Roles and Modules: Enhance your playbooks with reusable roles and modules.

  • Integrate with CI/CD Pipelines: Incorporate your Bash-Ansible scripts into continuous integration and deployment workflows.

  • Leverage Advanced Ansible Features: Utilize features like conditionals, loops, and handlers for more complex automation tasks.

  • Stay Updated: Regularly update your scripts and playbooks to adapt to evolving infrastructure requirements and best practices.

If you need a detailed script for a specific use case or further assistance, feel free to ask!