1、 控制提权

Ansible playbook 能实现多种不同方式的提权操作,提权的级别取决于你打算控制的级别,ansible使用命令或连接参数,在play、role、block和tasks中,都可以设置提权,设置提权的命令有:become、become_user、become_method和become_flags

1.1 配置提权方式

如果你需要通过become参数进行提权,可以在ansible.cfg文件中设置become=true设置提权

配置文件 命令行 说明
become --become或-b 设置提权
become_method --become-method=提权方式 提权方式
become_user --become-user=用户 提权用户
become_password --ask-become-pass或-K 提权用户密码

1.2 在play中设置提权

可在playbook中每个play通过设置提权参数become:true的方式进行,play提权应该最小提权方式(需要提权再提权)

---
- name: 提权管理
  beceom: true
  tasks:
    - name: 显示用户ID
      debug:
        var: ansible_user_id
        
- name: 不提权管理
    hosts: webservers
    become: false
      debug:
      var: ansible_user_id
# 通过配置文件设置提权
[privilege_escalation]
become=true
become_method=sudo
become_user=root
become_password="XX"
---
- name: 通过配置文件管理
  hosts: webservers
  tasks:
      debug:
      var: ansible_user_id

1.3 在task中提权

可在task中设置提权参数

---
- name: task配置提权
  hosts: all
  become: false
  tasks:
    - name: task提权
      yum:
        name: httpd
        state: present
      become: yes
      
    - name: 查看服务
      shell: "systemctl status httpd"
      become: false

1.4 在Block块中配置提权

可以针对一组逻辑块进行整体的提权操作,相比task,范围更大,可以整体控制become状态

---
- name: Block块中配置提权
  hosts: all
  become: false
  tasks:
    - block:
      - name: task提权
        yum:
          name: httpd
          state: present
        become: yes
      
      - name: 查看服务
        shell: "systemctl status httpd"
    become: yes

1.5 在Role中配置提权

如果role中become没有开启,可以在roles下配置提权选项进行提权

---
- name: 在role中配置提权
  hosts: all
  roles:
    - role: apache
      become: true

1.6 配置提权变量

可以通过在配置文件中设置参数或使用提权变量在设置提权

配置文件 或 playbook选项 连接变量
become ansible_become
become_method ansible_become_method
become_user ansible_become_user
become_password ansible_become_pass

1.6.1 针对主机组

可以通过设置变量的方式对主机组进行批量提权

webservers:
  hosts:
    servera.lab.example.com:
    serverb.lab.example.com:
  vars:
    ansible_become: true

1.6.2 针对单个主机

可以通过设置变量的方式真的单个主机提权

webservers:
  hosts:
    servera.lab.example.com:
    	ansible_become: true
    serverb.lab.example.com:

1.6.3 playbook设置提权变量

可以通过在playbook下通过设置变量进行提权

---
- name: 通过变量进行提权
  hosts: all
  vars:
    ansible_become: true
  tasks:
    - name: 安装WEB服务器
        yum:
          name: httpd
          state: present

1.7 控制提权的一些建议

通过控制提权范围,对后期维护十分有帮助,尽管前期编写playbook的时候麻烦一点,怎么有选择的控制提权呢,可以分两种情况

  1. 优先考虑保持playbook的简洁
  2. 运行task的时候保持最小权限运行,不要一次性给出最大权限,后期不利于维护也不安全

初学者编写playbook的时候,很喜欢在配置文件privilege_escalation这里加入become=yes这一个选项,虽然这样执行任何命令都会通过高权限用户,省去了不少麻烦。但是要注意的是,也有很多命令不需要通过root,通过在必要的位置开启提权功能,没必要提权的位置不要开启该功能。虽然在前期编写playbook的时候会麻烦一些,但是后期维护的时候。

一个好的方法是将需要提权的playbook放在文件A,不需要提权的playbook放在文件B,这样可以一次性提权或不提权,减少工作量。

在生产环境下,应该将提权功能关闭,在写playbook的时候,多次测试,到了要提权的时候在task下加入提权选项,不要一次性开启提权,如果遇到了某些主机不用提权,可以通过指定提权变量,禁止运行该主机的时候提权。这也是最困难的,往往需要花费大量时间,不过后期维护起来将会带来非常不错的感受。

总之:让事情变得简单的情况下,谨慎使用提权,确保安全(别没事乱提权!)

1.8 控制提权练习

1.8.1 题目要求

  1. 开启实验环境
  2. GIT克隆文件:http://git.lab.example.com:8081/git/task-escalation.git
  3. 进入task-escalation目录
    1. 关闭配置文件中提权选项
    2. 编辑roles/firewall/tasks/main.yml,task加入提权操作
    3. 检查并编辑roles/firewall/handlers/main.yml ,在reload haproxy下开启提权
    4. 查看 roles/haproxy/tasks/main.yml ,使用block方式添加提权任务
    5. 编辑roles/haproxy/handlers/main.yml,使用block方式添加提权任务
    6. 编辑roles/apache/tasks/main.yml ,使用block方式添加提权任务
    7. 编辑roles/webapp/tasks/main.yml ,使用block方式添加提权任务
    8. 执行site.yml,测试haproxy服务器起来没有
  4. 实验结束

1.8.2 练习

[workstation ~]# lab task-escalation start 

Setting up workstation for the Guided Exercise: Controlling Privilege Escalation

 · Checking python on remote hosts.............................  SUCCESS
 · Installing git..............................................  SUCCESS
 · Installing tree.............................................  SUCCESS
 · Configuring Git.............................................  SUCCESS
 · Configuring Git credentials.................................  SUCCESS
 · Adding content to Git repo..................................  SUCCESS
[workstation git-repos]# git clone http://git.lab.example.com:8081/git/task-escalation.git
Cloning into 'task-escalation'...
remote: Enumerating objects: 77, done.
remote: Counting objects: 100% (77/77), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 77 (delta 12), reused 0 (delta 0)
Unpacking objects: 100% (77/77), done.
# 检查配置文件,关闭提权功能
[workstation task-escalation (master)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops

[privilege_escalation]
become=true
become_method=sudo
become_user=root
become_ask_pass=false
[workstation task-escalation (master)]# vim ansible.cfg 
[workstation task-escalation (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops

[privilege_escalation]
# become=true
# become_method=sudo
# become_user=root
# become_ask_pass=false
# 编辑roles/firewall/tasks/main.yml,task加入提权操作
[workstation task-escalation (master *)]# cat roles/firewall/tasks/main.yml 
---
# tasks file for firewall

- name: Ensure Firewall Sources Configuration
  firewalld:
    source: "{{ item.source if item.source is defined else omit }}"
    zone: "{{ item.zone if item.zone is defined else omit }}"
    permanent: true
    state: "{{ item.state | default('enabled') }}"
    service: "{{ item.service if item.service is defined else omit }}"
    immediate: true
    port: "{{ item.port if item.port is defined else omit }}"
  loop: "{{ firewall_rules }}"
  notify: reload firewalld
[workstation task-escalation (master *)]# vim roles/firewall/tasks/main.yml 
[workstation task-escalation (master *)]# cat roles/firewall/tasks/main.yml 
---
# tasks file for firewall

- name: Ensure Firewall Sources Configuration
  firewalld:
    source: "{{ item.source if item.source is defined else omit }}"
    zone: "{{ item.zone if item.zone is defined else omit }}"
    permanent: true
    state: "{{ item.state | default('enabled') }}"
    service: "{{ item.service if item.service is defined else omit }}"
    immediate: true
    port: "{{ item.port if item.port is defined else omit }}"
  loop: "{{ firewall_rules }}"
  notify: reload firewalld
  become: true
# 检查并编辑roles/firewall/handlers/main.yml  ,在reload haproxy下开启提权
[workstation task-escalation (master *)]# cat roles/firewall/handlers/main.yml 
---
# handlers file for firewall

- name: reload firewalld
  service:
    name: firewalld
    state: reloaded


[workstation task-escalation (master *)]# vim roles/firewall/handlers/main.yml 
[workstation task-escalation (master *)]# cat roles/firewall/handlers/main.yml 
---
# handlers file for firewall

- name: reload firewalld
  service:
    name: firewalld
    state: reloaded
  become: true
# 查看 roles/haproxy/tasks/main.yml ,配置提权功能
[workstation task-escalation (master *)]# cat roles/haproxy/tasks/main.yml 
---
# tasks file for haproxy

- name: Ensure haproxy packages are present
  yum:
    name:
      - haproxy
      - socat
    state: present

- name: Ensure haproxy is started and enabled
  service:
    name: haproxy
    state: started
    enabled: true

- name: Ensure haproxy configuration is set
  template:
    src: haproxy.cfg.j2
    dest: /etc/haproxy/haproxy.cfg
    #validate: haproxy -f %s -c -q
  notify: reload haproxy

[workstation task-escalation (master *)]# vim roles/haproxy/tasks/main.yml 

# 使用逻辑块将大量需要提权的区域扩起来
[workstation task-escalation (master *)]# cat roles/haproxy/tasks/main.yml 
---
# tasks file for haproxy

- block:
  - name: Ensure haproxy packages are present
    yum:
      name:
        - haproxy
        - socat
      state: present

  - name: Ensure haproxy is started and enabled
    service:
      name: haproxy
      state: started
      enabled: true

  - name: Ensure haproxy configuration is set
    template:
      src: haproxy.cfg.j2
      dest: /etc/haproxy/haproxy.cfg
      #validate: haproxy -f %s -c -q
    notify: reload haproxy
  become: true
# 编辑roles/haproxy/handlers/main.yml,使用block方式添加提权任务
[workstation task-escalation (master *)]# cat roles/haproxy/handlers/main.yml 
---
# handlers file for haproxy

- name: restart haproxy
  service:
    name: haproxy
    state: restarted

- name: reload haproxy
    service:
      name: haproxy
      state: reloaded
[workstation task-escalation (master *)]# cat roles/haproxy/handlers/main.yml 
---
# handlers file for haproxy

- block:
 - name: restart haproxy
   service:
     name: haproxy
     state: restarted

 - name: reload haproxy
   service:
     name: haproxy
     state: reloaded
  become: true
# 编辑roles/apache/tasks/main.yml ,使用block方式添加提权任务
[workstation task-escalation (master *)]# cat :roles/apache/tasks/main.yml 
---
# tasks file for apache

- name: Ensure httpd packages are installed
  yum:
    name:
      - httpd
      - php
      - git
      - php-mysqlnd
    state: present

- name: Ensure SELinux allows httpd connections to a remote database
  seboolean:
    name: httpd_can_network_connect_db
    state: true
    persistent: true

- name: Ensure httpd service is started and enabled
  service:
    name: httpd
    state: started
    enabled: true

[workstation task-escalation (master *)]# vim roles/apache/tasks/main.yml 
[workstation task-escalation (master *)]# cat roles/apache/tasks/main.yml 
---
# tasks file for apache
- block:
  - name: Ensure httpd packages are installed
    yum:
      name:
        - httpd
        - php
        - git
        - php-mysqlnd
      state: present

  - name: Ensure SELinux allows httpd connections to a remote database
    seboolean:
      name: httpd_can_network_connect_db
      state: true
      persistent: true

  - name: Ensure httpd service is started and enabled
    service:
      name: httpd
      state: started
      enabled: true
  become: true
# 编辑roles/webapp/tasks/main.yml ,使用block方式添加提权任务
[workstation task-escalation (master *)]# cat roles/webapp/tasks/main.yml 
---
# tasks file for webapp

#- name: Copy the code from the repository
#  git:
#    repo: "{{ webapp_repo }}"
#    version: "{{ webapp_version }}"
#    dest: /var/www/html/
#    accept_hostkey: yes
##    key_file: deployment key??

- name: Ensure stub web content is deployed
  copy:
    content: "{{ webapp_message }}. (version {{ webapp_version}})\n"
    dest: /var/www/html/index.html

[workstation task-escalation (master *)]# vim roles/webapp/
defaults/ meta/     tasks/    tests/    
[workstation task-escalation (master *)]# cat roles/webapp/tasks/main.yml 
---
# tasks file for webapp

#- name: Copy the code from the repository
#  git:
#    repo: "{{ webapp_repo }}"
#    version: "{{ webapp_version }}"
#    dest: /var/www/html/
#    accept_hostkey: yes
##    key_file: deployment key??

- name: Ensure stub web content is deployed
  copy:
    content: "{{ webapp_message }}. (version {{ webapp_version}})\n"
    dest: /var/www/html/index.html
  become: true
# 执行site.yml
[workstation task-escalation (master *)]# ansible-playbook site.yml 

PLAY [Ensure HAProxy is deployed] *****************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] *******************************************************************************************
changed: [servera.lab.example.com] => (item={'port': '80/tcp'})

TASK [haproxy : Ensure haproxy packages are present] **********************************************************************************************
changed: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy is started and enabled] ********************************************************************************************
changed: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy configuration is set] **********************************************************************************************
changed: [servera.lab.example.com]

