Ansible_advanced
Chapter 45: Ansible Advanced
Section titled “Chapter 45: Ansible Advanced”This chapter covers advanced Ansible features including Vault, lookups, async tasks, and custom modules.
Ansible Vault
Section titled “Ansible Vault”Ansible Vault encrypts sensitive data in playbooks and roles.
┌─────────────────────────────────────────────────────────────────────────────┐│ Ansible Vault │├─────────────────────────────────────────────────────────────────────────────┤│ ││ ┌─────────────────────────────────────────────────────────────────────┐ ││ │ Vault Encryption │ ││ │ │ ││ │ ansible-vault create secrets.yml # Create encrypted file │ ││ │ ansible-vault edit secrets.yml # Edit encrypted file │ ││ │ ansible-vault decrypt secrets.yml # Decrypt file │ ││ │ ansible-vault encrypt secrets.yml # Encrypt file │ ││ │ ansible-vault view secrets.yml # View without decrypt │ ││ │ ansible-vault rekey secrets.yml # Change password │ ││ │ │ ││ └─────────────────────────────────────────────────────────────────────┘ ││ ││ Using encrypted files: ││ ansible-playbook site.yml --vault-password-file ~/.vault_pass ││ ansible-playbook site.yml --ask-vault-pass ││ │└─────────────────────────────────────────────────────────────────────────────┘Creating Encrypted Files
Section titled “Creating Encrypted Files”# Create new encrypted fileansible-vault create secrets.yml
# Encrypt existing fileansible-vault encrypt secrets.yml
# Edit encrypted fileansible-vault edit secrets.yml
# View encrypted fileansible-vault view secrets.ymlEncrypted Variable Files
Section titled “Encrypted Variable Files”# group_vars/production/vault.yml (encrypted)---vault_db_password: "super_secret_password"vault_api_key: "api_key_12345"vault_ssl_cert: | -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE-----
# Using vault variables# (unencrypted file)db_password: "{{ vault_db_password }}"Vault Password Files
Section titled “Vault Password Files”# Create password fileecho "my_vault_password" > .vault_pass
# Make securechmod 600 .vault_pass
# Use in playbookansible-playbook site.yml --vault-password-file .vault_passLookups
Section titled “Lookups”Lookups fetch data from external sources.
# Using lookups---- name: Get password from HashiCorp Vault debug: msg: "{{ lookup('hashi_vault', 'secret=secret/data/db:password') }}"
- name: Read file contents debug: msg: "{{ lookup('file', '/path/to/file.txt') }}"
- name: Get environment variable debug: msg: "{{ lookup('env', 'PATH') }}"
- name: Query DNS debug: msg: "{{ lookup('dig', 'example.com') }}"
- name: Use password store debug: msg: "{{ lookup('passwordstore', 'database/password') }}"
- name: Read from template debug: msg: "{{ lookup('template', 'config.j2') }}"
- name: URL content debug: msg: "{{ lookup('url', 'https://api.github.com') }}"
- name: CSV data debug: msg: "{{ lookup('csvfile', 'item=server1 file=inventory.csv delimiter=,') }}"Async and Parallel Tasks
Section titled “Async and Parallel Tasks”---- name: Run long-running tasks hosts: all
tasks: - name: Start backup command: /opt/backup.sh async: 3600 # Max runtime in seconds poll: 0 # Don't wait, fire and forget register: backup_job
- name: Check backup status async_status: jid: "{{ backup_job.ansible_job_id }}" register: status until: status.finished retries: 100 delay: 30
- name: Download files in parallel get_url: url: "http://example.com/file{{ item }}.tar.gz" dest: "/tmp/file{{ item }}.tar.gz" loop: "{{ range(1, 11) | list }}" throttle: 5 # Max parallel tasksDelegation
Section titled “Delegation”Run tasks on different hosts.
---- name: Deploy to webservers, manage on localhost hosts: webservers
tasks: - name: Deploy application synchronize: src: ./app/ dest: /opt/app/
- name: Restart app on all webservers service: name: myapp state: restarted delegate_to: "{{ inventory_hostname }}"
- name: Notify external service uri: url: https://api.example.com/deploy method: POST delegate_to: localhost
- name: Run on local machine local_action: module: command cmd: echo "Running locally"Blocks and Error Handling
Section titled “Blocks and Error Handling”---- name: Error handling with blocks hosts: webservers
tasks: - name: Block with rescue block: - name: Attempt risky operation command: /opt/may_fail.sh register: result rescue: - name: Handle failure debug: msg: "Operation failed: {{ result.stderr }}" always: - name: Always run this debug: msg: "Cleanup or notification"
- name: Handle errors block: - name: Install packages apt: name: "{{ packages }}" state: present failed_when: "'not found' in result.stderr" changed_when: result.rc == 0Facts and Magic Variables
Section titled “Facts and Magic Variables”---- name: Work with facts hosts: all
tasks: - name: Show all facts debug: var: ansible_facts
- name: Show specific facts debug: msg: "OS: {{ ansible_facts['distribution'] }}"
- name: Register variable command: hostname register: hostname_result
- name: Use registered variable debug: msg: "Hostname: {{ hostname_result.stdout }}"
- name: Hostvars debug: msg: "Other host IP: {{ hostvars['other.example.com'].ansible_host }}"
- name: Group names debug: msg: "Groups: {{ group_names }}"
- name: Loop hosts debug: msg: "Host: {{ item }}" loop: "{{ groups['webservers'] }}"Custom Modules
Section titled “Custom Modules”Module Structure
Section titled “Module Structure”#!/usr/bin/python3from ansible.module_utils.basic import AnsibleModule
def main(): module = AnsibleModule( argument_spec=dict( name=dict(type='str', required=True), state=dict(type='str', default='present', choices=['present', 'absent']) ) )
name = module.params['name'] state = module.params['state']
if state == 'present': # Logic to ensure something exists module.exit_json(changed=True, msg="Created resource") else: # Logic to remove something module.exit_json(changed=True, msg="Removed resource")
if __name__ == '__main__': main()Using Custom Module
Section titled “Using Custom Module”---- name: Use custom module hosts: all tasks: - name: Call custom module custom_module: name: myresource state: presentJinja2 Filters
Section titled “Jinja2 Filters”# Using filters---- name: Use filters hosts: localhost gather_facts: no
vars: numbers: [1, 2, 3, 4, 5] user_data: name: john email: john@example.com
tasks: - name: String filters debug: msg: "{{ 'hello' | upper }}"
- name: Number filters debug: msg: "{{ numbers | sum }}"
- name: JSON filter debug: msg: "{{ user_data | to_json }}"
- name: Default filter debug: msg: "{{ undefined_var | default('default_value') }}"
- name: Unique filter debug: msg: "{{ [1,2,2,3] | unique }}"
- name: Zip filter debug: msg: "{{ ['a','b'] | zip(['1','2']) | list }}"
- name: Ternary filter debug: msg: "{{ (true) | ternary('yes', 'no') }}"Strategy and Performance
Section titled “Strategy and Performance”---# Use free strategy (run tasks as fast as possible)- name: Fast execution hosts: all strategy: free
tasks: - name: Quick tasks yum: name: "{{ item }}" state: present loop: - vim - curl
# Use serial for rolling updates- name: Rolling update hosts: webservers serial: 1 # Or percentage: "25%"
tasks: - name: Update service yum: name: myapp state: latest
- name: Verify uri: url: http://localhost/healthSecurity Best Practices
Section titled “Security Best Practices”┌─────────────────────────────────────────────────────────────────────────────┐│ Ansible Security Best Practices │├─────────────────────────────────────────────────────────────────────────────┤│ ││ 1. Credentials Management ││ ✓ Use Ansible Vault for secrets ││ ✓ Use external secrets management (HashiCorp Vault) ││ ✓ Never commit secrets to version control ││ ││ 2. SSH Security ││ ✓ Use SSH keys instead of passwords ││ ✓ Enable StrictHostKeyChecking ││ ✓ Use ansible-bender for encrypted connections ││ ││ 3. Privilege Escalation ││ ✓ Use become: yes only when necessary ││ ✓ Limit sudo access ││ ✓ Use specific sudo users instead of all ││ ││ 4. Code Review ││ ✓ Review playbooks before running ││ ✓ Use --check mode (dry run) ││ ✓ Use --diff to see changes ││ │└─────────────────────────────────────────────────────────────────────────────┘Testing Ansible
Section titled “Testing Ansible”# Syntax checkansible-playbook --syntax-check playbook.yml
# Dry runansible-playbook --check playbook.yml
# Show differencesansible-playbook --diff playbook.yml
# Lint with ansible-lintansible-lint playbook.ymlMolecule Testing
Section titled “Molecule Testing”---- name: Converge hosts: all become: yes
roles: - role: my_role my_role_var: test_value# Run molecule testsmolecule test
# Create scenariomolecule init scenario
# List scenariosmolecule listSummary
Section titled “Summary”In this chapter, you learned:
- Ansible Vault: Encrypting sensitive data
- Lookups: Fetching data from external sources
- Async Tasks: Running long-running tasks
- Delegation: Running on different hosts
- Error Handling: Blocks and rescue
- Custom Modules: Creating your own modules
- Jinja2 Filters: Data transformation
- Performance: Strategies and parallel execution
- Security Best Practices: Securing Ansible
- Testing: Syntax check, dry run, Molecule