ansible基础-优化

简介

当管理集群达到必定规模时,ansible达到性能瓶颈是难以免的,此时咱们能够经过必定手段提升ansible的执行效率和性能。html

笔者虽未管理过超大规模服务器,但也经过查找资料和咨询大神了解了一些。现总结一些调优方法,供你们参考。node

Pipelinling

咱们知道ansible执行一个模块要ssh到目的主机屡次,开启「pipelining」特性其实是经过减小ssh链接次数,从而缩短ansible执行时间。在部署大规模服务器或引用模块很是多时,开启「pipelining」特性会给ansible带来显著的性能提高。linux

开启方法也很简单,将ansible.cfg的pipelining参数设置为True便可,该参数默认值是False。redis

既然「pipelining」特性默认是关闭的,确定有它的理由:关闭该特性能够与sudo的requiretty兼容(即/etc/sudoers配置文件的「Defaults requiretty」配置项)。大部分linux操做系统是默认开启requiretty功能的,因此pipelining也是默认False的。shell

也就是说,若是咱们要开启pipelining特性,要么playbook不使用sudo越权功能,要么取消sudo的「requiretty」特性数据库

该特性能够经过命令行添加 -vvvv 后,根据执行结果对比出区别,因篇幅缘由这里再也不展现。json

适用场景缓存

  • 管理大规模集群
  • 部署代码内容不少,调用了大量的ansible模块 

Control_path

control_path经过设置ControlPath sockets的文件路径与文件命名避免因sockets文件过长(超过108个字符串)致使ansible报错的问题。服务器

设置方法为更改ansible.cfg里的control_path参数,ansible2.7版本默认值为「配置项control_path_dir的值」+「根据hostname生成的哈希值」+「ssh端口号」+「用户名」网络

在ansible旧版本中,默认值是包含主机名的,这在一些特殊状况下(例如EC2主机),会因主机名过长致使ControlPath sockets文件过长,从而致使ansible执行报错。但在新版本中默认值的主机名部分被替换为主机名的哈希值,这很大程度上避免了该问题的发生。

咱们也能够设置其余的参数,例如:

control_path = %(directory)s/%%h-%%r

其中$directiry是control_path_dir的值,后面的参数能够灵活定制,可用参数以下:

%L 本地主机名的第一个组件 %l 本地主机名(包括域名) %h 远程主机名(命令行输入) %n 远程原始主机名 %p 远程主机端口 %r 远程登陆用户名 %u 本地 ssh 正在使用的用户名 %i 本地 ssh 正在使用 uid %C 值为 %l%h%p%r 的 hash

适用场景

当ansible报错而且使用 -vvvv 查看发现有相似「too long for Unix domain socket」的错误信息,咱们应该想到这个调优方式。 

Gather subset

Disable gather facts

在介绍Gather subset以前,咱们先简单说下gather_facts功能,gather_facts用于控制一个play是否收集目的主机的facts信息(参考《ansible基础-变量》),默认值为true/True/yes,写法以下:

- hosts: nodes gather_facts: True tasks:

在playbook执行过程当中,ansible收集facts变量是很耗时的一个步骤,若是咱们肯定play中没有用到fact变量信息,能够直接将其关闭,即将gather_facts设置为false/False/no。

Gather subset

可是在实际使用中不收集facts变量的状况不多。在gather_facts关闭的状况下,咱们能够给play单独添加一个setup模块,并经过gather_subset参数严格控制facts的收集种类,这样既拿到了咱们须要的fact变量又提升了ansible的执行效率,gather_subset参数的默认值为all。

playbook中使用方法示例:

- name: Collect only facts returned by facter setup: gather_subset: - '!all'
      - '!any'
      - facter

命令行使用方法示例:

# Collect only facts returned by facter. ansible all -m setup -a 'gather_subset=!all,!any,facter'

可用参数有all, min, hardware, network, virtual, ohai, facter,可使用列表的格式指定多个参数,使用「!」指定不收集的facts类型。

比较经常使用的几个范例:

  • 仅指定facter,说明收集puppet facter和min子集信息(默认包含min子集)。
  • 指定「!all」,说明只收集min子集信息
  • 指定「!all,!min」,说明不收集任何信息
  • 指定「!all,!any」+其余的fact子集,说明只收集该子集信息 

