Last Updated: December 24, 2024
Advanced Playbook Patterns
---
- name: Deploy multi-tier application
hosts: all
become: yes
vars:
app_version: "{{ lookup('env', 'APP_VERSION') | default('latest') }}"
deploy_env: "{{ ansible_env }}"
pre_tasks:
- name: Validate prerequisites
assert:
that:
- ansible_version.full is version('2.10', '>=')
- app_version is defined
msg: "Requirements not met"
roles:
- role: common
tags: ['common']
- role: webserver
tags: ['web']
when: inventory_hostname in groups['webservers']
- role: database
tags: ['db']
when: inventory_hostname in groups['databases']
post_tasks:
- name: Verify deployment
uri:
url: "http://{{ ansible_host }}/health"
status_code: 200
register: health_check
until: health_check.status == 200
retries: 5
delay: 10
Dynamic Inventory
#!/usr/bin/env python3
# aws_inventory.py
import json
import boto3
def get_inventory():
ec2 = boto3.client('ec2')
response = ec2.describe_instances(
Filters=[{'Name': 'instance-state-name', 'Values': ['running']}]
)
inventory = {
'_meta': {'hostvars': {}},
'all': {'hosts': []},
}
for reservation in response['Reservations']:
for instance in reservation['Instances']:
host = instance['PrivateIpAddress']
inventory['all']['hosts'].append(host)
# Add tags as groups
for tag in instance.get('Tags', []):
if tag['Key'] == 'Group':
group = tag['Value']
if group not in inventory:
inventory[group] = {'hosts': []}
inventory[group]['hosts'].append(host)
inventory['_meta']['hostvars'][host] = {
'instance_id': instance['InstanceId'],
'instance_type': instance['InstanceType'],
}
return inventory
if __name__ == '__main__':
print(json.dumps(get_inventory(), indent=2))
Ansible Vault Best Practices
ansible-vault create secrets.yml
Create encrypted file
ansible-vault encrypt vars.yml
Encrypt existing file
ansible-vault edit secrets.yml
Edit encrypted file
ansible-playbook --vault-password-file=.vault_pass site.yml
Run playbook with vault password file
Custom Modules
#!/usr/bin/python
# library/custom_module.py
from ansible.module_utils.basic import AnsibleModule
def run_module():
module_args = dict(
name=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['present', 'absent']),
)
result = dict(
changed=False,
message=''
)
module = AnsibleModule(
argument_spec=module_args,
supports_check_mode=True
)
if module.check_mode:
module.exit_json(**result)
# Module logic here
result['changed'] = True
result['message'] = f"Processed {module.params['name']}"
module.exit_json(**result)
if __name__ == '__main__':
run_module()
💡 Pro Tip:
Use roles for reusability, implement idempotency in all tasks, and leverage tags for selective execution. Always test playbooks in staging before production.