RUNNING HANDLER [firewall : reload firewalld] *****************************************************************************************************
changed: [servera.lab.example.com]

RUNNING HANDLER [haproxy : reload haproxy] ********************************************************************************************************
changed: [servera.lab.example.com]

PLAY [Ensure Apache is deployed] ******************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] *******************************************************************************************
changed: [serverc.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})
changed: [serverb.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})

TASK [apache : Ensure httpd packages are installed] ***********************************************************************************************
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

TASK [apache : Ensure SELinux allows httpd connections to a remote database] **********************************************************************
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

TASK [apache : Ensure httpd service is started and enabled] ***************************************************************************************
changed: [serverb.lab.example.com]
changed: [serverc.lab.example.com]

RUNNING HANDLER [firewall : reload firewalld] *****************************************************************************************************
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

PLAY [Ensure Web App is deployed] *****************************************************************************************************************

TASK [webapp : Ensure stub web content is deployed] ***********************************************************************************************
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

PLAY RECAP ****************************************************************************************************************************************
servera.lab.example.com    : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb.lab.example.com    : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

# 测试haproxy服务器起来没有
[workstation task-escalation (master *)]# curl servera
Hello from serverb.lab.example.com. (version v1.0)
[workstation task-escalation (master *)]# curl servera
Hello from serverc.lab.example.com. (version v1.0)
[workstation task-escalation (master *)]# curl servera
Hello from serverb.lab.example.com. (version v1.0)
[workstation task-escalation (master *)]# curl servera
Hello from serverc.lab.example.com. (version v1.0)
# 结束实验
[workstation task-escalation (master *)]# lab task-escalation finish 

Cleaning up the lab on workstation:

 · Cloning the task-escalation repository......................  SUCCESS
 · Retrieving cleanup playbook.................................  SUCCESS
 · Executing cleanup playbook..................................  SUCCESS
 · Removing temporary repository clone.........................  SUCCESS

2、 控制task执行

2.1 控制执行顺序

在play中,ansible总是先执行role,不管role在最前面还是最后面,总是优先执行。

---
- name: 安装apache
  hosts: servera
  gather_facts: no
  
  tasks:
    - name: 开启防火墙
      firewalld:
        service http
        permanent: yes
        state: enabled
        
  roles:
    - role: apache

最佳实践认为:为了易读性,先写role,再写task,这样看着就很舒服。

2.2 使用import或include导入roles和task

ansible允许使用import或者include导入task,playbook,roles,通过import或者include这类参数,可以将role当成一个task执行,这样就不用担心roles影响play的执行了。

  • include_role模块是动态导入role
  • import_role模块是静态导入role
---
- name: 在task执行role
  hosts: all
  tasks:
    - name: 在task中执行role
      debug:
        msg: 'first task'

    - name: 使用include导入role
      include_role:
        name: role1
   
   - name: 在task执行role
     debug: 
       msg: 'second task'

2.3 使用Pre和Post task

  • pre_task选项,在task执行之前执行一些task(优先级高于role)
  • post_task选项,在task执行之后执行一些task
---
- name: 创建新应用版本
  hosts: webserver
  
  # 提前执行tasks
  pre_tasks:
    - name: disabling nagios for this host
      nagios:
        action: disable_alerts
        hosts: "{{ inventor_hostname }}"
        services: http
      delegate_to: nagios-srv
  roles:
    - role: deploy-content

  tasks:
    - name: 重启memcached
      service:
        name: memcached
        status: restarted
      notify: Notifying the support team
      
      - name: 验证新的部署
        uri:
          url: "http://{{ inventory_hostname }}/healthz"
          return_content: yes
        register: result
        failed_when: "'OK' not in result.content"

  # 最后执行tasks
  post_tasks:
    - name: 在主机上开启Nagios
      nagios:
        action: enable_alerts
        host: "{{ inventory_hostname }}"
        services: http
      delegate_to: http
      
  handlers:
    # 发送消息到支持的team
    # 每次重启memcached服务时
    - name: Notifying the support team
      slack:
        token: xoxb-1234-56789abcdefghijklmnop
        msg: 'Memcached on {{ inventory_hostname }} restarted'
      delegate_to: localhost
      become: false

2.4 回顾执行顺序

  • pre_tasks
    • handlers在pre_tasks使用notify声明
  • roles
  • tasks
    • handlers在tasks使用notify声明
  • post_tasks
    • handlers在post_tasks使用notify声明

ansible执行期间handlers最后会执行,如果需要强制执行handlers,可以使用meta模块,声明flush_handlers,手工控制handlers执行。

在本案例中,配置文件更新后需要重启服务,可以在更新配置文件之后,使用meta模块声明handlers,手工控制handlers执行。在收到notify通知后,直接重启api,避免后面task因为没有收到最新api信息而导致报错。

- name: restart api server
  meta: flush_handlers
  hosts: app_servers
  tasks:
    - name: deploying the configuration file
      template:
        src: api-server.cfg.j2
        dest: /etc/api-server.cfg
      notify: restart api serer
        
    - name: running all notified handlers
      meta: flush_handlers
        
    - name: asking the api server to rebuild its internal cache
      uri:
        url: "https://{{ inventory_hostname }}/rest/api/2/cache/"
        method: POST
        force_basic_auth: yes
        user: admin
        password: redhat
        body_format: json
        body:
          type: data
          delay: 0
        status_code: 201

      handlers:
        - name: restart api server
          service:
            name: api-server
            state: restarted
            enabled: yes

在play中,handlers具有全局范围,一个play能声明handlers定义在role里,一个role能声明一个handler定义在其他的role或者play中。

Ansible总是按照handlers部分中列出的顺序运行已通知的handlers,而不是按照通知的顺序。

2.5 监听handlers

除了收到task通知外,一个handlers也能”subscribe“(订阅)一个具体的通知。在默认情况下,handlers通过声明名称与之匹配才执行,每个handlers必须有一个唯一名称,同时触发多个handlers的唯一方法,是每个都有“subscribe”的通知名称。

---
- name: testing the listen directive
  hosts: localhost
  gather_facts: no
  become: no
  
  tasks:
    - debug:
        msg: trigerring the handlers
      notify: My handlers
      changed_when: true
      
  handlers:
    # listening to the "my handlers" event
    - name: listening to a notification
      debug:
        msg: First handler was notification
      listen: My handlers
      
    # as an example, this handler is also triggered because
    # its name matches the notification, but no two handlers
    # can have the same name
    - name: My handlers
      debug:
        msg: second handler was notified
