ansible笔记(45):常用技巧(一)

栏目: 服务器 · 发布时间: 5年前

内容简介:所属分类:Ansible
  • A+

所属分类:Ansible 运维技术

在本博客中,ansible是一个系列文章,我们会尽量以通俗易懂的方式总结ansible的相关知识点。

ansible系列博文直达链接:ansible轻松入门系列

"ansible系列"中的每篇文章都建立在前文的基础之上,所以, 请按照顺序阅读这些文章,否则有可能在阅读中遇到障碍。

你可能会在实际使用ansible的过程中遇到一些小问题,这些小问题通常对应着实际的应用场景,你会在遇到这些小问题时搜索怎样解决,也许,你只是需要学会一些小技巧罢了,记住这些小技巧,能让我们在实际的工作中事半功倍,当然,这些都是见仁见智的,我只是将我觉得有用的进行总结,想到哪个写哪个,可能会分成几篇文章进行总结 。

小技巧:在ansible中使用 python 字符串的一些特性

ansible基于python实现,当我们在ansible中处理字符串时,能够借助一些python的字符串特性,比如,在python中可以使用中括号(方括号)截取字符串中的一部分,在ansible中也可以利用这一特性,示例playbook如下:

# cat test.yml
- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a[2]}}"

如上例所示,我们定义了一个字符串变量a,如果我们想要获取a字符串的第3个字符,则可以使用"a[2]"获取,索引从0开始,执行上例playbook,debug的输出信息如下:

TASK [debug] *************************
ok: [test71] => {
    "msg": "A"
}

可以从输出信息中看到,我们已经获取到了a字符串的第三个字符"A"

你也可以使用a[2:5]获取到a字符串的第3到第5个字符(不包含第6个字符)

使用a[:5]获取到a字符串的第6个字符之前的所有字符(不包含第6个字符)

使用a[5:]获取到a字符串的第6个字符之后的所有字符(包含第6个字符)

其实之前文章中总结的成员运算符"in"和"not in",也是python的字符串运算符

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "true"
    when: "'va' in a"

如上例所示,我们可以利用它们判断某个字符串是否包含另一个字符串

我们可以使用加号"+"连接两个字符串

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
    b: "vbB67890"
  tasks:
  - debug:
      msg: "{{a+b}}"

或者使用乘号"*"连续的重复输出字符串,比如将字符串a连续输出3次

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a*3}}"

上例的debug输出如下:

TASK [debug] *************************
ok: [test71] => {
    "msg": "vaA12345vaA12345vaA12345"
}

在python中,有很多内建的处理字符串的函数(或者称之为字符串方法),在ansible中我们也可以利用这些字符串函数,处理字符串。

比如,使用find函数查找指定字符在字符串中的位置,示例如下:

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a.find('A1')}}"

上例表示,找出字符串'A1'处于字符串a的位置,上例的debug输出如下:

TASK [debug] *************************
ok: [test71] => {
    "msg": "2"
}

输出结果是2,也就是说,"A1"在字符串a中的位置是3,当在字符串中没有找到对应的字符时,find函数的返回值为"-1",所以,我们也可以利用这一特性,判断字符串中是否包含指定的字符,如下:

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "not found"
    when: a.find('A2') == -1

在使用find函数时,也可以指定查找范围,find函数的语法是find(string,begin,end)

string是要查找的字符串,begin是起始位置,end是结束位置

比如,从字符串的第2个字符开始查找

- hosts: test71
  gather_facts: no
  vars:
    a: "vaA12345"
  tasks:
  - debug:
      msg: "{{a.find('A1',1)}}"

除了find函数,还有很多其他的字符串函数,你可以了解一下,动手试试,此处只是为了演示怎样在ansible中使用python的字符串函数,所以就不一一示例了。

小技巧:"任务委派",让某个任务在指定的主机上执行

当我们执行一个playbook时,需要设置目标主机,也就是说,playbook中定义的task会在目标主机上执行(一些特定的模块除外,某些模块天生就只会在ansible主机上执行,即使你指定了目标主机,它也仍然会在ansible主机上执行)。

但是,在某些场景下,我们需要指定某个任务在特定的主机上执行,举个例子,playbook中设置的目标主机是A、B、C三台主机,playbook中一共有5个task,因为某些原因,其中第3个task需要在D主机上执行,而不是在A、B、C这三台目标主机上执行,这个时候,我们该怎么办呢?我们可以使用最原始的方法,将第3个task单独设置成一个play段,然后将这个play段的目标主机设置为D,示意代码如下:

- hosts: A,B,C
  tasks:
  - task1:
      ...
  - task2:
      ...
 
- hosts: D
  gather_facts: no
  tasks:
  - task3:
 
- hosts: A,B,C
  tasks:
  - task4:
      ...
  - task5:
      ...

上述playbook虽然可以满足我们的目标,但是略显笨拙,因为上例中的大部分tasks都是需要在目标主机A、B、C上执行的,只是因为某些逻辑上的原因,task3需要到特定的主机上执行,难道每次遇到这种临时需要到特定主机上执行的任务,都需要单独分出一个play段吗?这样也太麻烦了吧,有没有更好的办法呢?当然有啦,遇到这种情况,我们就可以使用ansible的"任务委托"功能,"任务委派"可以让某个任务在指定的主机上执行,使用"delegate_to"关键字即可实现"任务委托"功能,示例如下:

