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)跳过事实收集任务。
剧本经常使用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模块在一个事务中安装几个包,这是安装一组包的最有效方法。
以上脚本等价于在shell提示符中运行以下命令:
[root@demo ~]# yum install httpd mod_ssl httpd-tools mariadb-server mariadb php php-mysqlnd
下面的例子效率不高。它使用循环一次安装一个包:
这个例子相当于运行多个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参数的单个值,您需要一个循环来操作多个项目:
使用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服务器。
📑使用模板
lineinfile模块插入或删除文件中的行,例如配置文件中的配置指令。下面的剧本示例通过替换几行来更新Apache HTTP服务器配置文件。
当与循环一起使用时,lineinfile的效率不是很高(而且容易出错)。在这种情况下,使用模板或复制模块代替。
📑优化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命令。
📑分析控制节点CPU和内存
cgroup_perf_recap回调插件在剧本运行期间对控制节点进行配置。在剧本执行的最后,它显示一个全局摘要和每个任务的摘要。这些概要包括CPU和内存消耗,以及剧本和任务执行期间启动的最大进程数。
您可以使用这个插件来识别正在消耗您的控制节点资源的任务。当你在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命令
📑定时任务和角色
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命令的输出。
📜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
📑删除循环
[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
📑实验评分和清除实验
[student@workstation ~]$ lab task-review grade
[student@workstation ~]$ lab task-review finish
💡总结
RHCA认证需要经历5门的学习与考试,还是需要花不少时间去学习与备考的,好好加油,可以噶🤪。
以上就是【金鱼哥】对 第三章 管理任务执行–速度执行优化 的简述和讲解。希望能对看到此文章的小伙伴有所帮助。
如果这篇【文章】有帮助到你,希望可以给【金鱼哥】点个赞👍,创作不易,相比官方的陈述,我更喜欢用【通俗易懂】的文笔去讲解每一个知识点,如果有对【运维技术】感兴趣,也欢迎关注❤️❤️❤️ 【金鱼哥】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💕💕!