DO447管理任务执行--速度执行优化

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: DO447管理任务执行--速度执行优化

DO447管理任务执行–速度执行优化

RHCSA专栏:戏说 RHCSA 认证

RHCE专栏:戏说 RHCE 认证

此文章(第三章 管理任务执行–速度执行优化 )收录在RHCA专栏:RHCA 回忆录

📜4.1 优化策略的执行

有很多方法可以优化你的Ansible剧本。随着管理主机数量的增加,编写有效运行的剧本变得越来越重要。

📑优化基础设施

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

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


📑禁用事实收集

每个play都有一个首先运行的隐藏任务,使用setup模块从每个主机收集事实。这些事实提供了关于play可以通过ansible_facts变量使用的节点的一些信息。

收集每个远程主机上的事实需要时间。如果你在play中不使用这些事实,通过设置gather_facts指令为False(或no)跳过事实收集任务。

image-20220412202052601

剧本经常使用ansible_facts[‘hostname’], ansible_hostname, ansible_facts[‘nodename’],或ansible_nodename变量来引用当前处理的主机。这些变量来自事实收集任务,但通常可以用inventory_hostname和inventory_hostname_short 魔法变量替换它们。

您还可以选择手工收集事实,方法是在选定的主机上作为剧本的一部分运行setup模块作为任务,这些事实将用于剧本中的后续剧本。


📑提高并行性

当Ansible正在运行一个play时,它将在当前批处理中的每个主机上运行第一个任务,然后在当前批处理中的每个主机上运行第二个任务,如此循环,直到play完成。forks参数控制Ansible同时可以激活多少个连接。默认情况下,这个值被设置为5,这意味着即使当前任务上有100个主机需要处理,Ansible也会以5个主机为单位与它们进行通信。一旦它与所有的100个通信,Ansible就会进入下一个任务。

通过增加fork值,Ansible可以同时在更多主机上运行每个任务,而playbook通常会在更短的时间内完成。例如,如果您将forks设置为100,Ansible可以尝试同时打开前面示例中所有100个主机的连接。这将增加控制节点的负载,它仍然需要足够的时间与每个主机通信。

指定要在Ansible配置文件中使用的分支数量,或者在ansible-playbook通过传递 -f选项。

下面的示例显示了在ansible.cfg配置文件的[defaults]部分将forks参数设置为100

[user@demo ~]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
forks=100

因为forks的值告诉Ansible要启动多少工作进程,如果数值太高,可能会损害控制节点和网络。首先尝试使用保守值(例如20或50),然后在每次监控系统时逐步增加该值。


📑避免使用包管理器模块的循环

有些模块接受一个项目列表来处理,不需要使用循环。这种方法可以提高效率,因为模块将被调用一次而不是多次。

用于管理操作系统包的模块是这样工作的。下面的示例使用yum模块在一个事务中安装几个包,这是安装一组包的最有效方法。

image-20220412202246598

以上脚本等价于在shell提示符中运行以下命令:

[root@demo ~]# yum install httpd mod_ssl httpd-tools mariadb-server mariadb php php-mysqlnd

下面的例子效率不高。它使用循环一次安装一个包:

image-20220412202315284

这个例子相当于运行多个yum命令:

[root@demo ~]# yum install httpd
[root@demo ~]# yum install mod_ssl
[root@demo ~]# yum install httpd-tools
[root@demo ~]# yum install mariadb-server
[root@demo ~]# yum install mariadb
[root@demo ~]# yum install php
[root@demo ~]# yum install php-mysqlnd

第二个例子更慢,效率更低,因为Ansible运行yum模块7次,启动模块的进程7次,进行依赖解析7次。

并不是所有的Ansible模块都接受name参数的列表。例如,服务模块只接受name参数的单个值,您需要一个循环来操作多个项目:

image-20220412202409267

使用ansible-doc命令获取关于不同模块参数将接受的值类型的信息:

# ansible-doc yum
- name
        A package name or package specifier with version, like `name-1.0'.
        If a previous version is specified, the task also needs to turn `allow_downgrade' on.
        See the `allow_downgrade' documentation for caveats with downgrading packages.
        When using state=latest, this can be `'*'' which means run `yum -y update'.
        You can also pass a url or a local path to a rpm file (using state=present). To
        operate on several packages this can accept a comma separated string of packages or (as of 2.0) a list of packages.
        (Aliases: pkg)[Default: (null)]
        elements: str
        type: list