[root@CentOS-Stream9 ansible (master)]# ansible-playbook handler_listen.yml 

PLAY [testing the listen directive] ********************************************************************************************************************

TASK [debug] *******************************************************************************************************************************************
changed: [localhost] => {
    "msg": "trigerring the handlers"
}

RUNNING HANDLER [listening to a notification] **********************************************************************************************************
ok: [localhost] => {
    "msg": "First handler was notification"
}

RUNNING HANDLER [My handlers] **************************************************************************************************************************
ok: [localhost] => {
    "msg": "second handler was notified"
}

PLAY RECAP *********************************************************************************************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

运行playbook的时候可以发现,使用listen关键字监听handlers,可以在执行playbook的时候,发现notify通知后,一并执行handlers监听的任务(其他的任务),监听指令有助于帮助理解task的作用。通过listen的方式,可以监听role,一个role能记录事件发生时通知特定的handlers,在role之外,其他role或者play可能使用notify方式来运行handlers。

例如一个role当需要重启服务的时候会通知一个handlers。当ansible重启服务的时候,在你的playbook中,你可以定义一个handler来监听那个role的通知然后执行额外的task,比如给一个监控工具发送消息或者重启一个单独的服务。

例如,你可以创建一个role来检查SSL证书的有效期,如果过期了需要通知handlers来更新过期的证书。然后你在playbook中,你可以调用这个role来检查web服务器的证书有效期,然后创建一个handlers来监听这个通知,如果role更新了证书,那么playbook定义的handlers就是重启httpd服务。这样讲就完成了一个很好的配合。

2.6 处理handers通知

总结,一个task可以使用两种方式通知多个handlers:

  • 可以通知一个handlers的列表
  • 可以通知一个handlers的名字,然后多个handlers监听被通知handlers的名字。

哪种方法更好呢?如果handlers需要像多个需要被重用的task那样使用,那么最简单的方式是使用第二种方法,使用listen参数。因为,你只需要改变handlers来标记是否handlers的task需要被使用。

当通知大量的handlers的时候,使用listen参数是一个有用的方法。不需要通知每个handlers的名字,task只需要发一个通知。ansible触发所有的监听那个通知的handlers。这种方法,你可以只更改handlers而不需要更新task。

如果使用第一种方法,你就必须要找到然后编辑每个有关的task去更改通知的handlers列表。你还必须要确保每个通知的handlers都存在。

2.7 控制主机执行顺序

Ansible根据hosts中指定主机确定task命令作用于那些主机上,默认情况下,ansible2.4以后可以通过inventory顺序执行,你也可以使用order关键字改变主机执行顺序。

# 以下案例按照字母顺序执行servera、serverb……
---
- name: test host order
  hosts: web_server
  order: sorted
  
  tasks:
    - name: creating a test file in /tmp
      copy:
        content: 'this is a sample file'
        dest: /tmp/test.out   
order参数 执行顺序说明
Inventory 按照Inventory的顺序执行
reserve_Inventory Inventory反向顺序
sorted 按照字母顺序执行
reverse_sorted 字母反向顺序
shuffle 随机执行

如果没有定义order参数,ansible执行task会合并执行,比如有3台主机,执行顺序出现2、1、3,这样的原因可能是CPU不同导致的。

2.8 控制task执行练习

2.8.1 题目要求

  1. 开启实验
  2. 本实验记录登陆信息,要求在任务之前和之后新增和移除登陆信息
    1. 编辑deploy_haproxy.yml文件
    2. 新增pre_tasks,使用copy模块在/etc/motd.d/maintenance文件中写入Maintenance in progress\n
    3. 新增post_tasks,使用file模块移除/etc/motd.d/maintenance文件
  3. 查看roles/haproxy/handlers/main.yml文件,要求重启了haproxy之后,发送一封邮件到"student@workstation.lab.example.com"下,邮件内容包括harpoxy主机的IP地址信息。
    1. 查看roles/haproxy/handlers/main.yml文件
    2. 编辑deploy_haproxy.yml文件,编写handlers,使用mail模块发邮件和syslogger模块记录日志,通过listen关键字监听reload haproxy
    3. 运行deploy_haproxy.yml,使用mail命令测试,查看日志是否有邮件信息
  4. 结束实验

2.8.2 练习

[workstation ~]# lab task-execution start 

Setting up workstation for the Guided Exercise: Controlling Task Execution

 · Checking python on remote hosts.............................  SUCCESS
 · Removing HAProxy on servera.................................  SUCCESS
 · Removing the HAProxy configuration file on servera..........  SUCCESS
 · Installing postfix and mailx on workstation.................  SUCCESS
 · Starting postfix on workstation.............................  SUCCESS
 · Downloading starter project.................................  SUCCESS
 · Downloading solution project................................  SUCCESS
[workstation ~]# cd DO447/labs/task-execution/
[workstation task-execution]# ls
ansible.cfg  appservers.yml  deploy_apache.yml  deploy_haproxy.yml  deploy_webapp.yml  group_vars  inventory  roles  site.yml
[workstation task-execution]# cat deploy_haproxy.yml 
- name: Ensure HAProxy is deployed
  hosts: lb_servers
  force_handlers: True

  roles:
    # The "haproxy" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: haproxy
[workstation task-execution]# cat deploy_haproxy.yml 
- name: Ensure HAProxy is deployed
  hosts: lb_servers
  force_handlers: True

  pre_tasks:
    - name: setting the maintenance message
      copy:
        dest: /etc/motd.d/maintenance
        content: "Maintenance in progress\n"

  roles:
    # The "haproxy" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: haproxy


  post_tasks:
    - name: Removing the maintenance message
      file:
        path: /etc/motd.d/maintenance
        state: absent
[workstation task-execution]# cat deploy_haproxy.yml 
- name: Ensure HAProxy is deployed
  hosts: lb_servers
  force_handlers: True

  pre_tasks:
    - name: setting the maintenance message
      copy:
        dest: /etc/motd.d/maintenance
        content: "Maintenance in progress\n"

  roles:
    # The "haproxy" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: haproxy


  post_tasks:
    - name: Removing the maintenance message
      file:
        path: /etc/motd.d/maintenance
        state: absent

  handlers:
      - name: send an email to student
        mail:
          subject: "HAProxy reloaded on {{ inventory_hostname }}"
          to: student@workstation.lab.example.com
        delegate_to: localhost
        become: false
        listen: reload haproxy

      - name: Logging a message to syslog 
        syslogger:
          msg: "HAProxy reloaded on {{ inventory_hostname }}"
        delegate_to: localhost
        become: false
        listen: reload haproxy
[workstation task-execution]# ansible-playbook deploy_haproxy.yml 

PLAY [Ensure HAProxy is deployed] **********************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************
ok: [servera.lab.example.com]

TASK [setting the maintenance message] *****************************************************************************************************************
ok: [servera.lab.example.com]

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
ok: [servera.lab.example.com] => (item={'port': '80/tcp'})

TASK [haproxy : Ensure haproxy packages are present] ***************************************************************************************************
ok: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy is started and enabled] *************************************************************************************************
ok: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy configuration is set] ***************************************************************************************************
ok: [servera.lab.example.com]

