Day 64 of 90 Days of DevOps Challenge: Ansible Vault & Roles


On Day 63, I deepened my Ansible knowledge by exploring Handlers, Tags, and Variables, which enabled me to build smarter and more efficient automation playbooks. I learned to trigger tasks conditionally using Handlers, execute specific tasks selectively with Tags, and dynamically manage playbooks using different types of Variables such as Runtime, Playbook, Group, and Host variables.
Today, I focused on enhancing automation security using Ansible Vault and organizing playbooks more effectively through Ansible Roles for better structure and modularity.
Ansible Vault
In any infrastructure automation workflow, protecting sensitive information, such as passwords, API keys, and certificates, is essential.
Ansible Vault provides a way to secure playbooks, variables, and files by encrypting them, ensuring that confidential data remains protected even when stored in version control systems like Git.
What Can You Encrypt with Ansible Vault?
Entire playbooks
Variable files containing secrets
Sensitive strings or data blocks within files
How It Works
Encryption: Converts data from a readable format to an unreadable, encrypted format.
Decryption: Converts the encrypted data back to its original, readable form when needed.
This mechanism allows automation workflows to remain secure, auditable, and compliant, especially in production environments.
Vault Key Operations
# Encrypt a file
ansible-vault encrypt file.yml
# Decrypt a file
ansible-vault decrypt file.yml
# View encrypted content
ansible-vault view file.yml
# Edit encrypted content
ansible-vault edit file.yml
# Execute encrypted playbook
ansible-playbook file.yml --ask-vault-pass
# Encrypting Strings
ansible-vault encrypt_string 'mysecretpassword' --name 'db_password'
Best Practices
Never store your vault password file in version control.
Regularly rotate vault passwords.
Use vault IDs for managing multiple environments (e.g., staging, production).
Ansible Roles:
As Ansible playbooks grow with more tasks and functionalities, they can become lengthy, complex, and difficult to maintain. To address this challenge, Ansible Roles provide a solution by breaking down large playbooks into smaller, organized, and reusable components.
Roles help structure configurations in a modular format, offering abstraction that enhances readability, scalability, and collaboration across teams.
Why Use Ansible Roles?
Reusability: Easily reuse roles across different projects and environments.
Improved Readability: Clear separation of tasks, variables, handlers, and templates improves code clarity.
Maintainability: Easier to debug, test, and update specific components without affecting the entire playbook.
Team Collaboration: Roles allow teams to work on different parts of infrastructure code independently.
Best Practices: Encourages standardized playbook design aligned with Ansible community conventions.
By adopting roles, automation becomes more scalable, maintainable, and production-ready, especially in complex infrastructure setups.
Implementing Ansible Roles:
To better manage and scale Ansible playbooks, breaking them into Roles is an effective strategy. For example, consider the following monolithic playbook used to install and configure Apache:
---
- hosts: webservers
become: true # Use sudo privileges
tasks:
- name: Install httpd package
yum:
name: httpd
state: latest
- name: Copy index.html file
copy:
src: index.html
dest: /var/www/html/index.html
- name: Start httpd service
service:
name: httpd
state: started
Managing and maintaining such playbooks can get cumbersome as complexity grows. Let's modularize this using the Ansible Roles approach.
Step 1: Connect to Control Node
Switch to the Ansible user on the control node:
sudo su ansible
cd ~
Step 2: Create the Roles Directory and Initialize a Role
Create a roles directory if it doesn't exist:
mkdir roles
cd roles
Initialize a new role (e.g., apache) using ansible-galaxy:
ansible-galaxy init apache
Optionally, install the tree command to visualize the directory structure:
sudo yum install tree
tree apache
Step 3: Define Tasks in tasks/main.yml
Navigate to the role’s tasks/
directory and define the tasks:
---
# tasks file for apache role
- name: Install httpd
yum:
name: httpd
state: latest
- name: Copy index.html
copy:
src: index.html
dest: /var/www/html/
notify:
- Restart Apache
Step 4: Add Required Static Files
Place the index.html file inside the files/ directory:
roles/apache/files/index.html
This ensures that the copy module in your task can find and deploy the file correctly.
Step 5: Define Handlers in handlers/main.yml
Create a handler to restart Apache when notified:
---
# handlers file for apache role
- name: Restart Apache
service:
name: httpd
state: restarted
Summary Directory Structure
After these steps, your apache role directory will resemble:
roles/
└── apache/
├── defaults/
├── files/
│ └── index.html
├── handlers/
│ └── main.yml
├── meta/
├── tasks/
│ └── main.yml
├── templates/
├── vars/
└── README.md
Step 6: Invoke the Role via a Playbook
Create a new playbook to invoke the apache role:
cd ~
vi invoke-roles.yml
---
- hosts: all
become: true
roles:
- apache
Running the Playbook
Execute the role-based playbook:
ansible-playbook invoke-roles.yml
Final Thoughts
Today’s session strengthened my expertise in securing automation workflows with Ansible Vault and designing scalable, modular configurations using Ansible Roles—both of which are crucial for building production-ready DevOps pipelines where security, maintainability, and scalability are paramount. Up next on Day 65, I’ll be diving into Ansible Conditionals, Loops, and Facts to enhance the dynamism and contextual awareness of my playbooks.
Stay tuned as I continue advancing in my DevOps journey!
Subscribe to my newsletter
Read articles from Vaishnavi D directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
