[RHCE] 03 – Use roles and Ansible Content Collections

    03_01 – Creating and Working with Ansible Roles

    Role Directory Structure

    # Create role structure
    mkdir -p roles/webserver/{defaults,files,handlers,meta,tasks,templates,vars}
    

    Basic Role Components

    # filepath: roles/webserver/tasks/main.yml
    ---
    - name: Install required packages
      dnf:
        name: 
          - httpd
          - php
          - php-mysql
        state: present
    
    - name: Configure Apache
      template:
        src: httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf
      notify: restart apache
    
    - name: Start services
      service:
        name: "{{ item }}"
        state: started
        enabled: yes
      loop:
        - httpd
        - php-fpm
    
    # filepath: roles/webserver/handlers/main.yml
    ---
    - name: restart apache
      service:
        name: httpd
        state: restarted
    
    - name: reload apache
      service:
        name: httpd
        state: reloaded
    
    # filepath: roles/webserver/defaults/main.yml
    ---
    http_port: 80
    doc_root: /var/www/html
    max_clients: 150
    php_version: "7.4"
    
    # filepath: roles/webserver/meta/main.yml
    ---
    dependencies:
      - role: common
        vars:
          packages:
            - epel-release
            - firewalld
    
    # filepath: roles/webserver/templates/httpd.conf.j2
    ServerRoot "/etc/httpd"
    Listen {{ http_port }}
    ServerAdmin root@localhost
    DocumentRoot "{{ doc_root }}"
    MaxClients {{ max_clients }}
    

    Using the Role

    # filepath: site.yml
    ---
    - hosts: webservers
      roles:
        - role: webserver
          vars:
            http_port: 8080
            max_clients: 200
    

    Role Dependencies Example

    # filepath: roles/webapp/meta/main.yml
    ---
    dependencies:
      - role: webserver
      - role: database
        vars:
          mysql_databases:
            - name: webapp_db
              encoding: utf8
      - role: php
        vars:
          php_version: "7.4"
    

    Complete Role Example

    # filepath: roles/webapp/tasks/main.yml
    ---
    - name: Include OS-specific variables
      include_vars: "{{ ansible_os_family }}.yml"
    
    - name: Install dependencies
      package:
        name: "{{ webapp_packages }}"
        state: present
    
    - name: Deploy application files
      git:
        repo: "{{ webapp_repo }}"
        dest: "{{ webapp_root }}"
        version: "{{ webapp_version }}"
      notify: restart webapp
    
    - name: Configure application
      template:
        src: config.php.j2
        dest: "{{ webapp_root }}/config.php"
      notify: restart webapp
    
    - name: Set permissions
      file:
        path: "{{ webapp_root }}"
        owner: "{{ webapp_user }}"
        group: "{{ webapp_group }}"
        mode: '0755'
        recurse: yes
    
    # filepath: roles/webapp/defaults/main.yml
    ---
    webapp_repo: https://github.com/company/webapp.git
    webapp_version: main
    webapp_root: /var/www/webapp
    webapp_user: apache
    webapp_group: apache
    

    Remember to test roles in development before deploying to production.


    03_02 Installing and Using Ansible Roles

    Installing Roles

    # filepath: /examples/commands.sh
    # Install role from Galaxy
    ansible-galaxy install geerlingguy.nginx
    
    # Install specific version
    ansible-galaxy install geerlingguy.mysql,2.9.0
    
    # Install multiple roles from requirements file
    ansible-galaxy install -r requirements.yml
    
    # filepath: /examples/requirements.yml
    ---
    - src: geerlingguy.nginx
      version: 3.1.0
      name: nginx
    
    - src: geerlingguy.mysql
      version: 3.3.0
    
    - src: https://github.com/company/ansible-role-app.git
      scm: git
      version: main
      name: custom_app
    

    Using Roles in Playbooks

    # filepath: /examples/site.yml
    ---
    - hosts: webservers
      roles:
        - role: nginx
          vars:
            nginx_port: 8080
        
        - role: mysql
          vars:
            mysql_databases:
              - name: webapp
                encoding: utf8
    
        - role: custom_app
    

    Complete Production Example

    # filepath: /examples/production.yml
    ---
    - name: Configure Production Environment
      hosts: prod_servers
      pre_tasks:
        - name: Update package cache
          dnf:
            update_cache: yes
          changed_when: false
    
      roles:
        - role: common
          tags: always
    
        - role: nginx
          vars:
            nginx_vhosts:
              - listen: "80"
                server_name: "example.com"
                root: "/var/www/example"
          tags: webserver
    
        - role: mysql
          vars:
            mysql_root_password: "{{ vault_mysql_root_password }}"
            mysql_databases:
              - name: production_db
                encoding: utf8mb4
                collation: utf8mb4_general_ci
          tags: database
    
        - role: php
          vars:
            php_memory_limit: "256M"
            php_max_execution_time: 60
          tags: php
    
      post_tasks:
        - name: Verify services
          service:
            name: "{{ item }}"
            state: started
          loop:
            - nginx
            - mysql
            - php-fpm
    
    # filepath: /examples/group_vars/prod_servers/vars.yml
    ---
    nginx_worker_processes: auto
    mysql_max_connections: 200
    php_version: "7.4"
    
    # filepath: /examples/group_vars/prod_servers/vault.yml
    ---
    vault_mysql_root_password: secure_password_here
    

    Remember to encrypt sensitive variables using ansible-vault.


    03_03 Installing and Using Ansible Collections

    Installation Commands

    # filepath: /examples/collection_commands.sh
    # Install single collection
    ansible-galaxy collection install community.general
    
    # Install from requirements file
    ansible-galaxy collection install -r requirements.yml
    
    # Install specific version
    ansible-galaxy collection install community.mysql:2.3.0
    

    Requirements File

    # filepath: /examples/requirements.yml
    ---
    collections:
      - name: community.general
        version: '>=3.0.0'
      - name: ansible.posix
        version: '>=1.0.0'
      - name: community.mysql
        version: '>=2.0.0'
    

    Using Collections

    # filepath: /examples/playbook.yml
    ---
    - hosts: webservers
      collections:
        - community.general
        - ansible.posix
      
      tasks:
        - name: Configure firewall
          ansible.posix.firewalld:
            service: http
            permanent: yes
            state: enabled
    
        - name: Install package
          community.general.pacman:
            name: nginx
            state: present
    

    Complete Production Example

    # filepath: /examples/production_stack.yml
    ---
    - name: Deploy Production Stack
      hosts: production
      collections:
        - community.general
        - community.mysql
        - ansible.posix
      
      tasks:
        - name: Configure MySQL
          community.mysql.mysql_db:
            name: production_db
            state: present
            login_unix_socket: /var/run/mysqld/mysqld.sock
    
        - name: Setup user
          community.mysql.mysql_user:
            name: webapp
            password: "{{ mysql_password }}"
            priv: 'production_db.*:ALL'
            state: present
    
        - name: Configure SELinux
          ansible.posix.seboolean:
            name: httpd_can_network_connect_db
            state: yes
            persistent: yes
    
        - name: Setup firewall
          ansible.posix.firewalld:
            port: 3306/tcp
            permanent: yes
            state: enabled
    

    Using Multiple Collections

    # filepath: /examples/multi_collection.yml
    ---
    - name: System Configuration
      hosts: all
      collections:
        - ansible.posix
        - community.general
        - community.docker
      
      tasks:
        - name: Install Docker
          community.general.dnf:
            name: docker-ce
            state: present
    
        - name: Start Docker
          ansible.builtin.service:
            name: docker
            state: started
            enabled: yes
    
        - name: Deploy container
          community.docker.docker_container:
            name: webapp
            image: nginx:latest
            ports:
              - "80:80"
    

    Remember to verify collection compatibility with your Ansible version.


    03_04 Using Related Roles and Collections

    Requirements Setup

    # filepath: requirements.yml
    ---
    collections:
      - name: redhat.rhel_system_roles
        version: '>=1.0.0'
      - name: ansible.posix
        version: '>=1.0.0'
    
    roles:
      - name: geerlingguy.mysql
        version: '3.3.0'
      - name: geerlingguy.apache
        version: '3.1.0'
    

    Installation Commands

    # filepath: install_commands.sh
    # Install collections and roles
    ansible-galaxy collection install -r requirements.yml
    ansible-galaxy role install -r requirements.yml
    

    Complete Production Example

    # filepath: site.yml
    ---
    - name: Configure Production Environment
      hosts: production_servers
      collections:
        - redhat.rhel_system_roles
        - ansible.posix
    
      pre_tasks:
        - name: Check requirements
          ansible.builtin.assert:
            that:
              - ansible_distribution == "RedHat"
              - ansible_distribution_major_version == "8"
    
      roles:
        - role: redhat.rhel_system_roles.storage
          vars:
            storage_pools:
              - name: data
                disks:
                  - /dev/sdb
                volumes:
                  - name: mysql
                    size: 10g
                    fs_type: xfs
                    mount_point: /var/lib/mysql
    
        - role: geerlingguy.mysql
          vars:
            mysql_databases:
              - name: webapp
                encoding: utf8mb4
                collation: utf8mb4_general_ci
            mysql_users:
              - name: webapp_user
                password: "{{ vault_mysql_password }}"
                priv: "webapp.*:ALL"
    
        - role: redhat.rhel_system_roles.network
          vars:
            network_connections:
              - name: eth0
                type: ethernet
                ip:
                  address:
                    - 192.168.1.100/24
    
        - role: geerlingguy.apache
          vars:
            apache_vhosts:
              - servername: "example.com"
                documentroot: "/var/www/html"
    
      tasks:
        - name: Configure SELinux
          ansible.posix.seboolean:
            name: httpd_can_network_connect_db
            state: yes
            persistent: yes
    
        - name: Configure Firewall
          ansible.posix.firewalld:
            service: "{{ item }}"
            permanent: yes
            state: enabled
          loop:
            - http
            - https
            - mysql



    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 *