# ansible-doc service
= name
        Name of the service.

        type: str

📑高效地将文件复制到所管理的主机

习惯用copy模块递归地将目录复制到托管主机。但当目录很大,有很多文件时,复制可能会花费很长时间。如果您多次运行playbook,后续的复制将花费更少的时间,因为模块只复制不同的文件。

但是,使用synchronize模块将大量文件复制到托管主机通常更有效。这个模块在后台使用rsync,在大多数情况下比copy模块要快。

下面的剧本使用synchronize模块递归地将web_content目录复制到web服务器。

image-20220412202527273


📑使用模板

lineinfile模块插入或删除文件中的行,例如配置文件中的配置指令。下面的剧本示例通过替换几行来更新Apache HTTP服务器配置文件。

image-20220412202600281

当与循环一起使用时,lineinfile的效率不是很高(而且容易出错)。在这种情况下,使用模板或复制模块代替。

image-20220412202618884


📑优化SSH连接

SSH连接的建立过程可能比较缓慢。当一个剧本有很多任务,目标是大量节点时,Ansible建立这些连接的总体时间可以显著增加剧本的全局执行时间。

为了缓解这个问题,Ansible依赖于SSH提供的两个特性:

ControlMaster:ControlMaster SSH指令允许与远程主机同时使用多个SSH会话来使用单个网络连接。第一个SSH会话建立连接,到同一主机的其他会话将重用该连接,从而绕过缓慢的初始过程。一旦最后一个会话关闭,SSH就会销毁共享连接。

ControlPersist:ControlPersist SSH指令在后台保持连接打开,而不是在最后一个会话之后销毁连接。此指令允许以后的SSH会话重用连接。ControlPersist表示SSH应保持空闲连接打开的时间;每一个新的会话都会重置这个空闲计时器。

Ansible通过在Ansible配置文件[ssh_connection]部分的ssh_args指令来启用controlMaster和ControlPersist特性。ssh_args的默认值如下所示。

