Bookmark this page

Lab: Managing Task Execution

  • Optimize the execution of plays and tasks in a playbook by selectively escalating privileges, configuring when tasks run, optimizing it for speed, and adding tags to specify that selected parts of it should run.

Outcomes

  • Change privilege escalation to a more secure configuration.

  • Add task hooks and handlers to alter the task behavior.

  • Tag tasks to control their execution.

As the student user on the workstation machine, use the lab command to prepare your system for this exercise.

This command initializes the remote Git repository that you need for this lab. When you are ready to push your changes to the remote repository, use Student@123 as the Git password.

[student@workstation ~]$ lab start task-review

Procedure 6.5. Instructions

  1. Clone the https://git.lab.example.com/student/task-review.git repository to the /home/student/git-repos directory and then create the exercise branch.

    1. From a terminal, create the /home/student/git-repos directory if it does not already exist, and then change into it.

      [student@workstation ~]$ mkdir -p ~/git-repos/
      [student@workstation ~]$ cd ~/git-repos/
    2. Clone the repository and then change to the /home/student/git-repos/task-review/ directory.

      [student@workstation git-repos]$ git clone \
      > https://git.lab.example.com/student/task-review.git
      Cloning into 'task-review'...
      ...output omitted...
      [student@workstation git-repos]$ cd task-review/
    3. Create the exercise branch and check it out.

      [student@workstation task-review]$ git checkout -b exercise
      Switched to a new branch 'exercise'
  2. Modify the ansible.cfg file so that privilege escalation is disabled by default.

    Because all the tasks in the firewall, haproxy, apache, and webapp roles require privilege escalation, enable privilege escalation at the play level in the deploy_apache.yml, deploy_haproxy.yml, and deploy_webapp.yml playbooks.

    1. Edit the ansible.cfg file to remove the become=true entry from the privilege_escalation block, use become=false in the privilege_escalation block, or remove the entire [privilege_escalation] block from the ansible.cfg file. If you choose the last option, then the file contains the following content:

      [defaults]
      inventory=inventory.yml
      remote_user=devops
    2. Enable privilege escalation for the play in the deploy_apache.yml playbook. Add the become: true line to the play.

      ---
      - name: Ensure Apache is deployed
        hosts: web_servers
        force_handlers: true
        gather_facts: false
        become: true
      
        roles:
          # The "apache" role has a dependency on the "firewall" role.
          # The "firewall" role requires the "firewall_rules" variable.
          - role: apache
    3. Enable privilege escalation for the play in the deploy_haproxy.yml playbook. Add the line become: true to the play.

      ---
      - name: Ensure HAProxy is deployed
        hosts: lb_servers
        force_handlers: true
        gather_facts: false
        become: true
      
        roles:
          # The "haproxy" role has a dependency on the "firewall" role.
          # The "firewall" role requires the "firewall_rules" variable.
          - role: haproxy
    4. Enable privilege escalation for the play in the deploy_webapp.yml playbook. Add the line become: true to the play.

      ---
      - name: Ensure Web App is deployed
        hosts: web_servers
        gather_facts: false
        become: true
        vars:
          - webapp_version: v1.0
      
        roles:
          - role: webapp
  3. In the deploy_haproxy.yml playbook, add a copy task that runs before any other task in the play. That task must write the text Playbook site.yml ready to start to the /tmp/site.ready file on the servers in the lb_servers group.

    1. Edit the deploy_haproxy.yml file. In the play in that file, add a pre_tasks block consisting of a copy task that creates a /tmp/site.ready file containing the text Playbook site.yml ready to start. If desired, then you can add a newline character to the end of the text string. The modified file contains the following content:

      ---
      - name: Ensure HAProxy is deployed
        hosts: lb_servers
        force_handlers: true
        gather_facts: false
        become: true
      
        pre_tasks:
          - name: Setting the maintenance message
            ansible.builtin.copy:
              dest: /tmp/site.ready
              content: "Playbook site.yml ready to start\n"
      
        roles:
          # The "haproxy" role has a dependency on the "firewall" role.
          # The "firewall" role requires the "firewall_rules" variable.
          - role: haproxy
  4. Add a handler to the haproxy role that writes the message Reloaded to the /tmp/haproxy.status file. Notify the handler if the task that uses the template module in the haproxy role reports that the state of the system changed. Use haproxy filehandler as the name of the handler.

    1. Edit the roles/haproxy/handlers/main.yml file and add the handler that copies the text to the file. If desired, then you can add a newline character to the end of the text string. The modified file contains the following content:

      ---
      # handlers file for haproxy
      
      - name: restart haproxy
        ansible.builtin.service:
          name: haproxy
          state: restarted
      
      - name: reload haproxy
        ansible.builtin.service:
          name: haproxy
          state: reloaded
      
      - name: haproxy filehandler
        ansible.builtin.copy:
          dest: /tmp/haproxy.status
          content: "Reloaded\n"
    2. Edit the roles/haproxy/tasks/main.yml file and modify the Ensure haproxy configuration is set task so that it notifies the haproxy filehandler handler if the task reports that it changed the current system. Because the modified task notifies two handlers, the existing reload haproxy handler must be moved to a separate line. The modified file contains the following content:

      ---
      # tasks file for haproxy
      
      - name: Ensure haproxy packages are present
        ansible.builtin.yum:
          name:
            - haproxy
            - socat
          state: present
      
      - name: Ensure haproxy is started and enabled
        ansible.builtin.service:
          name: haproxy
          state: started
          enabled: true
      
      - name: Ensure haproxy configuration is set
        ansible.builtin.template:
          src: haproxy.cfg.j2
          dest: /etc/haproxy/haproxy.cfg
          owner: root
          group: root
          mode: 0644
        notify:
          - reload haproxy
          - haproxy filehandler
  5. Add the apache_installer tag to the yum task in the apache role.

    1. Edit the roles/apache/tasks/main.yml file and add the apache_installer tag to the yum task. The modified file contains the following content:

      ---
      # tasks file for apache
      
      - name: Ensure httpd packages are installed
        ansible.builtin.yum:
          name: "{{ item }}"
          state: present
        loop:
          - httpd
          - php
          - git
          - php-mysqlnd
        tags: apache_installer
      
      - name: Ensure SELinux allows httpd connections to a remote database
        ansible.posix.seboolean:
          name: httpd_can_network_connect_db
          state: true
          persistent: true
      
      - name: Ensure httpd service is started and enabled
        ansible.builtin.service:
          name: httpd
          state: started
          enabled: true
  6. Enable the timer and profile_tasks callback plug-ins for the playbook. The two plug-ins are part of the ansible.posix collection. If desired, then you can specify the FQCNs for the callback plug-ins.

    1. Edit the ansible.cfg configuration file and add the plug-ins to the callbacks_enabled directive. The modified file contains the following content:

      [defaults]
      inventory=inventory
      remote_user=devops
      callbacks_enabled=ansible.posix.timer,ansible.posix.profile_tasks
  7. Use automation content navigator to run the site.yml playbook in stdout mode. Analyze the output to find the task that uses the most time.

    1. Run the site.yml playbook in stdout mode. Your output looks similar to the following.

      [student@workstation task-review]$ ansible-navigator run site.yml -m stdout
      ...output omitted...
      PLAY RECAP *********************************************************************
      servera.lab.example.com    : ok=8    changed=8    unreachable=0    failed=0 ...
      serverb.lab.example.com    : ok=5    changed=4    unreachable=0    failed=0 ...
      serverc.lab.example.com    : ok=5    changed=4    unreachable=0    failed=0 ...
      Playbook run took 0 days, 0 hours, 0 minutes, 50 seconds
      Monday 07 November 2022  21:27:18 +0000 (0:00:00.788)       0:00:50.513 *******
      ===============================================================================
      apache : Ensure httpd packages are installed --------------------------- 25.32s
      haproxy : Ensure haproxy packages are present --------------------------- 4.55s
      haproxy : reload haproxy ------------------------------------------------ 3.81s
      haproxy : haproxy filehandler ------------------------------------------- 3.60s
      firewall : reload firewalld --------------------------------------------- 2.25s
      ...output omitted...
    2. The previous output sorted the tasks based on how long it took for each task to complete. The following task took the most time:

      apache : Ensure httpd packages are installed --------------------------- 25.32s
  8. Refactor the most expensive task to make it more efficient. When done, run the cleanup_apache.yml playbook to clean up the web servers so that you can compare the results. To verify the changes, run the site.yml playbook with an appropriate tag so that you only run the modified task.

    1. Identify the file containing the Ensure httpd packages are installed task. The -R option performs a recursive search and the -l option restricts the output to only show the file name. In addition to the roles/apache/tasks/main.yml file, your output displays one or more site-artifact files.

      [student@workstation task-review]$ grep -Rl 'Ensure httpd packages are installed'
      roles/apache/tasks/main.yml
      ...output omitted...
    2. Edit the roles/apache/tasks/main.yml task file to remove the loop from the yum task and instead install all the packages in one transaction. The modified file contains the following content:

      ---
      # tasks file for apache
      
      - name: Ensure httpd packages are installed
        ansible.builtin.yum:
          name:
            - httpd
            - php
            - git
            - php-mysqlnd
          state: present
        tags: apache_installer
      
      - name: Ensure SELinux allows httpd connections to a remote database
        ansible.posix.seboolean:
          name: httpd_can_network_connect_db
          state: true
          persistent: true
      
      - name: Ensure httpd service is started and enabled
        ansible.builtin.service:
          name: httpd
          state: started
          enabled: true
    3. Run the cleanup_apache.yml playbook to clean up the web servers.

      [student@workstation task-review]$ ansible-navigator run cleanup_apache.yml \
      > -m stdout
      ...output omitted...
    4. Use automation content navigator to run the site.yml playbook with the apache_installer tag in stdout mode. Verify that the Ensure httpd packages are installed task takes less time to complete.

      [student@workstation task-review]$ ansible-navigator run site.yml \
      > --tags apache_installer -m stdout
      ...output omitted...
      PLAY RECAP *********************************************************************
      serverb.lab.example.com    : ok=1    changed=1    unreachable=0    failed=0 ...
      serverc.lab.example.com    : ok=1    changed=1    unreachable=0    failed=0 ...
      Playbook run took 0 days, 0 hours, 0 minutes, 15 seconds
      Monday 07 November 2022  21:56:20 +0000 (0:00:14.971)       0:00:15.060 *******
      ===============================================================================
      apache : Ensure httpd packages are installed --------------------------- 14.97s
  9. Commit and push your changes to the remote Git repository.

    1. Add the changed files, commit the changes, and push them to the Git repository. If prompted, then use Student@123 as the Git password.

      [student@workstation task-review]$ git add .
      [student@workstation task-review]$ git commit -m "Lab updates"
      [exercise 0a55370] Lab updates
       7 files changed, 19 insertions(+), 10 deletions(-)
      [student@workstation task-review]$ git push -u origin exercise
      Password for 'https://student@git.lab.example.com': Student@123
      ...output omitted...

Evaluation

As the student user on the workstation machine, use the lab command to grade your work. Correct any reported failures and rerun the command until successful.

[student@workstation ~]$ lab grade task-review

Finish

On the workstation machine, change to the student user home directory and use the lab command to complete this exercise. This step is important to ensure that resources from previous exercises do not impact upcoming exercises.

[student@workstation ~]$ lab finish task-review

This concludes the section.

Revision: do374-2.2-82dc0d7