Fact gather cache

关于facts变量还有一个优化手段,即facts缓存。

fact缓存是指将收集到的facts信息缓存到本地json文件或者redis数据库内,以便下次执行直接读取,从而提升执行效率。

关于facts缓存,咱们在《ansible基础-变量》6.1.2 facts缓存有详细介绍,在这里就再也不重复介绍了。

Strategy

strategy的做用范围是一个play,经过设置不一样参数,控制一个play内全部任务的执行策略。

设置方法为更改ansible.cfg里的strategy参数,默认值为linear,可选参数为free;另一种方式是在playbook内定义该策略,格式为:

- hosts: all strategy: free tasks: ...

参数含义:

  • linear策略即线性执行策略,线性执行策略指主机组内全部主机完成一个任务后才继续下一个任务的执行,在执行一个任务时,若是某个主机先执行完则会等待其余主机执行结束。说直白点就是第一个任务在指定的主机都执行完,再进行第二个任务的执行,第二个任务在指定的主机都执行完后,再进行第三个任务的执行…… 以此类推。
  • free策略即自由策略,即在一个play执行完以前,每一个主机都各顾各的尽量快的完成play里的全部任务,而不会由于其余主机没执行完任务而等待,不受线性执行策略那样的约束。因此这种策略的执行结果给人感受是无序的甚至是杂乱无章的,并且每次执行结果的task显示顺序极可能不同。

举个🌰,展现下两种策略的执行效果:

playbook要实现的是三台主机debug出test_1,test_2,test_3三个字符串。当使用linear策略时,执行效果以下:

➜  lab-ansible ansible-playbook playbooks/test_trategy.yaml

PLAY [nodes] ***********************************************************

TASK [Gathering Facts] ***********************************************************
ok: [node3]
ok: [node2]
ok: [node1]

TASK [debug] ***********************************************************
ok: [node1] => {
    "msg": "test_1"
}
ok: [node3] => {
    "msg": "test_1"
}
ok: [node2] => {
    "msg": "test_1"
}

TASK [debug] ***********************************************************
ok: [node1] => {
    "msg": "test_2"
}
ok: [node3] => {
    "msg": "test_2"
}
ok: [node2] => {
    "msg": "test_2"
}

TASK [debug] ***********************************************************
ok: [node1] => {
    "msg": "test_3"
}
ok: [node3] => {
    "msg": "test_3"
}
ok: [node2] => {
    "msg": "test_3"
}

PLAY RECAP ***********************************************************
node1                      : ok=4    changed=0    unreachable=0    failed=0
node2                      : ok=4    changed=0    unreachable=0    failed=0
node3                      : ok=4    changed=0    unreachable=0    failed=0
执行结果

当使用free策略时,执行效果以下:

PLAY [nodes] ***********************************************************

TASK [Gathering Facts] ***********************************************************
ok: [node3]
ok: [node2]
TASK [debug] ***********************************************************
ok: [node3] => {
    "msg": "test_1"
}
ok: [node2] => {
    "msg": "test_1"
}
TASK [Gathering Facts] ***********************************************************
ok: [node1]

TASK [debug] ***********************************************************
ok: [node3] => {
    "msg": "test_2"
}
ok: [node2] => {
    "msg": "test_2"
}
TASK [debug] ***********************************************************
ok: [node1] => {
    "msg": "test_1"
}
TASK [debug] ***********************************************************
ok: [node3] => {
    "msg": "test_3"
}
ok: [node2] => {
    "msg": "test_3"
}

TASK [debug] ***********************************************************
ok: [node1] => {
    "msg": "test_2"
}

TASK [debug] ***********************************************************
ok: [node1] => {
    "msg": "test_3"
}

PLAY RECAP ***********************************************************
node1                      : ok=4    changed=0    unreachable=0    failed=0
node2                      : ok=4    changed=0    unreachable=0    failed=0
node3                      : ok=4    changed=0    unreachable=0    failed=0
执行结果