- hosts: test70,test71
  gather_facts: no
  tasks:
  - file:
      path: "/tmp/ttt"
      state: touch
 
  - file:
      path: "/tmp/delegate"
      state: touch
    delegate_to: test61
 
  - file:
      path: "/tmp/ttt1"
      state: touch

如上例所示,上例中一共有3个tasks,第2个task使用了"delegate_to"关键字指定了对应的主机,test61,也就是说,第2个task只会在test61主机上执行,而不会在目标主机test70和test71主机上执行,但是第1个task和第3个task仍然会在目标主机test70和test71上执行,这样,就轻松的实现了我们想要的效果,通过"delegate_to"关键字,可以指定某个任务在特定的主机上执行,这个特定的主机可以是目标主机中的某一个,也可以不是目标主机中的任何一个。执行上例playbook,输出如下:

# ansible-playbook test1.yml
 
PLAY [test70,test71] *************************
 
TASK [file] *************************
changed: [test71]
changed: [test70]
 
TASK [file] *************************
changed: [test70 -> 10.1.1.61]
changed: [test71 -> 10.1.1.61]
 
TASK [file] *************************
changed: [test70]
changed: [test71]
 
PLAY RECAP *************************
test70                     : ok=3    changed=3    unreachable=0    failed=0  
test71                     : ok=3    changed=3    unreachable=0    failed=0

如你所见,第二个task都委托到test61主机上执行了。

小技巧:让某个任务在ansible主机上执行,而不是在目标主机上执行

默认情况下,task都会在目标主机上执行,但是在某些场景下,我们需要让某个task在ansible主机上执行,而不是在目标主机上执行,我们该怎么做呢?聪明如你一定想到了,刚才提到的"delegate_to"关键字不是正好能解决这个问题吗?我们只需要将"delegate_to"对应的主机设置成ansible主机即可,完全正确,"delegate_to"的确可以完美的解决这个问题,不过,除了"delegate_to",还有另外一种方法也能实现相同的效果,当我们想要让某个任务在ansible主机上执行,而不是在目标主机上执行时,可以使用"connection: local"来完成,示例如下:

- hosts: test70,test61
  gather_facts: no
  tasks:
  - file:
      path: "/tmp/inAnsible"
      state: touch
    connection: local
 
  - file:
      path: "/tmp/test"
      state: touch

上例中,第一个task使用了"connection: local",表示当前任务只在ansible主机本地执行,并不在目标主机上执行,快动手试试吧。

小技巧:"只跑一次",设置某个task只运行一次

默认情况下,一个task会在每个目标主机上都执行一遍,也就是说,如果目标主机有5台,那么一个task就会执行5遍(每一遍在不同的目标主机上执行),在某些场景下,我们希望某个任务只运行一次,而不是有多少个目标主机就运行多少次。

我来描述一个场景,在剧本的开始,我需要下载某个软件包到ansible主机,于是我使用了get_url模块,从网站上下载了这个包,但是由于目标主机中一共有5台,所以,下载包的这个task会重复执行5次,示例如下:

- hosts: A,B,C,D,E
  gather_facts: no
  tasks:
  - get_url:
      url: "http://nexus.zsythink.net/repository/testraw/testfile/test.tar"
      dest: /tmp/
    connection: local
 
  - copy:
      src: "/tmp/test.tar"
      dest: "/tmp"

执行上例playbook,你会发现,每个任务会针对每个目标主机都执行一遍,一共执行5遍,但是对于第一个task来说,没有必要执行5遍,因为只要执行一遍,我需要的安装包就会下载到ansible主机中,之后的4遍就没必要执行了,如果执行上例playbook,你会发现,由于ansible具备幂等性,当第一个task执行一次后,之后执行的4次其实并没有什么实质性的操作,但是,当你的安装包特别大、目标主机又特别多时,这些多余的操作仍然会浪费一些时间,所以,我们完全没有必要执行之后的4遍操作,这时,我们就需要借助到"run_once"关键字了,"run_once"关键字能让对应的任务只运行一次,示例如下:

- hosts: A,B,C,D,E
  gather_facts: no
  tasks:
  - get_url:
      url: "http://nexus.zsythink.net/repository/testraw/testfile/test.tar"
      dest: /tmp/
    connection: local
    run_once: true
 
  - copy:
      src: "/tmp/test.tar"
      dest: "/tmp"

如上例所示,我为第一个task设置了"run_once: true",这表示,即使目标主机有5台,这个task也只会运行一次。

运行上例playbook,你会发现,当执行get_url这个任务时,只运行了一次。

当任务设置了"run_once"以后,只会在操作第一个目标主机时,运行一次。

这篇文章就先总结到这里,希望这些小技巧能够对你有所帮助~

我的微信公众号

关注"实用运维笔记"微信公众号,当博客中有新文章时,可第一时间得知哦~


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Design systems

Design systems

Not all design systems are equally effective. Some can generate coherent user experiences, others produce confusing patchwork designs. Some inspire teams to contribute to them, others are neglected. S......一起来看看 《Design systems》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码