TASK [Removing the maintenance message] ****************************************************************************************************************
changed: [servera.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************
servera.lab.example.com    : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

# 发送邮件回显消息
[workstation task-execution]# mail
Heirloom Mail version 12.5 7/5/10.  Type ? for help.
"/var/spool/mail/student": 1 message 1 new
>N  1 root@workstation.lab  Thu Oct 13 15:08  27/1100  "HAProxy reloaded on servera.lab.example.com"
& 
Message  1:
From root@workstation.lab.example.com  Thu Oct 13 15:08:40 2022
Return-Path: <root@workstation.lab.example.com>
X-Original-To: student@workstation.lab.example.com
Delivered-To: student@workstation.lab.example.com
Content-Type: multipart/mixed; -charset="utf-8"; boundary="===============6772219814566406897=="
From: root@workstation.lab.example.com
Subject: HAProxy reloaded on servera.lab.example.com
X-Mailer: Ansible mail module
To: student@workstation.lab.example.com
Cc: 
Date: Thu, 13 Oct 2022 15:08:40 +0800 (CST)
Status: R

Part 1:
Content-Type: text/plain; charset="utf-8"

HAProxy reloaded on servera.lab.example.com

& 
At EOF
& 
At EOF
& Held 1 message in /var/spool/mail/student
You have mail in /var/spool/mail/student

# 过滤日志信息
[workstation task-execution]# sudo grep "HAProxy reloaded" /var/log/messages
[sudo] password for student: 
Oct 13 15:08:39 workstation platform-python[15676]: ansible-mail Invoked with subject=HAProxy reloaded on servera.lab.example.com to= host=localhost port=25 sender=root cc=[] bcc=[] attach=[] headers=[] charset=utf-8 subtype=plain secure=try timeout=20 username=None password=NOT_LOGGING_PARAMETER body=None
Oct 13 15:08:40 workstation platform-python[15698]: ansible-syslogger Invoked with msg=HAProxy reloaded on servera.lab.example.com priority=info facility=daemon log_pid=False
Oct 13 15:08:40 workstation ansible_syslogger[15698]: HAProxy reloaded on servera.lab.example.com

# 实验结束
[workstation task-execution]# lab task-execution finish 

Cleaning up the lab on workstation:

 · Deleting student's emails...................................  SUCCESS
 · Removing postfix and mailx from workstation.................  SUCCESS
 · Executing cleanup playbook..................................  SUCCESS
 · Cleaning lab files..........................................  SUCCESS
 · Cleaning solutions files....................................  SUCCESS
Lab finished.

3、 ansible的资源标记

在一些时候,执行比较大型的、复杂的playbook的时候,你可能只需要运行一部分play,这个时候可以通过tags关键字,对资源打上标记,通过tags的控制,可以忽略或者运行tasks。

3.1 标记可用资源

在执行playbook的时候,使用--tags选项过滤playbook和执行特定标记的资源。tags示例如下:

  • 在tasks层面通过tags控制
- name: install application
  hosts: dbservers
  vars:
    packages:
      - postfix
      - mariadb-server
  tasks:
    - name: ensure that packages are installed
      yum:
        name: "{{ packages }}"
        state: installed
      tags:
        - install
  • 在play层面通过tags控制
- name: setup web services
  hosts: dbservers
  tags:
    - setup
  tasks:
    - name: ensure that packages are installed
      yum:
        name: httpd
        state: present
  • 在include_tasks上通过tags控制
tasks:
  - name: include common web service tasks
    include_tasks: common.yml
    tags:
      - webproxy
      - webserver
  • 在roles上通过tags控制
- name: setup web services
  roles:
    - role: databases
  tags:
    - production
    - staging
  • 在block上通过tags控制
---
- name: setup httpd service
  hosts: XX
  tasks:
    - name: notify start of process
      debug:
        msg: beginning httpd setup
    - block:
      - name: ensure httpd packages are installed
        yum:
          name:
            - httpd
            - php
            - git
            - php-myselnd
          state: present
          
      - name: ensure selinux allows httpd connections to a remote database
        seboolean:
          name: httpd_can_network_connect_db
          state: true
          persistent: true
          
      - name: ensure httpd service is started and enabled
        service:
          name: httpd
          state: started
          enabled: true
      tags:
        - webserver

3.2 管理tag标记

在运行playbook的时候,可以通过命令参数--tags选项对标记tags进行管理,或者使用--skip-tags选项跳过该tags的执行。

命令选项 说明
--tags 执行tags
--skip-tags 跳过tags
# 拿上面一个例子来说
- name: install application
  hosts: dbservers
  vars:
    packages:
      - postfix
      - mariadb-server
  tasks:
    - name: ensure that packages are installed
      yum:
        name: "{{ packages }}"
        state: installed
      tags:
        - install
# 使用--tags参数执行该tag
[workstation ~]# ansible-playbook main.yml --tags install

# 使用--skip-tags
[workstation ~]# ansible-playbook main.yml --skip-tags install

3.3 特殊的TAGS

ansible有特殊资源标记always,这个资源标记默认总是运行,即使它与传递给的标签不匹配,可以使用--skip-tags always这种方式跳过always的执行。默认always会执行所有的tags,never这个特殊标记不会执行tag,你可以通过--tags never这种方式进行设置。

特殊tags 说明
all 运行所有tags(缺省值)
tagged 运行所有标记tag
untagged 运行所有为标记tag

3.4 ansible资源标记练习

3.4.1 题目要求

  1. 开启实验
  2. 在/home/student/git-repos目录下
    1. GIT克隆文件:http://git.lab.example.com:8081/git/task-tagging.git
    2. 进入task-tagging目录
    3. 创建test_webapp.yml文件
    4. 将test_webapp.yml静态导入到site.yml中
    5. 运行site.yml文件,执行tests这个资源标记
    6. 运行site.yml文件,跳过tests这个资源标记
  3. 实验结束

3.4.2 练习

[workstation ~]# lab task-tagging start 

Setting up workstation for the Guided Exercise: Running Selected Tasks

 · Checking python on remote hosts.............................  SUCCESS
 · Installing git..............................................  SUCCESS
 · Installing tree.............................................  SUCCESS
 · Configuring Git.............................................  SUCCESS
 · Configuring Git credentials.................................  SUCCESS
 · Adding content to Git repo..................................  SUCCESS
# git克隆
[workstation git-repos]# git clone http://git.lab.example.com:8081/git/task-tagging.git
Cloning into 'task-tagging'...
remote: Enumerating objects: 56, done.
remote: Counting objects: 100% (56/56), done.
remote: Compressing objects: 100% (42/42), done.
remote: Total 56 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (56/56), done.
[workstation git-repos]# cd task-tagging/
# 编写test_webapp.yml文件,手动制造一个错误并使用tags标记
[workstation task-tagging (master)]# cat test_webapp.yml 
---
- name: web application smoke test 
  hosts: web_servers
  gather_facts: no
  tasks:
    - name: verify content of http://localhost
      uri:
        url: http://localhost
        return_content: yes
      register: test_url
      failed_when: "'Hello from' not in test_url.content"
      tags:
        - tests
# 将test_webapp.yml导入site.yml中
[workstation task-tagging (master *)]# cat site.yml 

- name: Deploy HAProxy
  import_playbook: deploy_haproxy.yml

- name: Deploy Web Server
  import_playbook: deploy_apache.yml

- name: Deploy Web App
  import_playbook: deploy_webapp.yml

- name: test deployed web app
  import_playbook: test_webapp.yml
# 使用tests这个tags
[workstation task-tagging (master *)]# ansible-playbook site.yml --tags tests

PLAY [Ensure HAProxy is deployed] **********************************************************************************************************************

PLAY [Ensure Apache is deployed] ***********************************************************************************************************************

PLAY [Ensure Web App is deployed] **********************************************************************************************************************

PLAY [web application smoke test] **********************************************************************************************************************

TASK [verify content of http://localhost] **************************************************************************************************************
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************
serverb.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
# 跳过tests这个tags
[workstation task-tagging (master *)]# ansible-playbook site.yml --skip-tags tests

PLAY [Ensure HAProxy is deployed] **********************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
ok: [servera.lab.example.com] => (item={'port': '80/tcp'})

TASK [haproxy : Ensure haproxy packages are present] ***************************************************************************************************
ok: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy is started and enabled] *************************************************************************************************
ok: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy configuration is set] ***************************************************************************************************
ok: [servera.lab.example.com]

PLAY [Ensure Apache is deployed] ***********************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
ok: [serverb.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})
ok: [serverc.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})

TASK [apache : Ensure httpd packages are installed] ****************************************************************************************************
ok: [serverc.lab.example.com]
ok: [serverb.lab.example.com]

TASK [apache : Ensure SELinux allows httpd connections to a remote database] ***************************************************************************
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

TASK [apache : Ensure httpd service is started and enabled] ********************************************************************************************
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

PLAY [Ensure Web App is deployed] **********************************************************************************************************************

TASK [webapp : Ensure stub web content is deployed] ****************************************************************************************************
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

PLAY [web application smoke test] **********************************************************************************************************************

PLAY RECAP *********************************************************************************************************************************************
servera.lab.example.com    : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb.lab.example.com    : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=5    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
[workstation task-tagging (master *)]# lab task-tagging finish 

Cleaning up the lab on workstation:

 · Cloning the task-tagging repository.........................  SUCCESS
 · Retrieving cleanup playbook.................................  SUCCESS
 · Executing cleanup playbook..................................  SUCCESS
 · Removing temporary repository clone.........................  SUCCESS

4、 优化playbook执行

随着被管理主机数量的增加,playbook的运行会越来越慢,对于优化playbook的运行显得更加重要了。

4.1 优化基础设施

红帽Ansible引擎的每个版本都增加了增强和改进。运行最新版本的Ansible可能有助于提高你的playbook的速度,因为Ansible的核心组件,特别是与它一起提供的模块是经过时间优化的

从网络的角度来看,您可以进行的一种架构优化是让您的控制节点“接近”被管理节点。Ansible在很大程度上依赖于网络通信和数据传输。控制节点和被管理主机之间的高延迟连接或低带宽会降低plavbooks的执行时间。

  • 使用最新版的ansible
  • 使用稳定版的核心模块
  • 控制节点和被管理节点近一点(网络环境)

4.2 关闭Fact变量收集

每当运行ansible的时候,ansible会自动收集fact变量,如果确定playbook中一定不会使用fact变量,或者一些fact变量可以使用inventory变量替换,这个时候,为了提高运行效率,关闭fact变量收集就十分有必要了。

---
- name: disabling the facts gathering
  hosts: web_servers
  gather_facts: false
  
  tasks:
    - name: print hello
      debug:
        msg: "gather_facts is set to false"
        
# 没有收集facts变量耗时:1.736s
[workstation task-tagging (master *)]# time ansible-playbook speed_facts.yml 

PLAY [disabling the facts gathering] *******************************************************************************************************************

TASK [print hello] *************************************************************************************************************************************
ok: [servera.lab.example.com] => {
    "msg": "gather_facts is set to false"
}
ok: [serverb.lab.example.com] => {
    "msg": "gather_facts is set to false"
}
ok: [serverc.lab.example.com] => {
    "msg": "gather_facts is set to false"
}

PLAY RECAP *********************************************************************************************************************************************
servera.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


real	0m1.736s
user	0m1.470s
sys	0m0.321s

# 收集facts变量耗时:4.819s
[workstation task-tagging (master *)]# time ansible-playbook speed_nofacts.yml 

PLAY [disabling the facts gathering] *******************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

TASK [print hello] *************************************************************************************************************************************
ok: [servera.lab.example.com] => {
    "msg": "gather_facts is set to false"
}
ok: [serverb.lab.example.com] => {
    "msg": "gather_facts is set to false"
}
ok: [serverc.lab.example.com] => {
    "msg": "gather_facts is set to false"
}

PLAY RECAP *********************************************************************************************************************************************
servera.lab.example.com    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb.lab.example.com    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   