从上面两个个执行结果很明显的能看出区别,linear策略是遵循第一个任务、第二个任务、第三个任务……这样顺序执行下去的,而free策略则是无序的,甚至Gathering Facts任务也可能在debug任务以后执行。

Forks

forks用来设置同一时刻与目的主机链接数,也能够理解为主机并行数,默认值比较保守为5。在生产中,多数状况下咱们会更改这个参数。若是控制节点的CPU和网络性可以用,设置几十上百个也是能够的。

在ansible.cfg设置forks的全局默认值:

# ansible.cfg [defaults] forks = 15

命令行设置forks的数量,即在执行playbook时,经过「--forks」或「-f」指定: 

lab-ansible ansible-playbook playbooks/test_forks.yaml --fork 10

Serial

serial用于控制一个play内的主机并行数,这个并行数不能超过forks,超事后则serial不会生效。

定义方法以下:

--
- hosts: nodes serial: 2 tasks:

本质上,serial做用范围是一个play,受限于forks,但比forks控制的更加细节。假如咱们的forks设置为100,可是想让某个play里的全部任务并行数为50的执行,此时咱们应该想到serial这个调优方法。

Async and poll

同步阻塞模式和异步模式

  1. 同步阻塞模式指在playbook执行时,控制端和被控制端会一直保持链接状态,逐个任务的执行,直到该playbook执行完毕,这种模式称为同步阻塞模式,也是absible的默认执行模式。
  2. 异步模式指ansible将一次性运行全部的任务,并将全部的任务丢到后台执行,每一个任务有一个job_id,ansible会根据这个job_id每隔一段时间轮训检测该任务的执行状况,直到检测到任务执行结束。这种模式称为异步模式。

Async and pool

前面章节咱们所说的Strategy、Forks、Serial都是ansible同步阻塞模式下的优化方法,其中,strategy是经过控制任务执行策略进行优化,forks和serial是经过控制并行数进行优化。

针对某些特殊任务,尤为是可能被锁住或超时的任务,咱们能够采用ansible异步模式来提升执行效率。

async和poll分别用来指定异步模式下任务的最大运行时间和检测间隔时间,poll的缺省值为10。

示例以下:

---
- hosts: all remote_user: root tasks: - name: simulate long running op (15 sec), wait for up to 45 sec, poll every 5 sec command: /bin/sleep 15 async: 45 poll: 5

该示例中sleep命令采用异步的方式执行,ansible会等待该任务最长45秒,每隔5秒钟检测一次任务的执行结果。

特殊状况下,咱们能够将poll的值设置为0,这表明ansible将任务放到后台后,不会再管这个任务的执行状态,任其自生自灭。

这里举一个利用异步重启服务器的例子,因篇幅缘由,仅给你们展现部署代码,就不贴执行结果了,若是您感兴趣,能够亲自实践下:

---
- hosts: node1
  gather_facts: no
  tasks:
    - shell:
        cmd: grub2-set-default 0
      notify:
        - reboot
        - wait for reboot
        - wait for ssh start

  handlers:
    - name: reboot
      shell:
        cmd: shutdown -r now "Reboot triggered by ansible"
      async: 1
      poll: 0
      ignore_errors: True

    - name: wait for reboot
      wait_for_connection:
        timeout: 300

    - name: wait for ssh start
      wait_for:
        host: node1
        state: started
        delay: 10
        port: 22
        timeout: 30
reboot服务器示例

参考连接

  • https://docs.ansible.com/ansible/2.4/playbooks_acceleration.html
  • https://docs.ansible.com/ansible/2.4/intro_configuration.html#pipelining
  • https://docs.ansible.com/ansible/2.4/intro_configuration.html#control-path
  • https://docs.ansible.com/ansible/latest/modules/setup_module.html
  • https://docs.ansible.com/ansible/2.5/user_guide/playbooks_strategies.html
  • https://www.ansible.com/blog/ansible-performance-tuning
  • https://www.cnblogs.com/f-ck-need-u/p/7580170.html
  • https://docs.ansible.com/ansible/2.5/user_guide/playbooks_async.html

 

欢迎你们关注个人公众号:

相关文章
相关标签/搜索