[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s

有了这个值,Ansible会在最后一个会话完成后保持SSH连接打开60秒。当您拥有大量主机时,您可以增加ControlPersist的值,从而导致需要超过60秒才能完成任务。

使用默认值60秒,SSH在下一个任务启动时已经关闭了与第一个主机的连接,必须重新建立连接。您也可以增加fork指令的值,以便在空闲计时器到期之前更快地完成任务。

如果您的forks值或ControlPersist设置很大,则控制节点可能使用更多的同时连接。确保控制节点配置了足够的文件句柄,以支持许多活动的网络连接。


📑使流水线

为了在远程节点上运行一个任务,Ansible执行几个SSH操作,将模块及其所有数据复制到远程节点并执行模块。为了提高剧本的性能,您可以激活流水线特性。通过流水线,Ansible可以建立更少的SSH连接。

要激活pipelining,在Ansible配置文件的[ssh-connection]部分设置pipelining指令为True。

[ssh_connection]
pipelining = True

Ansible默认情况下不使用流水线,因为该特性要求禁用所有远程节点上的requiretty sudo选项。在Red Hat Enterprise Linux 8上,sudo选项默认是禁用的,但在其他系统上可能是活跃的。

要禁用该选项,使用visudo命令编辑托管节点的/etc/sudoers文件,并禁用requiretty标志:

[root@demo ~]# visudo
...output omitted...
Defaults !requiretty
...output omitted...

📑使用回调插件分析剧本的执行情况

回调插件通过调整Ansible对各种事件的响应方式来扩展它。其中一些插件修改命令行工具的输出,例如ansible-playbook命令,以提供额外的信息。例如,计时器插件在ansible-playbook命令的输出中显示playbook的执行时间。

重要:Red Hat Ansible Tower记录一些关于作业(playbook运行)的信息,它从Ansible -playbook的输出中提取这些信息。因为一些回调插件会修改这个输出,所以您应该小心使用它们,或者避免在Red Hat Ansible Tower中使用它们。

Ansible提供了一组回调插件,可以通过回调白名单指令在Ansible .cfg文件中启用它们。

[user@demo ~]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
callback_whitelist=timer, profile_tasks, cgroup_perf_recap

要列出可用的插件,请使用ansible-doc -t callback -l命令。要访问特定插件的文档,可以运行ansible-doc -t callback plug-in-name命令。

image-20220412202824038


📑分析控制节点CPU和内存

cgroup_perf_recap回调插件在剧本运行期间对控制节点进行配置。在剧本执行的最后,它显示一个全局摘要和每个任务的摘要。这些概要包括CPU和内存消耗,以及剧本和任务执行期间启动的最大进程数。

image-20220412202858907

image-20220412202928028

您可以使用这个插件来识别正在消耗您的控制节点资源的任务。当你在ansible.cfg文件中调优fork参数时,cgroup_perf_recap也可以用来监视系统活动。这样,您可以确保所选择的值不会使系统饱和。

cgroup_perf_recap回调插件依赖于Linux control groups (cgroup)特性来监视和配置ansible-playbook命令。在Linux系统上,您可以使用用于限制和监视一组进程可以消耗的资源(如内存或CPU)的控制组。要设置这些限制,请创建一个新组,设置限制,并将您的流程添加到组中。

要使用cgroup_perf_reca回调插件,您必须首先创建一个运行ansible-playbook命令的专用控制组。这个插件使用控制组的监视特性来收集ansible-playbook过程及其子过程的性能指标。

要创建专用控制组,使用cgcreate命令作为根用户。

[user@demo ~]$ sudo cgcreate -a user:user -t user:user -g cpuacct,memory,pids:ansible_profile

-a和-t选项显示可以访问和管理该控制组的用户和组。执行ansible-playbook命令时,请使用帐号所在的用户和组。-g选项给出了新的控制组的名称。该示例使用ansible_profile作为名称。用cgcreate命令创建的控制组在重新启动时不会持续存在。

下一步是在ansible.cfg文件中启用插件。

[user@demo ~]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
callback_whitelist=cgroup_perf_recap

[callback_cgroup_perf_recap]
control_group=ansible_profile

在[callback_cgroup_perf_recap]部分下的control_group指令给出了你的控制组的名称。

有了这个设置,您现在可以概述您的playbook。为此,请使用cgexec命令在新的控制组中运行ansible-playbook命令

image-20220412203044563

📑定时任务和角色

timer、profile_tasks和profile_roles回调插件对于识别慢速任务和角色很有用。

  • timer插件显示剧本执行的持续时间。

  • profile_tasks添加每个任务的开始时间,并在剧本执行结束时显示每个任务花费的时间,按降序排序。

  • profile_roles在末尾显示每个角色花费的时间,按降序排序。

要激活这些插件,请在ansible.cfg文件中添加或更新callback_whitelist指令:

[user@demo ~]$ cat ansible.cfg
[defaults]
inventory=inventory
remote_user=devops
callback_whitelist=timer, profile_tasks, profile_roles

不必启用所有三个插件:选择您需要的插件。

下面的示例显示了激活三个插件时ansible-playbook命令的输出。

image-20220412203350670


📜4.2 课本练习

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

📑查看实验剧本

[student@workstation ~]$ cd ~/DO447/labs/task-speed
[student@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

📑修改配置文件启用插件

[student@workstation task-speed]$ vim ansible.cfg
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer, profile_tasks

📑测试运行

[student@workstation task-speed]$ ansible-playbook deploy_webservers.yml
Tuesday 20 April 2021  22:53:38 +0800 (0:00:32.384)       0:01:00.797 ********* 
============================================================= 
Ensure the web content is installed --------------------------------------- 32.38s
Ensure required packages are installed ------------------------------------ 20.27s
Ensure the services are enabled -------------------------------------------- 6.37s
Gathering Facts ------------------------------------------------------------ 1.72s
Playbook run took 0 days, 0 hours, 1 minutes, 0 seconds

📑关闭事实收集

[student@workstation task-speed]$ vim deploy_webservers.yml
---
- name: Deploy the web servers
  hosts: web_servers
  become: True
  gather_facts: False

📑删除循环

    - name: Ensure required packages are installed
      yum:
        name: 
          - httpd
          - mod_ssl
          - httpd-tools
          - mariadb-server
          - mariadb
          - php
          - php-mysqlnd
        state: present

📑改用synchronize模块

    - name: Ensure the web content is installed
      synchronize:
        src: web_content/
        dest: /var/www/html
[student@workstation task-speed]$ ansible-playbook clean.yml
[student@workstation task-speed]$ ansible-playbook deploy_webservers.yml
Tuesday 20 April 2021  23:10:50 +0800 (0:00:15.056)       0:00:28.455 ********* 
=============================================================================== 
Ensure the web content is installed --------------------------------------- 15.06s
Ensure required packages are installed ------------------------------------- 9.90s
Ensure the services are enabled -------------------------------------------- 3.45s
Playbook run took 0 days, 0 hours, 0 minutes, 28 seconds

Ansible Tower不兼容定时器和profile_tasks回调插件,所以禁用。

[student@workstation task-speed]$ cat ansible.cfg
[defaults]
inventory=inventory.yml
remote_user=devops

📑清除实验

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

📖章节实验

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

📑拉取实验代码

[student@workstation ~]$ mkdir -p /home/student/git-repos/
[student@workstation ~]$ cd git-repos/
[student@workstation git-repos]$ git clone http://git.lab.example.com:8081/git/task-review.git 
[student@workstation git-repos]$ cd task-review

📑取消提权

[student@workstation task-review]$ vi ansible.cfg
[defaults]
inventory=inventory.yml
remote_user=devops

[privilege_escalation]
become_method=sudo
become_user=root
become_ask_pass=false

📑编写提权

[student@workstation task-review]$ vi 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: yes

[student@workstation task-review]$ vi roles/firewall/handlers/main.yml
---
# handlers file for firewall

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

[student@workstation task-review]$ vi 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: yes

[student@workstation task-review]$ vi roles/haproxy/handlers/main.yml
---
# handlers file for haproxy

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

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

[student@workstation task-review]$ vi 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: yes

[student@workstation task-review]$ vi 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: yes

📑编写任务执行顺序

[student@workstation task-review]$ vi 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

📑添加处理程序

[student@workstation task-review]$ vi roles/haproxy/handlers/main.yml
---
# handlers file for haproxy

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

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

- name: haproxy filehandler
  copy:
    dest: /tmp/haproxy.status
    content: "Reloaded"
[student@workstation task-review]$ vi 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: yes

📑添加标签

[student@workstation task-review]$ vi 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

📑启用回调插件

[student@workstation task-review]$ vi ansible.cfg
[defaults]
inventory=inventory.yml
remote_user=devops
callback_whitelist=timer,profile_tasks

[privilege_escalation]
become_method=sudo
become_user=root
become_ask_pass=false

📑测试执行

[student@workstation task-review]$ ansible-playbook site.yml

image-20220412211617115

📑删除循环

[student@workstation task-review]$ vi 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

📑标签运行

[student@workstation task-review]$ ansible-playbook site.yml –tags apache_installer

image-20220412211654256

📑实验评分和清除实验

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

💡总结

RHCA认证需要经历5门的学习与考试,还是需要花不少时间去学习与备考的,好好加油,可以噶🤪。

以上就是【金鱼哥】对 第三章 管理任务执行–速度执行优化 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。

如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
Python
【python脚本】执行过程中触发若干次就停止执行脚本的方式
【python脚本】执行过程中触发若干次就停止执行脚本的方式
|
3月前
|
Rust 安全 程序员
|
SQL Java Spring
如何查询已经执行过的流程信息?
如何查询已经执行过的流程信息?
|
IDE 测试技术 开发工具
教你实现一个非常有趣的自动化脚本“循环执行”的实例
教你实现一个非常有趣的自动化脚本“循环执行”的实例
798 0
|
运维 API 网络安全
DO447管理任务执行--控制任务执行
DO447管理任务执行--控制任务执行
140 0
DO447管理任务执行--控制任务执行
|
运维 数据库
DO447管理任务执行--运行选定的任务
DO447管理任务执行--运行选定的任务
165 0
DO447管理任务执行--运行选定的任务