[RHCE] 02 – Understand core components of Ansible

    02_01 Ansible Inventories

    Static Inventory Examples

    INI Format

    # filepath: /etc/ansible/hosts
    # Basic hosts
    web1.example.com
    web2.example.com
    
    # Groups
    [webservers]
    web[1:3].example.com
    192.168.1.[10:20]
    
    [dbservers]
    db[01:02].example.com
    
    # Group of groups
    [datacenter:children]
    webservers
    dbservers
    
    # Group variables
    [webservers:vars]
    http_port=80
    proxy_timeout=5
    

    YAML Format

    # filepath: /etc/ansible/inventory.yml
    all:
      hosts:
        mail.example.com:
      children:
        webservers:
          hosts:
            web1.example.com:
              http_port: 80
            web2.example.com:
              http_port: 8080
        dbservers:
          hosts:
            db01.example.com:
            db02.example.com:
    

    Host/Group Variables

    Host Variables

    # filepath: host_vars/web1.example.com.yml
    ---
    ansible_host: 192.168.1.100
    ansible_user: admin
    http_port: 80
    

    Group Variables

    # filepath: group_vars/webservers.yml
    ---
    ntp_server: ntp.example.com
    timezone: UTC
    

    Dynamic Inventory

    AWS Example

    # filepath: inventory/aws_ec2.py
    #!/usr/bin/env python3
    # AWS EC2 dynamic inventory script
    import boto3
    import json
    
    def get_hosts():
        ec2 = boto3.client('ec2')
        hosts = {'_meta': {'hostvars': {}}}
        # ... AWS specific code ...
        return hosts
    
    if __name__ == '__main__':
        print(json.dumps(get_hosts()))
    

    Inventory Parameters

    Connection Parameters

    # Common parameters
    ansible_host=192.168.1.100
    ansible_port=22
    ansible_user=admin
    ansible_connection=ssh
    ansible_ssh_private_key_file=/path/to/key
    

    Working Examples

    Complete Production Inventory

    # filepath: production.ini
    # Web Servers
    [web]
    web1.prod ansible_host=192.168.1.101
    web2.prod ansible_host=192.168.1.102
    
    # Database Servers
    [db]
    db1.prod ansible_host=192.168.1.201
    db2.prod ansible_host=192.168.1.202
    
    # Load Balancers
    [lb]
    lb1.prod ansible_host=192.168.1.301
    lb2.prod ansible_host=192.168.1.302
    
    # Group Hierarchy
    [prod:children]
    web
    db
    lb
    
    # Common Variables
    [prod:vars]
    ansible_user=ansible
    ansible_become=true
    ntp_server=ntp.internal
    dns_server=192.168.1.1
    

    Testing Inventory

    # List all hosts
    ansible-inventory --list
    
    # Graph view
    ansible-inventory --graph
    
    # Host variables
    ansible-inventory --host web1.prod
    
    # Ping all hosts
    ansible all -m ping -i production.ini
    

    Inventory Verification

    # Verify syntax
    ansible-inventory --verify
    
    # List specific group
    ansible webservers --list-hosts
    
    # Show host variables
    ansible-inventory --host web1.example.com --yaml
    

    Remember to validate inventory access and permissions after creation.


    02_02 Ansible Modules Guide

    1. System Modules

    # System Module Examples
    - name: Package Management
      dnf:
        name: httpd
        state: present
    
    - name: Service Control
      systemd:
        name: httpd
        state: started
        enabled: yes
    
    - name: User Management
      user:
        name: webadmin
        shell: /bin/bash
        groups: wheel
        append: yes
    

    2. File Modules

    # File Operation Examples
    - name: File Management
      file:
        path: /etc/app
        state: directory
        mode: '0755'
    
    - name: Copy Files
      copy:
        src: files/config.conf
        dest: /etc/app/config.conf
        owner: root
        group: root
        mode: '0644'
    
    - name: Template Usage
      template:
        src: templates/app.conf.j2
        dest: /etc/app/app.conf
    

    3. Network Modules

    # Network Configuration
    - name: Configure firewall
      firewalld:
        service: http
        permanent: yes
        state: enabled
    
    - name: Manage Network
      nmcli:
        conn_name: eth0
        ifname: eth0
        type: ethernet
        ip4: 192.168.1.100/24
        state: present
    

    4. Database Modules

    # Database Operations
    - name: Create MySQL DB
      mysql_db:
        name: webapp
        state: present
    
    - name: Create DB User
      mysql_user:
        name: dbuser
        password: secret
        priv: 'webapp.*:ALL'
        state: present
    

    5. Cloud Modules

    # AWS Examples
    - name: Launch EC2
      ec2:
        key_name: mykey
        instance_type: t2.micro
        image: ami-123456
        wait: yes
        count: 1
        region: us-east-1
    

    6. Working Examples

    # Complete Web Stack Setup
    ---
    - name: Configure Web Application
      hosts: webservers
      become: true
      tasks:
        - name: Install Packages
          dnf:
            name:
              - httpd
              - php
              - php-mysql
            state: present
    
        - name: Configure Apache
          template:
            src: vhost.conf.j2
            dest: /etc/httpd/conf.d/vhost.conf
          notify: restart apache
    
        - name: Deploy Application
          git:
            repo: https://github.com/user/app.git
            dest: /var/www/html
            version: master
    
      handlers:
        - name: restart apache
          service:
            name: httpd
            state: restarted
    

    7. Module Documentation

    # View module documentation
    ansible-doc yum
    ansible-doc -l          # List all modules
    ansible-doc -s file    # Short description
    

    8. Custom Module Example

    # filepath: library/custom_module.py
    #!/usr/bin/python
    from ansible.module_utils.basic import AnsibleModule
    
    def main():
        module = AnsibleModule(
            argument_spec=dict(
                name=dict(required=True, type='str'),
                state=dict(default='present', choices=['present', 'absent'])
            )
        )
        
        # Module logic here
        
        module.exit_json(changed=True, msg="Success")
    
    if __name__ == '__main__':
        main()
    

    9. Module Return Values

    # Return Value Examples
    - name: Get Command Output
      command: whoami
      register: result
    
    - name: Show Result
      debug:
        var: result


    02_03 Ansible Variables Guide

    1. Variable Definition Methods

    Playbook Variables

    # playbook.yml
    ---
    - hosts: webservers
      vars:
        http_port: 80
        max_clients: 200
    

    Inventory Variables

    # inventory
    [webservers]
    web1.example.com http_port=80
    web2.example.com http_port=8080
    
    [webservers:vars]
    ntp_server=ntp.example.com
    

    Host/Group Variables

    # group_vars/webservers.yml
    ---
    apache_version: 2.4
    php_version: 7.4
    
    # host_vars/web1.example.com.yml
    ---
    site_domain: example.com
    

    2. Variable Types

    Simple Variables

    # Simple variable examples
    string_var: "Hello World"
    number_var: 42
    boolean_var: true
    

    Lists/Arrays

    # List variables
    fruits:
      - apple
      - banana
      - orange
    
    packages:
      - httpd
      - php
      - mysql
    

    Dictionaries/Maps

    # Dictionary variables
    website:
      domain: example.com
      root: /var/www/html
      owner: www-data
    

    3. Using Variables

    In Tasks

    # Using variables in tasks
    - name: Configure Apache
      template:
        src: vhost.conf.j2
        dest: "/etc/httpd/conf.d/{{ site_domain }}.conf"
        owner: "{{ website.owner }}"
    

    In Templates

    # templates/vhost.conf.j2
    <VirtualHost *:{{ http_port }}>
        ServerName {{ site_domain }}
        DocumentRoot {{ website.root }}
    </VirtualHost>
    

    4. Working Examples

    Complete Web Setup

    # web_setup.yml
    ---
    - hosts: webservers
      vars:
        app_name: myapp
        app_version: 1.0
        
      vars_files:
        - vars/common.yml
        
      tasks:
        - name: Install packages
          dnf:
            name: "{{ item }}"
            state: present
          loop: "{{ packages }}"
          
        - name: Deploy configuration
          template:
            src: "{{ app_name }}.conf.j2"
            dest: "/etc/{{ app_name }}/config.conf"
            
        - name: Show variables
          debug:
            msg: "Deploying {{ app_name }} version {{ app_version }}"
    

    Variable Files

    # vars/common.yml
    ---
    packages:
      - httpd
      - php
      - mysql-client
    
    app_settings:
      port: 8080
      max_connections: 100
      timeout: 300
    

    5. Special Variables

    Built-in Variables

    # Using special variables
    - debug:
        msg: "{{ ansible_hostname }}"  # System hostname
    - debug:
        msg: "{{ inventory_hostname }}" # Inventory name
    - debug:
        msg: "{{ group_names }}"      # Groups host belongs to
    

    Register Variables

    # Register command output
    - command: whoami
      register: user_output
    
    - debug:
        msg: "Current user is {{ user_output.stdout }}"
    

    6. Variable Precedence

    1. Command line (-e)
    2. Task variables
    3. Block variables
    4. Role variables
    5. Play variables
    6. Host facts
    7. Host vars
    8. Group vars
    9. Defaults

    02_04 Ansible Facts Guide

    1. System Facts

    Gathering Facts

    # facts_demo.yml
    ---
    - hosts: all
      tasks:
        - name: Display OS Facts
          debug:
            msg: "OS: {{ ansible_distribution }} {{ ansible_distribution_version }}"
        
        - name: Show Memory Info
          debug:
            msg: "Total Memory: {{ ansible_memtotal_mb }}MB"
    

    2. Common Facts Reference

    # System Information
    ansible_hostname          # System hostname
    ansible_distribution     # OS distribution
    ansible_architecture    # System architecture
    ansible_processor      # CPU info
    ansible_memtotal_mb   # Total memory
    
    # Network Facts
    ansible_all_ipv4_addresses  # IPv4 addresses
    ansible_default_ipv4       # Default IPv4 info
    ansible_interfaces        # Network interfaces
    
    # Storage Facts
    ansible_devices         # Storage devices
    ansible_mounts         # Mounted filesystems
    

    3. Custom Facts

    Setup Custom Facts Directory

    # Create facts.d directory
    mkdir -p /etc/ansible/facts.d
    

    Custom Fact Script

    # filepath: /etc/ansible/facts.d/custom.fact
    #!/usr/bin/env python3
    import json
    print(json.dumps({
        'application_env': 'production',
        'custom_setting': 'enabled'
    }))
    

    Using Custom Facts

    # custom_facts.yml
    ---
    - hosts: webservers
      tasks:
        - name: Show Custom Facts
          debug:
            msg: "Env: {{ ansible_local.custom.application_env }}"
    

    4. Fact Caching

    Configure Fact Caching

    # ansible.cfg
    [defaults]
    fact_caching = jsonfile
    fact_caching_connection = /tmp/ansible_facts
    fact_caching_timeout = 86400
    

    5. Working Examples

    Comprehensive Fact Usage

    # system_report.yml
    ---
    - hosts: all
      gather_facts: yes
      tasks:
        - name: System Report
          debug:
            msg: |
              System Info:
              -------------
              Hostname: {{ ansible_hostname }}
              OS: {{ ansible_distribution }} {{ ansible_distribution_version }}
              Memory: {{ ansible_memtotal_mb }}MB
              CPU Cores: {{ ansible_processor_cores }}
              IP Address: {{ ansible_default_ipv4.address }}
    

    Facts in Conditionals

    # os_specific_tasks.yml
    ---
    - hosts: all
      tasks:
        - name: RHEL Specific Task
          dnf:
            name: httpd
            state: present
          when: ansible_distribution == "RedHat"
    
        - name: Ubuntu Specific Task
          apt:
            name: apache2
            state: present
          when: ansible_distribution == "Ubuntu"
    

    Hardware Requirements Check

    # check_requirements.yml
    ---
    - hosts: webservers
      tasks:
        - name: Verify Memory Requirements
          fail:
            msg: "Insufficient memory (4GB required)"
          when: ansible_memtotal_mb < 4096
    
        - name: Verify Disk Space
          fail:
            msg: "Insufficient disk space (20GB required)"
          when: ansible_mounts[0].size_total < 21474836480
    

    Gather Specific Facts

    # gather_subset.yml
    ---
    - hosts: all
      gather_facts: no
      tasks:
        - name: Gather Network Facts Only
          setup:
            gather_subset:
              - network

    02_05 Ansible Loops Guide

    Basic Loop Examples

    # Simple loop with items
    - name: Install packages
      dnf:
        name: "{{ item }}"
        state: present
      loop:
        - httpd
        - php
        - mariadb-server
    

    Dictionary Loops

    # Loop through dictionary
    - name: Create users
      user:
        name: "{{ item.name }}"
        shell: "{{ item.shell }}"
        groups: "{{ item.groups }}"
      loop:
        - { name: 'john', shell: '/bin/bash', groups: 'admins' }
        - { name: 'jane', shell: '/bin/zsh', groups: 'developers' }
    

    Nested Loops

    # Nested loop example
    - name: Configure virtual hosts
      template:
        src: "vhost.conf.j2"
        dest: "/etc/httpd/sites-available/{{ item.0.domain }}_{{ item.1 }}.conf"
      loop: "{{ domains | product(['http', 'https']) | list }}"
      vars:
        domains:
          - { domain: 'example.com', root: '/var/www/example' }
          - { domain: 'test.com', root: '/var/www/test' }
    

    Loop Control

    # Loop with control
    - name: Long running operation
      command: /long_task.sh
      loop:
        - task1
        - task2
        - task3
      loop_control:
        pause: 5
        label: "Processing {{ item }}"
    

    Working Examples

    # Complete web setup with loops
    - name: Configure Web Environment
      hosts: webservers
      vars:
        sites:
          - { domain: 'site1.com', port: 80, root: '/var/www/site1' }
          - { domain: 'site2.com', port: 8080, root: '/var/www/site2' }
        packages:
          - { name: 'httpd', state: 'latest' }
          - { name: 'php', state: 'present' }
      
      tasks:
        - name: Install required packages
          dnf:
            name: "{{ item.name }}"
            state: "{{ item.state }}"
          loop: "{{ packages }}"
    
        - name: Create document roots
          file:
            path: "{{ item.root }}"
            state: directory
            mode: '0755'
          loop: "{{ sites }}"
    
        - name: Configure virtual hosts
          template:
            src: vhost.conf.j2
            dest: "/etc/httpd/conf.d/{{ item.domain }}.conf"
          loop: "{{ sites }}"
          notify: restart apache
    

    Loop with Conditionals

    # Conditional loops
    - name: Service management
      service:
        name: "{{ item }}"
        state: started
        enabled: yes
      loop:
        - httpd
        - mariadb
        - php-fpm
      when: ansible_distribution == 'RedHat'
    

    Loop with Registered Variables

    # Register and loop
    - name: Check services
      command: systemctl status {{ item }}
      register: service_status
      loop:
        - httpd
        - mariadb
      ignore_errors: yes
    
    - name: Show status
      debug:
        msg: "{{ item.stdout }}"
      loop: "{{ service_status.results }}"

    02_06 Ansible Conditional Tasks Guide

    Basic Conditionals

    # Basic when condition
    - name: Install Apache on RHEL
      dnf:
        name: httpd
        state: present
      when: ansible_distribution == "RedHat"
    

    Multiple Conditions

    # Multiple conditions
    - name: Configure production settings
      template:
        src: prod.conf.j2
        dest: /etc/app/config.conf
      when:
        - ansible_environment == "production"
        - ansible_memtotal_mb > 4096
        - inventory_hostname in groups['webservers']
    

    Register Variable Conditions

    # Using registered variables
    - name: Check service status
      command: systemctl status httpd
      register: service_status
      ignore_errors: yes
    
    - name: Restart service if failed
      service:
        name: httpd
        state: restarted
      when: service_status.rc != 0
    

    Working Examples

    # Complete conditional deployment
    ---
    - hosts: all
      tasks:
        - name: Gather package facts
          package_facts:
            manager: auto
          
        - name: Install Apache based on OS
          block:
            - name: RHEL Apache
              dnf:
                name: httpd
                state: present
              when: ansible_distribution == "RedHat"
            
            - name: Ubuntu Apache
              apt:
                name: apache2
                state: present
              when: ansible_distribution == "Ubuntu"
    
        - name: Configure memory settings
          template:
            src: "{% if ansible_memtotal_mb > 4096 %}high_mem.conf.j2{% else %}low_mem.conf.j2{% endif %}"
            dest: /etc/httpd/conf.d/mem.conf
          when: "'httpd' in ansible_facts.packages"
    
        - name: Check disk space
          command: df -h /
          register: disk_space
          changed_when: false
    
        - name: Cleanup old logs
          file:
            path: /var/log/httpd/old
            state: absent
          when: disk_space.stdout is search("9[0-9]%")
    

    Environment Specific Tasks

    # Environment conditionals
    - name: Deploy configuration
      template:
        src: "{{ item }}"
        dest: /etc/app/config.yml
      with_first_found:
        - files:
            - "config_{{ ansible_hostname }}.yml.j2"
            - "config_{{ ansible_distribution }}.yml.j2"
            - "config_default.yml.j2"
          paths:
            - templates
      when: ansible_distribution_version >= "8"
    

    Boolean Logic

    # Complex boolean logic
    - name: Complex conditions
      debug:
        msg: "Meets requirements"
      when: >
        ( ansible_distribution == "RedHat" and
          ansible_distribution_major_version == "8" )
        or
        ( ansible_distribution == "Ubuntu" and
          ansible_distribution_major_version == "20" )
    

    Handlers with Conditions

    # Conditional handlers
    - name: Update web configuration
      template:
        src: web.conf.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: restart web service
      when: ansible_system == "Linux"
    
    handlers:
      - name: restart web service
        service:
          name: "{{ 'httpd' if ansible_distribution == 'RedHat' else 'apache2' }}"
          state: restarted

    02_07 Ansible Plays Guide

    Basic Play Structure

    // filepath: /etc/ansible/basic_play.yml
    ---
    - name: Basic Web Server Setup
      hosts: webservers
      become: true
      vars:
        http_port: 80
        
      tasks:
        - name: Install Apache
          dnf:
            name: httpd
            state: present
            
        - name: Start Apache
          service:
            name: httpd
            state: started
            enabled: yes
    

    Advanced Play Features

    // filepath: /etc/ansible/advanced_play.yml
    ---
    - name: Complex Web Application Deployment
      hosts: webservers
      become: true
      strategy: free
      serial: 2
      vars_files:
        - vars/main.yml
        
      pre_tasks:
        - name: Check Prerequisites
          assert:
            that:
              - ansible_memory_mb.real.total >= 2048
              
      tasks:
        - block:
            - name: Install Packages
              dnf:
                name:
                  - httpd
                  - php
                  - mariadb-server
                state: present
          rescue:
            - name: Log Failure
              debug:
                msg: "Package installation failed"
          always:
            - name: Ensure SELinux Context
              seboolean:
                name: httpd_can_network_connect
                state: yes
                persistent: yes
                
      post_tasks:
        - name: Verify Service
          uri:
            url: http://localhost
            return_content: yes
    

    Multi-Play Example

    // filepath: /etc/ansible/multi_play.yml
    ---
    - name: Database Setup
      hosts: dbservers
      become: true
      roles:
        - mysql
        
    - name: Web Setup
      hosts: webservers
      become: true
      roles:
        - apache
        - php
        
    - name: Load Balancer Setup
      hosts: lbservers
      become: true
      roles:
        - haproxy
    

    Play with Handlers

    // filepath: /etc/ansible/handlers_play.yml
    ---
    - name: Configure Web Services
      hosts: webservers
      become: true
      
      tasks:
        - name: Copy Apache Config
          template:
            src: httpd.conf.j2
            dest: /etc/httpd/conf/httpd.conf
          notify: restart apache
          
        - name: Copy PHP Config
          template:
            src: php.ini.j2
            dest: /etc/php.ini
          notify: restart php-fpm
          
      handlers:
        - name: restart apache
          service:
            name: httpd
            state: restarted
            
        - name: restart php-fpm
          service:
            name: php-fpm
            state: restarted
    

    Production Example

    // filepath: /etc/ansible/production_play.yml
    ---
    - name: Production Web Deployment
      hosts: prod_webservers
      become: true
      serial: "25%"
      max_fail_percentage: 20
      
      pre_tasks:
        - name: Backup Configs
          archive:
            path: /etc/httpd
            dest: /backup/httpd-{{ ansible_date_time.date }}.tar.gz
            
      tasks:
        - name: Update System
          dnf:
            name: "*"
            state: latest
          
        - name: Deploy Application
          git:
            repo: https://github.com/company/webapp.git
            dest: /var/www/html
            version: "{{ app_version }}"
          notify: reload apache
          
      post_tasks:
        - name: Verify Deployment
          uri:
            url: https://{{ inventory_hostname }}
            validate_certs: yes
            status_code: 200
            
      handlers:
        - name: reload apache
          service:
            name: httpd
            state: reloaded

    02_08 Ansible Task Failure Handling

    Basic Error Handling

    # Basic error handling examples
    ---
    - name: Service Management with Error Handling
      hosts: webservers
      tasks:
        - name: Check service status
          command: systemctl status httpd
          register: service_result
          ignore_errors: yes
    
        - name: Display status
          debug:
            msg: "Service status: {{ service_result.stdout }}"
          when: service_result is success
    

    Custom Failure Conditions

    # Custom failure conditions
    - name: Disk Space Check
      shell: df -h / | tail -n1 | awk '{print $5}' | sed 's/%//'
      register: disk_space
      failed_when: disk_space.stdout|int >= 90
    

    Block Error Handling

    # Block/rescue/always example
    - name: Application Deployment
      block:
        - name: Deploy application
          git:
            repo: https://github.com/app/repo.git
            dest: /var/www/html
            
        - name: Configure application
          template:
            src: app.conf.j2
            dest: /etc/app/config.conf
            
      rescue:
        - name: Restore backup
          command: cp /backup/app.conf /etc/app/config.conf
          
        - name: Notify team
          mail:
            to: admin@example.com
            subject: Deployment failed
            
      always:
        - name: Restart service
          service:
            name: httpd
            state: restarted
    

    Production Examples

    # Complete production deployment with error handling
    ---
    - name: Production Deployment
      hosts: production
      serial: "25%"
      max_fail_percentage: 20
      any_errors_fatal: true
      
      pre_tasks:
        - name: Check prerequisites
          block:
            - name: Verify disk space
              shell: df -h / | awk 'NR==2 {print $5}' | sed 's/%//'
              register: disk_space
              failed_when: disk_space.stdout|int >= 85
              
            - name: Check memory
              shell: free | awk '/Mem:/ {print $4/$2 * 100.0}'
              register: memory
              failed_when: memory.stdout|float <= 20.0
              
          rescue:
            - name: Log failure
              local_action: 
                module: shell
                cmd: echo "Pre-check failed on {{ inventory_hostname }}" >> /var/log/deploy.log
              
            - name: Skip host
              meta: clear_host_errors
              
      tasks:
        - block:
            - name: Update packages
              dnf:
                name: "*"
                state: latest
              register: update_result
              
            - name: Configure application
              template:
                src: app.conf.j2
                dest: /etc/app/config.conf
              notify: restart application
              
          rescue:
            - name: Rollback updates
              shell: dnf history rollback -y
              when: update_result is failed
              
            - name: Notify failure
              mail:
                to: admin@example.com
                subject: "Deployment failed on {{ inventory_hostname }}"
                body: "Check logs for details"
                
      handlers:
        - name: restart application
          service:
            name: application
            state: restarted
    

    Common Error Patterns

    # Common error handling patterns
    - name: Error handling examples
      hosts: all
      tasks:
        - name: Retry example
          command: /unreliable/script.sh
          register: result
          retries: 3
          delay: 5
          until: result is success
          
        - name: Changed when example
          shell: echo "Running task"
          register: echo_result
          changed_when: false
          
        - name: Multiple conditions
          command: systemctl status httpd
          register: service_status
          failed_when:
            - service_status.rc != 0
            - '"active" not in service_status.stdout'

    02_09 Ansible Playbooks Guide

    Basic Structure

    // filepath: /etc/ansible/basic_playbook.yml
    ---
    - name: Basic Web Setup
      hosts: webservers
      become: true
      vars:
        http_port: 80
        doc_root: /var/www/html
    
      tasks:
        - name: Install Apache
          dnf:
            name: httpd
            state: present
    
        - name: Start Apache
          service:
            name: httpd
            state: started
            enabled: yes
    

    Advanced Features

    // filepath: /etc/ansible/advanced_playbook.yml
    ---
    - name: Complete Web Stack
      hosts: webservers
      become: true
      vars_files:
        - vars/main.yml
      
      pre_tasks:
        - name: Update package cache
          dnf:
            update_cache: yes
      
      roles:
        - common
        - apache
        - php
        
      tasks:
        - name: Deploy application
          git:
            repo: "{{ app_repo }}"
            dest: "{{ doc_root }}"
            version: "{{ app_version }}"
          notify: restart web services
    
      handlers:
        - name: restart web services
          service:
            name: "{{ item }}"
            state: restarted
          loop:
            - httpd
            - php-fpm
    

    Production Example

    // filepath: /etc/ansible/production_playbook.yml
    ---
    - name: Load Balancer Setup
      hosts: lbservers
      roles:
        - haproxy
    
    - name: Database Setup
      hosts: dbservers
      roles:
        - mysql
      tags: 
        - db
    
    - name: Web Application
      hosts: webservers
      serial: "25%"
      max_fail_percentage: 25
      
      pre_tasks:
        - name: Verify requirements
          assert:
            that:
              - ansible_memory_mb.real.total >= 4096
              - ansible_distribution == "RedHat"
            msg: "System requirements not met!"
            
      roles:
        - common
        - apache
        - php
        - app
        
      post_tasks:
        - name: Verify deployment
          uri:
            url: "http://{{ inventory_hostname }}"
            return_content: yes
            status_code: 200
          register: webpage
          failed_when: "'Welcome' not in webpage.content"
    

    Directory Structure

    production_site/
    ├── ansible.cfg
    ├── inventory/
    │   ├── group_vars/
    │   │   ├── all.yml
    │   │   └── webservers.yml
    │   └── hosts
    ├── roles/
    │   ├── common/
    │   ├── apache/
    │   └── php/
    └── site.yml
    

    Best Practices

    // filepath: /etc/ansible/best_practices.yml
    ---
    - name: Following Best Practices
      hosts: webservers
      become: true
      
      vars_files:
        - "vars/{{ ansible_distribution }}.yml"
        - "vars/{{ environment }}.yml"
      
      tasks:
        - name: Include OS-specific tasks
          include_tasks: "tasks/{{ ansible_distribution }}.yml"
          
        - name: Configure application
          template:
            src: "templates/{{ item }}.j2"
            dest: "/etc/{{ item }}"
          loop:
            - apache2.conf
            - php.ini
          notify: reload services
          tags:
            - config

    02_10 Ansible Configuration Files Guide

    Configuration File Locations (In Order of Precedence)

    1. $ANSIBLE_CONFIG environment variable
    2. ./ansible.cfg (current directory)
    3. ~/ansible.cfg (home directory)
    4. /etc/ansible/ansible.cfg

    Basic Configuration Example

    # filepath: /etc/ansible/ansible.cfg
    [defaults]
    inventory = ./inventory
    remote_user = ansible
    host_key_checking = False
    forks = 5
    log_path = /var/log/ansible.log
    
    [privilege_escalation]
    become = True
    become_method = sudo
    become_user = root
    become_ask_pass = False
    

    Advanced Configuration

    # filepath: /etc/ansible/production.cfg
    [defaults]
    inventory = ./inventory/production
    remote_user = ansibleprod
    private_key_file = ~/.ssh/prod_key
    vault_password_file = ~/.vault_pass
    roles_path = ./roles:/usr/share/ansible/roles
    log_path = /var/log/ansible/prod.log
    forks = 20
    timeout = 30
    
    [ssh_connection]
    pipelining = True
    ssh_args = -o ControlMaster=auto -o ControlPersist=3600s
    
    [diff]
    always = True
    context = 3
    

    Environment-Specific Example

    # filepath: development.cfg
    [defaults]
    inventory = ./inventory/development
    remote_user = ansibledev
    host_key_checking = False
    retry_files_enabled = True
    roles_path = ./roles
    log_path = /var/log/ansible/dev.log
    
    [privilege_escalation]
    become = True
    become_method = sudo
    
    [callback_plugins]
    stdout_callback = debug
    

    Production Best Practices

    # filepath: production_secure.cfg
    [defaults]
    inventory = ./inventory/production
    remote_user = ansible
    private_key_file = ~/.ssh/id_rsa
    vault_password_file = ~/.vault_pass
    roles_path = ./roles:/usr/share/ansible/roles
    log_path = /var/log/ansible.log
    forks = 10
    timeout = 30
    retry_files_enabled = False
    host_key_checking = True
    nocows = True
    
    [privilege_escalation]
    become = True
    become_method = sudo
    become_user = root
    become_ask_pass = False
    
    [ssh_connection]
    pipelining = True
    control_path = /tmp/ansible-ssh-%%h-%%p-%%r
    ssh_args = -o ControlMaster=auto -o ControlPersist=60s
    
    [persistent_connection]
    connect_timeout = 60
    command_timeout = 30
    
    [galaxy]
    server_list = public_galaxy
    
    [public_galaxy]
    url = https://galaxy.ansible.com/
    token = ${GALAXY_TOKEN}
    

    Special Settings Example

    # filepath: special_config.cfg
    [defaults]
    gathering = smart
    fact_caching = jsonfile
    fact_caching_connection = /tmp/ansible_facts
    fact_caching_timeout = 86400
    timeout = 60
    callback_whitelist = timer, profile_tasks
    display_skipped_hosts = False
    error_on_undefined_vars = True
    system_warnings = True
    deprecation_warnings = True
    
    [colors]
    highlight = white
    verbose = blue
    warn = bright purple
    error = red
    debug = dark gray
    ok = green
    changed = yellow

    02_11 Ansible Roles Guide

    Basic Role Structure

    # Standard role directory structure
    roles/
    ├── example_role/
    │   ├── defaults/
    │   │   └── main.yml
    │   ├── files/
    │   ├── handlers/
    │   │   └── main.yml
    │   ├── meta/
    │   │   └── main.yml
    │   ├── tasks/
    │   │   └── main.yml
    │   ├── templates/
    │   │   └── example.conf.j2
    │   └── vars/
    │       └── main.yml
    

    Example Web Server Role

    # filepath: roles/webserver/tasks/main.yml
    ---
    - name: Install Apache
      dnf:
        name: httpd
        state: present
    
    - name: Configure Apache
      template:
        src: httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: restart apache
    
    - name: Start Apache
      service:
        name: httpd
        state: started
        enabled: yes
    
    # filepath: roles/webserver/handlers/main.yml
    ---
    - name: restart apache
      service:
        name: httpd
        state: restarted
    
    # filepath: roles/webserver/defaults/main.yml
    ---
    http_port: 80
    doc_root: /var/www/html
    max_clients: 150
    
    # filepath: roles/webserver/meta/main.yml
    ---
    dependencies:
      - role: common
        vars:
          package_list:
            - epel-release
            - firewalld
    

    Using Roles in Playbooks

    # filepath: site.yml
    ---
    - hosts: webservers
      roles:
        - common
        - webserver
        - { role: php, php_version: '7.4' }
    

    Complete Role Example

    # filepath: roles/app_deploy/tasks/main.yml
    ---
    - name: Include OS specific tasks
      include_tasks: "{{ ansible_distribution }}.yml"
    
    - name: Create application directory
      file:
        path: "{{ app_dir }}"
        state: directory
        mode: '0755'
    
    - name: Deploy application
      git:
        repo: "{{ app_repo }}"
        dest: "{{ app_dir }}"
        version: "{{ app_version }}"
      notify: restart application
    
    - name: Configure application
      template:
        src: app.conf.j2
        dest: "{{ app_conf_path }}"
      notify: reload application
    
    # filepath: roles/app_deploy/defaults/main.yml
    ---
    app_dir: /opt/myapp
    app_repo: https://github.com/org/app.git
    app_version: master
    app_user: www-data
    app_group: www-data
    app_port: 8080
    
    # filepath: roles/app_deploy/handlers/main.yml
    ---
    - name: restart application
      systemd:
        name: myapp
        state: restarted
    
    - name: reload application
      systemd:
        name: myapp
        state: reloaded
    
    # filepath: roles/app_deploy/templates/app.conf.j2
    server {
        listen {{ app_port }};
        root {{ app_dir }};
        
        location / {
            proxy_pass http://localhost:{{ app_port }};
        }
    }
    

    Similar code found with 1 license type


    02_12 Ansible Documentation Guide

    Basic Documentation Commands

    # View all modules
    ansible-doc -l
    
    # Get help for specific module
    ansible-doc yum
    
    # List plugin types
    ansible-doc -t connection -l
    
    # Show playbook keywords
    ansible-doc -t keyword -l
    

    Module Documentation Examples

    # Using ansible-doc output for dnf module
    - name: Install packages based on docs
      dnf:
        name: httpd
        state: present
        enablerepo: epel
        disable_gpg_check: no
    

    Working with Documentation

    # Search for modules
    ansible-doc -l | grep mysql
    
    # View specific module parameters
    ansible-doc -s file
    
    # Show examples
    ansible-doc -i copy
    

    Practical Documentation Usage

    # Example using documented parameters
    - name: Configure service
      systemd:
        name: httpd
        state: started
        enabled: yes
        daemon_reload: yes
    

    Documentation in Action

    # Complete example using documented features
    - name: Deploy web application
      hosts: webservers
      tasks:
        - name: Install web server
          dnf:
            name: 
              - httpd
              - mod_ssl
            state: present
            
        - name: Configure SSL
          openssl_certificate:
            path: /etc/pki/tls/certs/localhost.crt
            privatekey_path: /etc/pki/tls/private/localhost.key
            provider: selfsigned
            
        - name: Set file permissions
          file:
            path: /var/www/html
            state: directory
            mode: '0755'
            owner: apache
            group: apache
            setype: httpd_sys_content_t
    

    Version-Specific Documentation

    # Check ansible version
    ansible --version
    
    # Get version specific module info
    ansible-doc -v 2.9 yum
    

    Remember: Always check documentation for module updates and deprecated features.



    Discover more from Altgr Blog

    Subscribe to get the latest posts sent to your email.

    Leave a Reply

    Your email address will not be published. Required fields are marked *