real	0m4.819s
user	0m2.892s
sys	0m1.101s

4.3 增加并行数

在ansible运行playbook的时候,默认的并行数量是5,如果管理100台主机的话,执行playbook的时候会非常的慢,如果你的控制节点性能非常好,可以在配置文件或者playbook中设置forks参数,增加并行数,一次执行更多的tasks,提高playbook执行的效率。

[workstation task-tagging (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops
forks=20

4.4 避免在包管理的时候使用循环

很多模块可以传列表项,比如包管理工具yum,可以在name参数下传入列表,这样一次可以传入多个值,提高playbook的执行效率。也有很多模块不支持一次传入多个值,比如service模块,这样要重复开启服务,只能通过循环进行了。

4.4.1 包管理模块

# 直接使用列表
---
- name: install the packages on the web servers
  hosts: web_servers
  become: true
  gather_facts: false
  
  tasks:
    - name: ensure the packages are installed
      yum:
        name:
          - httpd
          - httpd-tools
          - php
          - mariadb
        state: present
# 相当于命令
yum install httpd httpd-tools php mariadb
# 使用循环
---
- name: install the packages on the web servers
  hosts: web_servers
  become: true
  gather_facts: false
  
  tasks:
    - name: ensure the packages are installed
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - http
        - httpd-tools
        - php
        - mariadb
# 相当于命令
yum install httpd
yum install httpd-tools
yum install php
yum install mariadb

4.4.2 查询模块是否支持列表

ansible-doc 模块名

[workstation ~]# ansible-doc yum
...
EXAMPLES:
...
- name: Install a list of packages
  yum:
    name:
      - nginx
      - postgresql
      - postgresql-server
    state: present
...

4.5 使用模版文件

lineinfile模块可以插入或删除行文件,比如修改配置文件,少量的修改还行,不过修改量一大,会十分的繁琐,通过J2模版文件可以在写好模版文件之后,仅需要修改变量就能达到同样目的。

# 通过lineinfile模块编辑配置文件,十分不灵活
---
- name: configure the apache http server
  hosts: web_servers
  become: true
  gathcer_facts: false
  tasks:
    - name: ensure proper configuration of the apache http serer
      lineinfile:
        dest: /etc/httpd/conf/httpd.conf
        regexp: "{{ item.regexy }}"
        line: "{{ item.line }}"
        state: present
      loop:
        - regexp: '^Listen 80$'
          line: 'Listen 8181'
        - regexp: '^Listen 80ServerAdmin root@localhost'
          line: 'ServerAdmin support@example.com'
        - regexp: '^DocumentRoot "/var/www/html"'
          line: 'DocumentRoot "/var/www/web"'
        - regexp: '^<Directory "/var/www/html">'
          line: '<Directory "/var/www/web">'
# 通过J2模版文件,灵活高效
---
- name: configure the apache http server
  hosts: web_servers
  become: true
  gather_facts: false
  
  tasks:
    - name: ensure proper configuration of hte apache http server
      template:
        src: httpd.conf.j2
        dest: /etc/httpd/conf/httpd.conf

4.6 优化SSH连接

建立ssh连接可能是一个缓慢的过程,当一个playbook有很多任务和targes的时候,大量的节点,Ansible建立这些连接的总体时间会显著增加,增加playbook总体执行时间。

为了缓解这个问题,ansible提出了两个解决方案:

  • ControlMaster

    建立额外会话,通过同时建立多个ssh会话可以重用ssh连接,提高playbook的执行效率。

  • ControlPersist

    持久化连接,通过将ssh的连接保存在后台,让第一次执行playbook之后,本地依然与被管理节点进行连接,这样一个长连接的SSH会话,可以重用后面的task,提高playbook的执行效率

# 配置文件对ssh连接进行设置
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

4.7 开启流水线

执行task在远程节点上,ansible执行多个SSH操作进行复制模块和所有的数据到远程节点上去执行这些模块,为了提高你playbook的效率,你可以激活流水线功能(Pipelining)

# 开启流水线功能
[ssh_connection]
pipelining = true

开启流水线功能需要关闭requiretty参数,在RHEL8中,该参数默认关闭,可以在/etc/sudoers文件关闭requiretty这个选项

[workstation ~]# visudo
...
Defaults !requiretty
...

4.8 Playbook执行分析

通过callback插件可以在playbook执行的时候拥有额外的返回值,使用callback查看可以计算playbook的运行时间、在playbook中进行输出。

[workstation task-tagging (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer, profile_tasks, cgroup_perf_recap
# 查看callback插件用法
actionable           shows only items that need attention                                                                                          
aws_resource_actions summarizes all "resource:actions" completed                                                                                   
cgroup_memory_recap  Profiles maximum memory usage of tasks and full execution using cgroups                                                       
cgroup_perf_recap    Profiles system activity of tasks and full execution using cgroups                                                            
context_demo         demo callback that adds play/task context                                                                                     
counter_enabled      adds counters to the output items (tasks and hosts/task)                                                                      
debug                formatted stdout/stderr display                                                                                               
default              default Ansible screen output                                                                                                 
dense                minimal stdout output                                                                                                         
foreman              Sends events to Foreman                                                                                                       
full_skip            suppresses tasks if all hosts skipped                                                                                         
grafana_annotations  send ansible events as annotations on charts to grafana over http api                                                         
hipchat              post task events to hipchat                                                                                                   
jabber               post task events to a jabber server                                                                                           
json                 Ansible screen output as JSON                                                                                                 
junit                write playbook output to a JUnit file                                                                                         
log_plays            write playbook output to log file                                                                                             
logdna               Sends playbook logs to LogDNA                                                                                                 
logentries           Sends events to Logentries                                                                                                    
logstash             Sends events to Logstash                                                                                                      
mail                 Sends failure events via email                                                                                                
minimal              minimal Ansible screen output                                                                                                 
nrdp                 post task result to a nagios server through nrdp                                                                              
null                 Don't display stuff to screen                                                                                                 
oneline              oneline Ansible screen output                                                                                                 
osx_say              notify using software speech synthesizer                                                                                      
profile_roles        adds timing information to roles                                                                                              
profile_tasks        adds time information to tasks                                                                                                
say                  notify using software speech synthesizer                                                                                      
selective            only print certain tasks                                                                                                      
skippy               Ansible screen output that ignores skipped status                                                                             
slack                Sends play events to a Slack channel                                                                                          
splunk               Sends task result events to Splunk HTTP Event Collector                                                                       
stderr               Splits output, sending failed tasks to stderr                                                                                 
sumologic            Sends task result events to Sumologic                                                                                         
syslog_json          sends JSON events to syslog                                                                                                   
timer                Adds time to play stats                                                                                                       
tree                 Save host events to files                                                                                                     
unixy                condensed Ansible output                                                                                                      
yaml                 yaml-ized Ansible screen output                      
# 查看callback模块用法
XX@XXdeMacBook-Air ~ % ansible-doc -t callback cgroup_perf_recap
> ANSIBLE.POSIX.CGROUP_PERF_RECAP    (/Library/Frameworks/Python.framework/Versions/3.9/lib/python3.9/site-packages/ansible_collections/ansible/posix/p>

        This is an ansible callback plugin utilizes cgroups to profile system activity of ansible and individual tasks,
        and display a recap at the end of the playbook execution

OPTIONS (= is mandatory):

= control_group
        Name of cgroups control group

        set_via:
          env:
          - name: CGROUP_CONTROL_GROUP
          ini:
          - key: control_group
            section: callback_cgroup_perf_recap

4.8 分析控制节点CPU和内存

在callback插件内可以使用cgroup_perf_recap可以监控控制节点运行playbook耗费多少资源。

# 在配置文件中配置插件信息
[workstation task-tagging (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer, profile_tasks, cgroup_perf_recap

[callback_cgroup_perf_recap]
control_group=ansible_profile
# 执行playbook,可以显示运行时间
ansible-playbook: error: no such option: --sikp-tags
[workstation task-tagging (master *)]# ansible-playbook site.yml --skip-tags tests
 [WARNING]: Cannot open /sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes for reading ([Errno 2] No such file or directory:
b'/sys/fs/cgroup/memory/ansible_profile/memory.max_usage_in_bytes'). Disabling cgroup_perf_recap


PLAY [Ensure HAProxy is deployed] **********************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
Friday 14 October 2022  23:27:21 +0800 (0:00:00.106)       0:00:00.106 ******** 
changed: [servera.lab.example.com] => (item={'port': '80/tcp'})

TASK [haproxy : Ensure haproxy packages are present] ***************************************************************************************************
Friday 14 October 2022  23:27:23 +0800 (0:00:02.480)       0:00:02.587 ******** 
changed: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy is started and enabled] *************************************************************************************************
Friday 14 October 2022  23:27:30 +0800 (0:00:06.536)       0:00:09.123 ******** 
changed: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy configuration is set] ***************************************************************************************************
Friday 14 October 2022  23:27:33 +0800 (0:00:03.065)       0:00:12.189 ******** 
changed: [servera.lab.example.com]

RUNNING HANDLER [firewall : reload firewalld] **********************************************************************************************************
Friday 14 October 2022  23:27:37 +0800 (0:00:04.607)       0:00:16.796 ******** 
changed: [servera.lab.example.com]

RUNNING HANDLER [haproxy : reload haproxy] *************************************************************************************************************
Friday 14 October 2022  23:27:49 +0800 (0:00:11.374)       0:00:28.171 ******** 
changed: [servera.lab.example.com]

PLAY [Ensure Apache is deployed] ***********************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
Friday 14 October 2022  23:27:54 +0800 (0:00:05.216)       0:00:33.387 ******** 
changed: [serverc.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})
changed: [serverb.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})

TASK [apache : Ensure httpd packages are installed] ****************************************************************************************************
Friday 14 October 2022  23:27:57 +0800 (0:00:03.278)       0:00:36.666 ******** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

TASK [apache : Ensure SELinux allows httpd connections to a remote database] ***************************************************************************
Friday 14 October 2022  23:28:06 +0800 (0:00:08.456)       0:00:45.123 ******** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

TASK [apache : Ensure httpd service is started and enabled] ********************************************************************************************
Friday 14 October 2022  23:28:09 +0800 (0:00:03.244)       0:00:48.367 ******** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

RUNNING HANDLER [firewall : reload firewalld] **********************************************************************************************************
Friday 14 October 2022  23:28:12 +0800 (0:00:02.703)       0:00:51.071 ******** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

PLAY [Ensure Web App is deployed] **********************************************************************************************************************

TASK [webapp : Ensure stub web content is deployed] ****************************************************************************************************
Friday 14 October 2022  23:28:17 +0800 (0:00:05.387)       0:00:56.459 ******** 
changed: [serverb.lab.example.com]
changed: [serverc.lab.example.com]

PLAY [web application smoke test] **********************************************************************************************************************

PLAY RECAP *********************************************************************************************************************************************
servera.lab.example.com    : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb.lab.example.com    : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=6    changed=6    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Friday 14 October 2022  23:28:19 +0800 (0:00:01.541)       0:00:58.001 ******** 
=============================================================================== 
firewall : reload firewalld -------------------------------------------------------------------------------------------------------------------- 11.37s
apache : Ensure httpd packages are installed ---------------------------------------------------------------------------------------------------- 8.46s
haproxy : Ensure haproxy packages are present --------------------------------------------------------------------------------------------------- 6.54s
firewall : reload firewalld --------------------------------------------------------------------------------------------------------------------- 5.39s
haproxy : reload haproxy ------------------------------------------------------------------------------------------------------------------------ 5.22s
haproxy : Ensure haproxy configuration is set --------------------------------------------------------------------------------------------------- 4.61s
firewall : Ensure Firewall Sources Configuration ------------------------------------------------------------------------------------------------ 3.28s
apache : Ensure SELinux allows httpd connections to a remote database --------------------------------------------------------------------------- 3.24s
haproxy : Ensure haproxy is started and enabled ------------------------------------------------------------------------------------------------- 3.07s
apache : Ensure httpd service is started and enabled -------------------------------------------------------------------------------------------- 2.70s
firewall : Ensure Firewall Sources Configuration ------------------------------------------------------------------------------------------------ 2.48s
webapp : Ensure stub web content is deployed ---------------------------------------------------------------------------------------------------- 1.54s
Playbook run took 0 days, 0 hours, 0 minutes, 57 seconds

4.9 Tasks和Roles运行时间

插件 说明
timer 列出时间
profile_tasks 执行tasks开启计时器,统计tasks执行时间
profile_roles 执行roles开启计时器,统计roles的执行时间
# 在配置文件中配置插件信息
[workstation task-tagging (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer, profile_tasks, cgroup_perf_recap

4.10 优化playbook执行练习

4.10.1 题目要求

  1. 开启实验
  2. 进入DO447/labs/task-speed/目录
    1. 查看deploy_webservers.yml文件
    2. 查看ansible.cfg文件
      1. 增加callback_whitelist支持查看监控程序执行时间和task执行时间
      2. 运行deploy_webservers.yml查看各个tasks执行时间
      3. 编辑deploy_webservers.yml文件,取消收集facts变量,运行查看时间
      4. 编辑deploy_webservers.yml文件,使用synchronize模块替代copy模块,运行查看时间
      5. 在配置文件中注释插件
  3. 结束实验

4.10.2 练习

[workstation ~]# lab task-speed start 

Setting up workstation for the Guided Exercise: Optimizing Execution for Speed

 · Checking python on remote hosts.............................  SUCCESS
 · Setting up labs folder......................................  SUCCESS
 · Downloading starter project.................................  SUCCESS
 · Setting up solutions folder.................................  SUCCESS
 · Downloading solution project................................  SUCCESS

Setup successful. Please proceed with the exercise.

 · Creating fake web content...................................  SUCCESS
# 查看配置文件,添加callback_whitelist插件和对应功能
[workstation ~]# cd DO447/labs/task-speed/
[workstation task-speed]# ls
ansible.cfg  clean.yml  deploy_webservers.yml  deploy_webservers.yml.backup  inventory.yml  web_content
[workstation task-speed]# cat deploy_webservers.yml
---
- name: Deploy the web servers
  hosts: web_servers
  become: True

  tasks:
    - name: Ensure required packages are installed
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - httpd
        - mod_ssl
        - httpd-tools
        - mariadb-server
        - mariadb
        - php
        - php-mysqlnd

    - name: Ensure the services are enabled
      service:
        name: "{{ item }}"
        state: started
        enabled: True
      loop:
        - httpd
        - mariadb

    - name: Ensure the web content is installed
      copy:
        src: web_content/
        dest: /var/www/html
[workstation task-speed]# vim ansible.cfg 
[workstation task-speed]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer, profile_tasks
# 添加插件,查看具体运行时间
[workstation task-speed]# ansible-playbook deploy_webservers.yml

PLAY [Deploy the web servers] **************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************
Saturday 15 October 2022  11:18:12 +0800 (0:00:00.156)       0:00:00.156 ****** 
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

TASK [Ensure required packages are installed] **********************************************************************************************************
Saturday 15 October 2022  11:18:15 +0800 (0:00:03.493)       0:00:03.649 ****** 
ok: [serverb.lab.example.com] => (item=httpd)
ok: [serverc.lab.example.com] => (item=httpd)
changed: [serverb.lab.example.com] => (item=mod_ssl)
changed: [serverc.lab.example.com] => (item=mod_ssl)
ok: [serverb.lab.example.com] => (item=httpd-tools)
ok: [serverc.lab.example.com] => (item=httpd-tools)
changed: [serverb.lab.example.com] => (item=mariadb-server)
changed: [serverc.lab.example.com] => (item=mariadb-server)
ok: [serverb.lab.example.com] => (item=mariadb)
ok: [serverc.lab.example.com] => (item=mariadb)
ok: [serverb.lab.example.com] => (item=php)
ok: [serverc.lab.example.com] => (item=php)
ok: [serverb.lab.example.com] => (item=php-mysqlnd)
ok: [serverc.lab.example.com] => (item=php-mysqlnd)

TASK [Ensure the services are enabled] *****************************************************************************************************************
Saturday 15 October 2022  11:18:50 +0800 (0:00:35.133)       0:00:38.782 ****** 
ok: [serverc.lab.example.com] => (item=httpd)
ok: [serverb.lab.example.com] => (item=httpd)
changed: [serverb.lab.example.com] => (item=mariadb)
changed: [serverc.lab.example.com] => (item=mariadb)

TASK [Ensure the web content is installed] *************************************************************************************************************
Saturday 15 October 2022  11:18:58 +0800 (0:00:07.201)       0:00:45.985 ****** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************
serverb.lab.example.com    : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=4    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Saturday 15 October 2022  11:19:56 +0800 (0:00:58.823)       0:01:44.808 ****** 
=============================================================================== 
Ensure the web content is installed ------------------------------------------------------------------------------------------------------------ 58.82s
Ensure required packages are installed --------------------------------------------------------------------------------------------------------- 35.13s
Ensure the services are enabled ----------------------------------------------------------------------------------------------------------------- 7.20s
Gathering Facts --------------------------------------------------------------------------------------------------------------------------------- 3.49s
Playbook run took 0 days, 0 hours, 1 minutes, 44 seconds
[workstation task-speed]# cat deploy_webservers.yml
---
- name: Deploy the web servers
  hosts: web_servers
  become: True
  gather_facts: false
...
[workstation task-speed]# ansible-playbook deploy_webservers.yml

PLAY [Deploy the web servers] **************************************************************************************************************************

TASK [Ensure required packages are installed] **********************************************************************************************************
Saturday 15 October 2022  11:29:20 +0800 (0:00:00.107)       0:00:00.107 ****** 
ok: [serverb.lab.example.com] => (item=httpd)
ok: [serverc.lab.example.com] => (item=httpd)
ok: [serverb.lab.example.com] => (item=mod_ssl)
ok: [serverc.lab.example.com] => (item=mod_ssl)
ok: [serverb.lab.example.com] => (item=httpd-tools)
ok: [serverc.lab.example.com] => (item=httpd-tools)
ok: [serverb.lab.example.com] => (item=mariadb-server)
ok: [serverc.lab.example.com] => (item=mariadb-server)
ok: [serverb.lab.example.com] => (item=mariadb)
ok: [serverc.lab.example.com] => (item=mariadb)
ok: [serverb.lab.example.com] => (item=php)
ok: [serverc.lab.example.com] => (item=php)
ok: [serverb.lab.example.com] => (item=php-mysqlnd)
ok: [serverc.lab.example.com] => (item=php-mysqlnd)

TASK [Ensure the services are enabled] *****************************************************************************************************************
Saturday 15 October 2022  11:29:43 +0800 (0:00:23.109)       0:00:23.217 ****** 
ok: [serverb.lab.example.com] => (item=httpd)
ok: [serverc.lab.example.com] => (item=httpd)
ok: [serverb.lab.example.com] => (item=mariadb)
ok: [serverc.lab.example.com] => (item=mariadb)

TASK [Ensure the web content is installed] *************************************************************************************************************
Saturday 15 October 2022  11:29:48 +0800 (0:00:04.435)       0:00:27.653 ****** 
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************
serverb.lab.example.com    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Saturday 15 October 2022  11:30:11 +0800 (0:00:23.475)       0:00:51.128 ****** 
=============================================================================== 
Ensure the web content is installed ------------------------------------------------------------------------------------------------------------ 23.48s
Ensure required packages are installed --------------------------------------------------------------------------------------------------------- 23.11s
Ensure the services are enabled ----------------------------------------------------------------------------------------------------------------- 4.44s
Playbook run took 0 days, 0 hours, 0 minutes, 51 seconds

# 使用synchronize模块替代copy模块
[workstation task-speed]# cat deploy_webservers.yml
---
- name: Deploy the web servers
  hosts: web_servers
  become: True
  gather_facts: false

  tasks:
    - name: Ensure required packages are installed
      yum:
        name: "{{ item }}"
        state: present
      loop:
        - httpd
        - mod_ssl
        - httpd-tools
        - mariadb-server
        - mariadb
        - php
        - php-mysqlnd

    - name: Ensure the services are enabled
      service:
        name: "{{ item }}"
        state: started
        enabled: True
      loop:
        - httpd
        - mariadb

    - name: Ensure the web content is installed
      # copy:
      synchronize:
        src: web_content/
        dest: /var/www/html
# 替换成同步模块,运行时间减少
[workstation task-speed]# ansible-playbook deploy_webservers.yml

PLAY [Deploy the web servers] **************************************************************************************************************************

TASK [Ensure required packages are installed] **********************************************************************************************************
Saturday 15 October 2022  11:46:35 +0800 (0:00:00.094)       0:00:00.094 ****** 
ok: [serverc.lab.example.com] => (item=httpd)
ok: [serverb.lab.example.com] => (item=httpd)
ok: [serverb.lab.example.com] => (item=mod_ssl)
ok: [serverc.lab.example.com] => (item=mod_ssl)
ok: [serverb.lab.example.com] => (item=httpd-tools)
ok: [serverc.lab.example.com] => (item=httpd-tools)
ok: [serverb.lab.example.com] => (item=mariadb-server)
ok: [serverc.lab.example.com] => (item=mariadb-server)
ok: [serverc.lab.example.com] => (item=mariadb)
ok: [serverb.lab.example.com] => (item=mariadb)
ok: [serverc.lab.example.com] => (item=php)
ok: [serverb.lab.example.com] => (item=php)
ok: [serverc.lab.example.com] => (item=php-mysqlnd)
ok: [serverb.lab.example.com] => (item=php-mysqlnd)

TASK [Ensure the services are enabled] *****************************************************************************************************************
Saturday 15 October 2022  11:46:57 +0800 (0:00:22.662)       0:00:22.757 ****** 
ok: [serverb.lab.example.com] => (item=httpd)
ok: [serverc.lab.example.com] => (item=httpd)
ok: [serverc.lab.example.com] => (item=mariadb)
ok: [serverb.lab.example.com] => (item=mariadb)

TASK [Ensure the web content is installed] *************************************************************************************************************
Saturday 15 October 2022  11:47:02 +0800 (0:00:04.417)       0:00:27.174 ****** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************
serverb.lab.example.com    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Saturday 15 October 2022  11:47:14 +0800 (0:00:12.489)       0:00:39.664 ****** 
=============================================================================== 
Ensure required packages are installed --------------------------------------------------------------------------------------------------------- 22.66s
Ensure the web content is installed ------------------------------------------------------------------------------------------------------------ 12.49s
Ensure the services are enabled ----------------------------------------------------------------------------------------------------------------- 4.42s
Playbook run took 0 days, 0 hours, 0 minutes, 39 seconds
# 结束实验
[workstation task-speed]# lab task-speed finish 

Cleaning up the lab on workstation:

 · Executing cleanup playbook..................................  SUCCESS
 · Removing the fake web content...............................  SUCCESS
 · Cleaning lab files..........................................  SUCCESS
 · Cleaning solutions files....................................  SUCCESS
Lab finished.

5、 综合实验

5.1 实验要求

  1. 开启实验
  2. 进入task-review目录
    • 编辑ansible.cfg文件,关闭become提权
    • 在roles/firewall/tasks/main.yml 下开启提权
    • 在roles/firewall/handlers/main.yml 下开启提权
    • 编辑roles/haproxy/tasks/main.yml ,使用block圈起来进行提权
    • 编辑roles/haproxy/handlers/main.yml 加入提权
    • 编辑roles/apache/tasks/main.yml,使用block圈起来进行提权
    • 编辑roles/webapp/tasks/main.yml,加入提权
    • 在deploy_haproxy.yml中添加copy的task
    • 在haproxy role中添加handler,使用copy模块将Reloaded复制到/tmp/haproxy.status
    • 在roles/haproxy/tasks/main.yml添加notify:haproxy filehandler
    • 在roles/apache/tasks/main.yml 加入tag进行控制
    • 编辑配置文件,监控时间和tasks
    • 运行site.yml,查看运行时间
    • 编辑roles/apache/tasks/main.yml,将yum模块软件包使用列表描述
    • 再次执行site.yml,使用tags apache_installer
  3. 判断成绩,结束实验

5.2 实验

[workstation ~]# lab task-review start 

Setting up workstation for the Lab: Managing Task Execution

 · Checking python on remote hosts.............................  SUCCESS
 · Installing git..............................................  SUCCESS
 · Installing tree.............................................  SUCCESS
 · Configuring Git.............................................  SUCCESS
 · Configuring Git credentials.................................  SUCCESS
 · Adding content to Git repo..................................  SUCCESS
[workstation git-repos]# git clone http://git.lab.example.com:8081/git/task-review.git
Cloning into 'task-review'...
remote: Enumerating objects: 56, done.
remote: Counting objects: 100% (56/56), done.
remote: Compressing objects: 100% (42/42), done.
remote: Total 56 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (56/56), done.
# 修改ansible.cfg文件,关闭提权
[workstation task-review (master)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops

[privilege_escalation]
become=true
become_method=sudo
become_user=root
become_ask_pass=false
[workstation task-review (master)]# vim ansible.cfg 
[workstation task-review (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops

[privilege_escalation]
# become=true
become_method=sudo
become_user=root
become_ask_pass=false
# 在roles/firewall/tasks/main.yml 下开启提权
[workstation task-review (master *)]# vim roles/firewall/tasks/main.yml 
[workstation task-review (master *)]# cat roles/firewall/tasks/main.yml 
---
# tasks file for firewall

- name: Ensure Firewall Sources Configuration
  firewalld:
    source: "{{ item.source if item.source is defined else omit }}"
    zone: "{{ item.zone if item.zone is defined else omit }}"
    permanent: true
    state: "{{ item.state | default('enabled') }}"
    service: "{{ item.service if item.service is defined else omit }}"
    immediate: true
    port: "{{ item.port if item.port is defined else omit }}"
  loop: "{{ firewall_rules }}"
  notify: reload firewalld
  become: true
# 在roles/firewall/handlers/main.yml 下开启提权
[workstation task-review (master *)]# vim roles/firewall/handlers/main.yml 
[workstation task-review (master *)]# cat roles/firewall/handlers/main.yml 
---
# handlers file for firewall

- name: reload firewalld
  service:
    name: firewalld
    state: reloaded
  become: true

# 编辑roles/haproxy/tasks/main.yml ,使用block圈起来进行提权
[workstation task-review (master *)]# cat roles/haproxy/tasks/main.yml 
---
# tasks file for haproxy

- block:
  - name: Ensure haproxy packages are present
    yum:
      name:
        - haproxy
        - socat
      state: present

  - name: Ensure haproxy is started and enabled
    service:
      name: haproxy
      state: started
      enabled: true

  - name: Ensure haproxy configuration is set
    template:
      src: haproxy.cfg.j2
      dest: /etc/haproxy/haproxy.cfg
    notify: reload haproxy
  become: true
# 编辑roles/haproxy/handlers/main.yml 加入提权
[workstation task-review (master *)]# cat roles/haproxy/handlers/main.yml 
---
# handlers file for haproxy

- name: restart haproxy
  service:
    name: haproxy
    state: restarted
  become: true

- name: reload haproxy
  service:
    name: haproxy
    state: reloaded
  become: true
# 编辑roles/apache/tasks/main.yml,使用block圈起来进行提权
[workstation task-review (master *)]# cat roles/apache/tasks/main.yml 
---
# tasks file for apache
- block:
  - name: Ensure httpd packages are installed
    yum:
      name: "{{ item }}"
      state: present
    loop:
      - httpd
      - php
      - git
      - php-mysqlnd

  - name: Ensure SELinux allows httpd connections to a remote database
    seboolean:
      name: httpd_can_network_connect_db
      state: true
      persistent: true

  - name: Ensure httpd service is started and enabled
    service:
      name: httpd
      state: started
      enabled: true
  become: true
# 编辑roles/webapp/tasks/main.yml,加入提权
[workstation task-review (master *)]# cat roles/webapp/tasks/main.yml 
---
# tasks file for webapp

- name: Ensure stub web content is deployed
  copy:
    content: "{{ webapp_message }}. (version {{ webapp_version}})\n"
    dest: /var/www/html/index.html
  become: true
# 在deploy_haproxy.yml中添加copy的task
[workstation task-review (master *)]# cat deploy_haproxy.yml 
- name: Ensure HAProxy is deployed
  hosts: lb_servers
  force_handlers: true
  gather_facts: false

  pre_tasks:
    - name: setting the maintenance message
      copy:
        dest: /tmp/site.ready
        content: "Playbook site.yml ready to start"

  roles:
    # The "haproxy" role has a dependency on the "firewall" role.
    # The "firewall" role requires a "firewall_rules" variable be defined.
    - role: haproxy
# 在haproxy role中添加handler,使用copy模块将Reloaded复制到/tmp/haproxy.status
[workstation task-review (master *)]# cat roles/haproxy/handlers/main.yml 
---
# handlers file for haproxy

- name: restart haproxy
  service:
    name: haproxy
    state: restarted
  become: true

- name: reload haproxy
  service:
    name: haproxy
    state: reloaded
  become: true

- name: haproxy filehandler
  copy:
    dest: /tmp/haproxy/status
    content: "Reloaded"
# 在roles/haproxy/tasks/main.yml添加notify:haproxy filehandler
[workstation task-review (master *)]# cat roles/haproxy/tasks/main.yml 
---
# tasks file for haproxy

- block:
  - name: Ensure haproxy packages are present
    yum:
      name:
        - haproxy
        - socat
      state: present

  - name: Ensure haproxy is started and enabled
    service:
      name: haproxy
      state: started
      enabled: true

  - name: Ensure haproxy configuration is set
    template:
      src: haproxy.cfg.j2
      dest: /etc/haproxy/haproxy.cfg
    notify: 
      - reload haproxy
      - haproxy filehandler
  become: true
# 在roles/apache/tasks/main.yml 加入tag进行控制
[workstation task-review (master *)]# cat roles/apache/tasks/main.yml 
---
# tasks file for apache
- block:
  - name: Ensure httpd packages are installed
    yum:
      name: "{{ item }}"
      state: present
    loop:
      - httpd
      - php
      - git
      - php-mysqlnd
    tags:
      - apache_installer

  - name: Ensure SELinux allows httpd connections to a remote database
    seboolean:
      name: httpd_can_network_connect_db
      state: true
      persistent: true

  - name: Ensure httpd service is started and enabled
    service:
      name: httpd
      state: started
      enabled: true
  become: true
# 编辑配置文件,监控时间和tasks
[workstation task-review (master *)]# cat ansible.cfg 
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer,profile_tasks

[privilege_escalation]
# become=true
become_method=sudo
become_user=root
become_ask_pass=false
# 运行site.yml,查看运行时间
[workstation task-review (master *)]# ansible-playbook site.yml 

PLAY [Ensure HAProxy is deployed] **********************************************************************************************************************

TASK [setting the maintenance message] *****************************************************************************************************************
Saturday 15 October 2022  13:27:32 +0800 (0:00:00.086)       0:00:00.086 ****** 
changed: [servera.lab.example.com]

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
Saturday 15 October 2022  13:27:35 +0800 (0:00:03.012)       0:00:03.099 ****** 
ok: [servera.lab.example.com] => (item={'port': '80/tcp'})

TASK [haproxy : Ensure haproxy packages are present] ***************************************************************************************************
Saturday 15 October 2022  13:27:37 +0800 (0:00:01.886)       0:00:04.985 ****** 
ok: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy is started and enabled] *************************************************************************************************
Saturday 15 October 2022  13:27:42 +0800 (0:00:05.065)       0:00:10.051 ****** 
ok: [servera.lab.example.com]

TASK [haproxy : Ensure haproxy configuration is set] ***************************************************************************************************
Saturday 15 October 2022  13:27:44 +0800 (0:00:02.560)       0:00:12.611 ****** 
ok: [servera.lab.example.com]

PLAY [Ensure Apache is deployed] ***********************************************************************************************************************

TASK [firewall : Ensure Firewall Sources Configuration] ************************************************************************************************
Saturday 15 October 2022  13:27:46 +0800 (0:00:01.737)       0:00:14.349 ****** 
ok: [serverb.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})
ok: [serverc.lab.example.com] => (item={'zone': 'internal', 'service': 'http', 'source': '172.25.250.10'})

TASK [apache : Ensure httpd packages are installed] ****************************************************************************************************
Saturday 15 October 2022  13:27:48 +0800 (0:00:02.259)       0:00:16.608 ****** 
changed: [serverb.lab.example.com] => (item=httpd)
changed: [serverc.lab.example.com] => (item=httpd)
changed: [serverb.lab.example.com] => (item=php)
changed: [serverc.lab.example.com] => (item=php)
ok: [serverb.lab.example.com] => (item=git)
ok: [serverc.lab.example.com] => (item=git)
changed: [serverb.lab.example.com] => (item=php-mysqlnd)
changed: [serverc.lab.example.com] => (item=php-mysqlnd)

TASK [apache : Ensure SELinux allows httpd connections to a remote database] ***************************************************************************
Saturday 15 October 2022  13:28:07 +0800 (0:00:19.017)       0:00:35.626 ****** 
ok: [serverc.lab.example.com]
ok: [serverb.lab.example.com]

TASK [apache : Ensure httpd service is started and enabled] ********************************************************************************************
Saturday 15 October 2022  13:28:11 +0800 (0:00:03.313)       0:00:38.939 ****** 
changed: [serverc.lab.example.com]
changed: [serverb.lab.example.com]

PLAY [Ensure Web App is deployed] **********************************************************************************************************************

TASK [webapp : Ensure stub web content is deployed] ****************************************************************************************************
Saturday 15 October 2022  13:28:13 +0800 (0:00:02.454)       0:00:41.393 ****** 
changed: [serverb.lab.example.com]
changed: [serverc.lab.example.com]

PLAY RECAP *********************************************************************************************************************************************
servera.lab.example.com    : ok=5    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverb.lab.example.com    : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=5    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Saturday 15 October 2022  13:28:15 +0800 (0:00:01.481)       0:00:42.874 ****** 
=============================================================================== 
apache : Ensure httpd packages are installed --------------------------------------------------------------------------------------------------- 19.02s
haproxy : Ensure haproxy packages are present --------------------------------------------------------------------------------------------------- 5.07s
apache : Ensure SELinux allows httpd connections to a remote database --------------------------------------------------------------------------- 3.31s
setting the maintenance message ----------------------------------------------------------------------------------------------------------------- 3.01s
haproxy : Ensure haproxy is started and enabled ------------------------------------------------------------------------------------------------- 2.56s
apache : Ensure httpd service is started and enabled -------------------------------------------------------------------------------------------- 2.45s
firewall : Ensure Firewall Sources Configuration ------------------------------------------------------------------------------------------------ 2.26s
firewall : Ensure Firewall Sources Configuration ------------------------------------------------------------------------------------------------ 1.89s
haproxy : Ensure haproxy configuration is set --------------------------------------------------------------------------------------------------- 1.74s
webapp : Ensure stub web content is deployed ---------------------------------------------------------------------------------------------------- 1.48s
Playbook run took 0 days, 0 hours, 0 minutes, 42 seconds
# 编辑roles/apache/tasks/main.yml,将yum模块软件包使用列表描述
[workstation task-review (master *)]# cat roles/apache/tasks/main.yml 
---
# tasks file for apache
- block:
  - name: Ensure httpd packages are installed
    yum:
      name:
        - httpd
        - php
        - git
        - php-mysqlnd
      state: present
    tags:
      - apache_installer

  - name: Ensure SELinux allows httpd connections to a remote database
    seboolean:
      name: httpd_can_network_connect_db
      state: true
      persistent: true

  - name: Ensure httpd service is started and enabled
    service:
      name: httpd
      state: started
      enabled: true
  become: true
# 再次执行site.yml,使用tags apache_installer
[workstation task-review (master *)]# ansible-playbook site.yml --tags apache_installer

PLAY [Ensure HAProxy is deployed] **********************************************************************************************************************

PLAY [Ensure Apache is deployed] ***********************************************************************************************************************

TASK [apache : Ensure httpd packages are installed] ****************************************************************************************************
Saturday 15 October 2022  13:31:26 +0800 (0:00:00.102)       0:00:00.102 ****** 
ok: [serverb.lab.example.com]
ok: [serverc.lab.example.com]

PLAY [Ensure Web App is deployed] **********************************************************************************************************************

PLAY RECAP *********************************************************************************************************************************************
serverb.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
serverc.lab.example.com    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Saturday 15 October 2022  13:31:31 +0800 (0:00:05.039)       0:00:05.141 ****** 
=============================================================================== 
apache : Ensure httpd packages are installed ---------------------------------------------------------------------------------------------------- 5.04s
Playbook run took 0 days, 0 hours, 0 minutes, 5 seconds
# 判断成绩
[workstation task-review (master *)]# lab task-review grade 

Grading the student's work for the Lab: Managing Task Execution

Setting up to Grade
 · Retrieving grading playbook.................................  SUCCESS

Grading Criteria
 · Check ansible.cfg privilege escalation......................  PASS
 · Privilege escalation added to firewall tasks................  PASS
 · Privilege escalation added to haproxy tasks.................  PASS
 · Privilege escalation added to apache tasks..................  PASS
 · Privilege escalation added to webapp tasks..................  PASS
 · Privilege escalation added to firewall handlers.............  PASS
 · Privilege escalation added to haproxy handlers..............  PASS
 · 'pre_tasks' are configured..................................  PASS
 · HAproxy handler was executed................................  PASS
 · The Apache installer task is tagged.........................  PASS
 · Profiling is active for the playbook........................  PASS
 · yum task in apache role is correct..........................  PASS
Lab results
 · Success.....................................................  11
 · Failure.....................................................  1

 · Overall Grade...............................................  PASS

Cleaning Up from Grading
 · Removing temporary repository clone.........................  SUCCESS
# 结束实验
[workstation ~]# lab task-review finish 

Cleaning up the lab on workstation:

 · Cloning the task-review repository..........................  SUCCESS
 · Retrieving cleanup playbook.................................  SUCCESS
 · Executing cleanup playbook..................................  SUCCESS
 · Removing temporary repository clone.........................  SUCCESS