【Ansible】

  参考文档:【http://www.ansible.com.cn/docs/intro.html】

  和ansible类似的工具还有saltstack,puppet,sshpass等,都用于远程(批量)地管理服务器资源。各种工具实现原理不同,像ansible的话就是基于SSH开发的,这就表示其无需安装客户端,在一台全新的服务器上线之后(只要其有sshd服务在运行)就可以直接加入被管理的集群了。

  ■  安装验证

  安装ansible的话我还是用了yum install ansible,据说用pip也可以装。对于其他一些的系统,可以选择从源码开始安装。源码安装一年前自己那本笔记本上有,可参考。总的来说,ansible的安装还要求许多系统的组件如pcre,zlib以及其开发包、还有就是很多python模块如paramiko等。

  安装完成后先验证一下。ansible --version可以看到版本信息。

  ansible的主要配置文件在/etc/ansible中,修改其中的hosts文件,默认情况下应该全是注释,在合适的地方比如第12行左右写入一行127.0.0.1。这个hosts文件主要用来配置所有被控端,现在验证性地把本地先配置进去。

  ●  关于验证用户方式

  因为ansible基于SSH,所以不可避免的一个问题就是通过ansible远程连接主机时如何验证用户?两种方式,一个是密码,一个是公钥认证。

  如果选择通过密码来认证,可以在/etc/ansible/hosts的相应主机配置项后面加上" ansible_ssh_user=xxx ansible_ssh_pass=yyy",此外通过密码登录时还要保证目标主机在当前使用ansible的用户的known_hosts中,即要求其至少要登录一次。添加known_hosts的方法可以是手动ssh登录一下,然后添加公钥。在/etc/ansible/ansible.cfg中配置host_key_checking = False也可以取消公钥检查步骤,但是这样并不安全。

  其实,使用ansible的时候大概都是期望不要在配置文件中写入密码来通过ssh验证了,免密ssh验证的方法是ssh-keygen和ssh-copy-id两个命令一起用。默认配置时,ansible使用和当前用户同名的用户登录目标主机,因此需要目标主机的此用户的HOME/.ssh/authorized_key中有本机本用户的公钥。在此前提下,当我们用root用户执行,且/root/.ssh/authorized_key中有了root的公钥信息,此时执行

  ansible all -m ping

  来测试ansible的安装情况,如果返回中没有报错,就表示OK了。

■  关于hosts文件

  /etc/ansible/hosts文件指出了ansible被控端的一些配置。除了上面的简单配置,其实这个配置文件的形式可以非常丰富。比如上面说了在一个IP地址后面加上ansible_ssh_user和ansible_ssh_pass这两个额外的配置项。另外还可以加上ansible_ssh_port(默认22),ansible_ssh_host(主机名,假如你想给目标IP的主机取一个别名,但是又不想下到系统层面的/etc/hosts中去改,就可以在这里取完别名后加上此参数指明IP即可),ansible_ssh_private_key_file(指定私钥文件)还有ansible_connection,可选local,ssh或paramiko。一些其他额外配置选项如下:

ansible_sudo_pass
sudo 密码(这种方式并不安全,我们强烈建议使用 --ask-sudo-pass) ansible_sudo_exe (new in version 1.8)
sudo 命令路径(适用于1.8及以上版本) ansible_connection
与主机的连接类型.比如:local, ssh 或者 paramiko. Ansible 1.2 以前默认使用 paramiko.1.2 以后默认使用 'smart','smart' 方式会根据是否支持 ControlPersist, 来判断'ssh' 方式是否可行. ansible_shell_type
目标系统的shell类型.默认情况下,命令的执行使用 'sh' 语法,可设置为 'csh' 或 'fish'. ansible_python_interpreter
目标主机的 python 路径.适用于的情况: 系统中有多个 Python, 或者命令路径不是"/usr/bin/python",比如 \*BSD, 或者 /usr/bin/python
不是 2.X 版本的 Python.我们不使用 "/usr/bin/env" 机制,因为这要求远程用户的路径设置正确,且要求 "python" 可执行程序名不可为 python以外的名字(实际有可能名为python26). 与 ansible_python_interpreter 的工作方式相同,可设定如 ruby 或 perl 的路径....

  hosts文件的基本格式是ini格式的,ini中的每个section是一个服务器逻辑分组,每个option是一个服务器,然后option后面可以添加上面说的额外配置。如:

[localloop]
127.0.0.1 ansible_ssh_user=frank ansible_connection=paramiko

  section无形中也对服务器做了分组,我们就可以基于分组 对一部分主机进行操作了。一台主机也可分属于几个不同的组。

  hosts文件还支持多匹配的配置,比如下面这个配置:

[localloops]
127.0.0.[1:5] ansible_connection=paramiko ansible_ssh_user=root

 指的是127.0.0.1到127.0.0.5所有IP都放在localloops组中。如果在这个配置下运行ansible all -m ping的话就会收到5条回应(虽然127.0.0.x都是指本地机)。

  ●  变量

  对于批量管理系统,一个很重要的要素就是可以设置根据主机不同而不同的变量。在ansible中,变量被使用在playbook中以发起对主机不同而个性化的配置。变量的设置可以在hosts中进行。变量分成好几个层级的变量,最小的是主机变量,跟在主机后面直接设置:

127.0.0.1 http_port=80 maxRequestPerChild=808

  这两个变量的作用域只有这个主机一台。由于对变量名没有限制,所以前面说到的那些ansible的配置如果打错字了也不会报错,ansible会认为这是你指定的一个主机变量

  另外还可以设置组变量。设置组变量需要新开一个section,名为[组名:vars],如:

[localloop:vars]
http_port=8080

  另外,组之间可以通过[组名:children]的方式来指出组之间的隶属关系。比如

[localloop1]
127.0.0.[1:5] [localloop2]
127.0.0.[6:10] [localloops:children]
localloop1
localloop2

  如此之后,在父组中定义的变量将也会可以被子组使用

  也可以把变量的定义在hosts文件外完成,这就是分文件定义主机和组变量。在/etc/ansible/下创建两个目录: host_vars和group_vars,这两个组中再分别创建YAML格式的,对应主机or组名的文件。例如可以在/etc/ansible/group_vars中创建localloop文件,在/etc/ansible/host_vars中创建testhost,然后修改hosts配置如下:

-----/etc/ansible/hosts-----
[localloop]
testhost ansible_ssh_host=127.0.0.1 -----/etc/ansible/group_vars/localloop-----
key1: value1
key2: vaule2 -----/etc/ansible/host_vars/testhost-----
key3: value3

  至于变量的用处,主要是在playbook中使用,这个后面细说。

■  命令行调用API

  配置完hosts之后,在命令行中我们可以调用一些命令来使用ansible如上面的ansible all -m ping。总的来说,命令行的ansible工具大体格式是这样的:

  ansible <pattern> -m <module> -a <arguments>

  pattern是一个标识,规定出了一部分主机。比如可以写all或者*,就是代表所有主机;写组名,代表该组内的主机;写主机名,就代表这一个主机。如果主机名和组名冲突则以先规定的那个为准,而且命令行中会给出警告信息,提示有重名发生。另外也可以直接写域名或者IP(只要在hosts中有配置),甚至可以写192.168.1.*这种格式的来匹配一批主机。

  pattern中可以借助符号来规划简单的组分逻辑,如

  a:b  a组和b组的并集

  a:!b  属于a但不属于b的主机们

  a:&b  a组和b组的交集

  甚至可以有a[0]这种下标的形式来取得a组中指定第几个的主机,a[0-1]则是下标群,最万能的正则表达式则需要在pattern最前面加上~,如~(www|db)\.example\.com。需要注意一旦用上正则,那么点都要反转义了。

  ●  命令行使用时一些其他参数

  使用命令行时如果想动态的指定远程执行命令的用户,可以加入-u参数;

  -f命令控制命令执行的进程数。比如操控5个主机进行一个比较耗时的任务,那么-f 5说不定只要一个单位的时间就能搞定,而-f 1的话必然需要五个单位的时间才能搞定。完成任务后返回是及时的,有点像多线程模型,但这里是多进程的。另外ansible一定会按照-f指出的进程数fork出那么多个子进程,并不管是否真有那么多主机需要处理。这个参数的值默认是5,在ansible.cfg中有配置。

  --sudo可以让命令在远端通过sudo执行,当然没有在远端主机上配置运行sudo的话会要求输密码,在ansible中默认不提供这种进一步的交互所以直接报错。如果想要手动输入密码来继续sudo任务,可以在运行命令时加上--ask-sudo-password参数。但是考虑到自动化的目的,相信这个参数是不太常用的。

  -m参数是指出了使用的ansible模块。ansible模块这东西有的说说,这类先不细讲。目前用过的模块有ping, command, shell等。

  -a参数就是argument,指出某个模块要求的参数,通常-a后参数的值有一定格式要求。

  需要注意的是,命令行执行命令适合于一些简单的批量管理任务,面对更加复杂的配置,安装等任务应该使用ansible-playbook,两者之间的关系就像是linux命令行和shell脚本。至于playbook详细后面说。

 

■  关于配置

  上面简单提到过了/etc/ansible下的ansible.cfg配置文件是用来配置ansible主控端的一些参数,而/etc/ansible/hosts则是用来配置一些被控端主机信息的。下面详细来看下这些配置文件。

  首先是ansible.cfg,这是一个INI格式,#开头行注释的配置文件。在目前的ansible中,运行ansible时会依次加载 环境变量ANSIBLE_CONFIG,当前目录的ansible.cfg,~/.ansible.cfg,/etc/ansible/ansible.cfg,针对同一个配置项以最先加载到的为准。

  这些配置文件中,大多数配置都集中在名为defaults的section中,其中可以使用的option有

  action_plugins  action代码被执行时运行的一些插件(ansible支持开发者自己写插件使用,非常灵活),类似的还有callback_plugins,connection_plugins,filter_plugins,lookup_plugins,vars_plugins

  ansible_managed

  ask_pass  默认是False,当设置为True时,ansible执行会要求输入远端的密码,即使配置了免密登录。所以一般维持False

  forks  进程数,默认为5

  gathering  用来指出是否收集远程主机的facts(一些被控端的变量),默认的值是implicit,每次都会收集,explicit表示不收集,smart表示扫描主机,对已经收集过的不收集

  host_key_checking  之前说过了,是否检验被控端主机的公钥,默认是True

  inventory  被控端配置文件(它的官方名称是inventory),默认是/etc/ansible/hosts

  log_path  日志文件,默认/var/log/ansible.log

  module_name  在不指出-m的参数时默认使用的模块,默认值是command,建议可以改成shell

  nocolor  默认为0,设置为1时ansible不会为不同状态(成功or失败or警告)的结果染不同颜色

  nocow  运行playbook的时候默认输出会有一头字符画的牛,设置为1可以关掉牛的显示(哈哈哈哈哈哈哈)

  pattern  当没有给出pattern时的默认pattern,默认值是*即所有主机

  poll_interval  ansible中有异步任务,这个配置设置一个秒数,当执行开始后每隔这么多秒查询一次任务状态

  remote_tmp  一些ansible任务涉及到文件的传输,而传输的第一目的地就是这个配置项

  remote_user  远端用什么用户执行任务,默认是和主控端当前用户名称一致的用户

  timeout  SSH连接超时时间

  

  除了defaults这个section之外,还有一些section可以配置比如Paramiko Specific Settings,OpenSSH Specific Settings等等。由于这些都是比较高端的玩法,就不多介绍了。

【Ansible-playbook】

  playbook的基本语法是YAML格式的。这个格式长成这样:

---
- hosts: local
 name: this is a test for playbook
remote_user: root
tasks:
- name: test to ping
ping: -------------------运行后返回是-------------------
PLAY [this is a test for playbook] ************************************************************************************************************************ TASK [Gathering Facts] **************************************************************************************************************
ok: [testhost2]
ok: [testhost1]
ok: [testhost3] TASK [test to ping] *****************************************************************************************************************
ok: [testhost3]
ok: [testhost2]
ok: [testhost1] PLAY RECAP **************************************************************************************************************************
testhost1                  : ok=2    changed=0    unreachable=0    failed=0   
testhost2                  : ok=2    changed=0    unreachable=0    failed=0   
testhost3                  : ok=2    changed=0    unreachable=0    failed=0 

  解释一下,playbook有一个根节点,下面的第一级子节点被称为一个个play。这里只有一个play。此play名为this is a test for playbook,其含义就是对主机组local,以root的身份进行名为test to ping的任务,具体内容是利用ping模块,参数为空进行操作。返回内容中可以看到有gathering facts板块,这个参看前面配置文件中说到的gathering项。关于facts的具体内容相信后面也会再讲。另外需要注意的一点就是返回的内容并不是在各个远端执行的stdout,而是一个状态码。比如我把模块换成了shell: echo hello,返回内容不是hello而也是ok。所以在使用command或者shell模块的时候通常会采用 xxxx || /bin/true的方式。

  运行方式是ansible-playbook test.yaml,ansible-playbook这个命令也可以加很多和ansible一样的参数,比如-f 10就是开10条进程来进行操作。上面说通过ansible获取到的返回信息是有限的,如果想要获取到更多的信息,可以加上参数--verbose。这样返回的信息中就会包含一些其他的比如stdout,stderr等输出的信息了。如果在正式运行playbook之前想查看本次playbook会对哪些主机进行操作的话可以加上参数--list-hosts来提前检查一下。

  其中比较中心的是tasks这个列表,tasks中包含了很多task。这些task会针对hosts字段定义的主机组中相应主机,从上到下依次进行task操作。每个task的本质是执行一个模块(module),除了少数如ping一样的模块是不用参数,大多数模块需要提供参数。参数中可以使用在配置文件、命令行参数等多个地方定义的变量。在playbook中调用变量的格式采用Jinja2的语法,比如:

---
- hosts: local
tasks:
- name: make dir {{ name }}
command: mkdir {{ name }}

  name变量可以定义是组变量,也可以是主机变量。可以察觉到当其是主机变量且各个主机配的name值不同的时候,返回内容会返回什么这个问题。经过实验,返回的是第一个主机的变量值。

  利用playbook执行模块只做必要的改动,如果ansible检测到模块动作的目的在执行前就已经达到,那么就会放弃本次操作。可以说即使重复执行playbook也是安全的。而像对于shell,command这样的命令执行模块而言是个例外,重复执行playbook等于重复执行命令。为了避免这样的情况发生,可以为参数中添加一个flag=creates来保证不重复操作。

  这种特性用术语来说就是每一个task都具有“幂等性”。

  ■  一个task的其他参数

  上面的例子中说到了一个task中最主要的两个字段,name(指出task名)以及<模块名>(指出task的具体操作)。除了这两个之外,task还可以写一些其他的字段参数。

  比如notify,notify下面跟着的每一条记录被称为handler。前面说过ansible在执行模块动作时会检测动作的目的是否已经达到,如果达到那么可以在task结束的时候做一些钩子操作。设置这个钩子操作的就是handlers了。需要注意的是,一个handler本身也是一个task,只不过它通过notify的形式在主task中被调用。由于handler本身就是task,所以说handler本身也具有幂等性,即不论主task通过notify调用了多少次同一个handler,在所有task结束之后这个handler都只被执行最多一次。handler的常用场景是在配置等变更后通过handler来重启服务等。下面是一个带有handler的task的例子:

tasks:
- name: change configuration
template: template/nginx.tpl.conf /etc/nginx/nginx.conf
notify:
- restart nginx handlers:
- name: change configuration
shell: /usr/sbin/nginx -s reload || /bin/true

  上面的例子中task中有个template字段参数,template字段有点像saltstack里面的file.manage模块中的template字段,其将指定的一个本地的模板文件中的变量具体化,然后将其传送到目标主机上的指定位置。变量可以来自于之前所说的多种多样的变量定义手段。

  ■  include(import)和roles

  include(在较新的版本中已经提示include关键字不再鼓励使用,应该使用更加确切的import_tasks和import_playbook)可以在一个playbook中引用进一些其他yaml文件的信息。这种引用可以在多个层面进行,比如在play这一层面进行引用那就是将其他文件中定义的play一并加入到当前文件中来执行。

  如果引用是发生在task层面,那么就是在一个play中的tasks下面声明引用,相对应的,被引用文件内容也是一个tasks集合。

  此外引用还可以插入到handlers中去,但是由于handler就是一个task,考虑这一点的话其实handlers中进行include的本质和在tasks下面进行是类似的。下面给出例子

---
- name: this is a test for playbook
hosts: local
tasks:
- name: test connection
ping: - import_tasks: mytask.yml - import_playbook: playbook/myplaybook.yml

  在tasks中引入了mytask.yml文件中定义的task,在整个playbook中引入了myplaybook.yml中定义的那些play。

  另外还需要指出,当在task层面进行引入的时候,除了引入一个具体的yml文件,还可以引入一个带有模板变量的文件,并且可以在引入之后定义变量的具体值(当然用其他手段定义的变量也都可以使用)。此时关键字不能写import_tasks而应该写include_tasks。这种引入模板的操作只有在task层面才能进行。

  

  在了解了playbook的引入机制之后,接下来的重点就是要说明一下roles这个ansible里面的重要概念了。一个role把一部分的task,handler等ansible要素逻辑上抽象成一个集合,我们可以基于这个集合进行ansible操作。而在playbook中,我们只要指出哪些机子是什么role(role和主机间多对多关系),那个角色该执行的所有操作都会被执行上去。

  那么如何定义一个role? 首先是在ansible.cfg中有一个配置项roles_path,这是一个用冒号隔开的多个路径。每个路径都被认为是roles路径。若这些路径下有名为testrole的目录,则表示有名为testrole的一个role。假设我们在某一个roles目录下的testrole目录结构如下:

testrole
├── defaults
├── files
├── handlers
├── meta
├── tasks
├── templates
└── vars

  在playbook中指定role的方式如下:

---
- hosts: local
roles:
- testrole

  指定之后,此play还可以补充一些其他内容,并且针对local这个主机组认可了以下行为:

  若testrole/tasks/main.yml存在,则其中定义的tasks将被添加到play中执行

  (main.yml中应该直接从task开始写,连tasks都是不用写的,也就是说类似- name:xxx\n  shell: xxx。下面也都是类似,直接从被引用那个层级开始写)

  若testrole/handlers/main.yml存在,则其中定义的handlers将被添加到play中(被添加到的意思是在这个play的context中可以直接写其name来使用,下同)

  若testrole/vars/main.yml存在,则其中定义的变量将被添加到play中

  若testrole/meta/main.yml存在,则其中定义的角色依赖将被添加到roles列表中

  若testrole/files存在,其中的文件和脚本可以分别被指定模块为copy和script类的task直接引用而不用加上路径

  若testrole/templates存在,其中的模板文件可以被template类task直接引用而不用加上路径

  若testrole/tasks存在,其中的文件可以被直接import_tasks等类型task直接引入,而不用加上路径

  

  执行roles相关操作的优先级是高于一般定义的tasks的,也就是说tasks会在roles全部完成之后再被执行。关于给roles具体化一些变量,以及role之间的依赖等内容先不说了。

■  关于变量

  ansible的变量使用jinja2的语法制成,支持了{{ var }}之类的变量语法以及变量相关的一些过滤器方法,同时也支持{% if %}{% for %}等jinja2语法规定的逻辑结构,一般而言这些逻辑结构更多的用在template模块的模板中,而不是playbook本身中,playbook本身更多的是用了简单的变量形式。小提醒一下,若变量在一个值的开头,要用引号引起,要不然解析yaml的时候会以为我们在试图声明一个字典。

  上面所说的所有变量,几乎都是我们自定义的变量。其实ansible为我们准备了很多内置的变量,一部分跟主机相关的被称为facts。

  facts的值根据主机不同而不同,ansible会为我们自动收集这些数据。一台主机具体有哪些facts并且值是多少可以ansible <host> -m setup来查看。数据量挺大的需要注意。可以注意到,在默认配置gathering为implicit的时候是不收集facts的,所以就无法将facts的变量名应用在ansible中。如果设置成了其他两个,那么在ansible执行之前一定会去gather一下facts。有时确认不需要用到facts,还想要加快运行速度的时候可以在相关play中加上gather_facts: no作为参数。

  facts是一个JSON结构的数据,其根节点的KEY名是ansible_facts,实际使用时不用写出这个根节点。比如{"ansible_facts": {"ansible_all_ipv4_addresses": ["xxx","yyy"]}}这个不完全的facts结构,如果在模板中想要获取yyy的值,那么可以直接{{ ansible_all_ipv4_addresses[1] }}即可。

  另一部分则是和ansible系统本身相关的变量,这些变量通常是一些预设的变量名比如groups, hostvars, group_names。这些变量名我们不能覆盖,具体哪些内容可以试验一下看看。只需要记得,这些变量都是和ansible本身相关,不随某一次playbook的运行而变化。

  除了在playbook运行之前定义变量,tasks被执行前gather一下facts之外,在tasks运行过程中也可以使用变量。这种操作被称为注册变量。注册变量是指将某一个task的返回结果保存下来,并且供给给后续其他task使用。一般而言,这种机制常和条件判断一起使用。

  脱离开playbook本身,从ansible的命令行来看(不论是ansible还是ansible-playbook),都可以在后面加上参数--extra-vars来指定额外的变量。后面跟的值的格式可以是--extra-vars "var1=value1 var2=value2"或者JSON格式的 --extra-vars {"var1":"value1", "var2": "value2"}

  现在来总结下可以定义变量的地方:

  首先在inventory(也就是默认的/etc/ansible/hosts文件)中,可以定义变量,可以给单个主机定义(直接跟在一个主机行后面),也可以给一整个组定义(开一个新的section)

  其次,在/etc/ansible/group_vars和/etc/ansible/host_vars下也可以定义变量。方法是创建和组/主机同名的文件,文件格式是yaml,里面定义变量。

  再次,roles的vars目录下的main.yml中也可以定义变量。

  此外,ansible有内置的变量,分成facts(内置主机变量,随着主机变化而变化)和其他一些和ansible相关,诸如groups,group_names的变量。

  在playbook的运行过程中,还可以把某一个task的返回作为变量的值保存下来。

  命令行加上--extra-vars也可以指定额外变量

  当这些地方声明的变量之间命名冲突了怎么办,优先级是这样的,命令行的--extra-vars最为优先,然后是inventory文件中定义的变量(包括/etc/ansible/host|group_vars),然后是play中定义的,roles中定义的变量等,然后是facts等系统内置变量。

■  条件判断和When语句

  通过when语句进行条件判断,并结合注册变量,可以在play的执行过程中加入逻辑顺序。比如下面这段:

tasks:
- name: first step
command: /bin/false
register: result
ignore_errors: True
- name: do when failed
command: /bin/dosomething
when: result|failed
- name: do when success
command: /bin/dosomethingelse
when: result|success
- name: do when skipped
command: /bin/other_something
when: result|skipped

  注意到,when语句的值中可以使用jinja2过滤器,将变量做一些处理后返回一个布尔值的判断结果给when语句。当符合when语句规定的条件时,自然when语句所在的task就会被执行了。

  ignore_errors参数指出,如果当前task失败了是否忽略错误继续往下执行其他task。

  更加灵活的when语句的使用方法还有诸如在其他地方定义一个变量然后给when用。比如定义了var: True的话,在when: var的时候就可以执行task,还有when: var is not defined这种用法来判断一个变量是否被定义。简单的判断相等,不等,大于小于也可以用when: xxx == "yyy",when: var|int <= 10之类的,就不再一一列举了。

  import的时候以及play在关联role的时候,均可以使用when条件语句来进行逻辑判断后再执行操作。

  ●  关于注册变量

  之前简单提到了下注册变量的内容,注册变量实质是将某一个task的返回的对象(完整对象可以通过--verbose参数来查看,是一个JSON格式的东西)保存下来。所以有时候如果想要获取到返回结果输出到stdout的值,可以result.stdout来调用。下面就是一个分析stdout输出的例子:

- name: test
shell: cat /tmp/testfile
register: result
- name: test2
shell: echo "find word hello in testfile"
when: result.stdout.find('hello') != -1 # find方法是来源于python的,python中对字符串的处理方法这里基本都可以用上

  其他诸如stderr,stdout_lines都可以调用,详细可以用上--verbose看返回的结果到底是怎样一个JSON。

■  循环结构

  这里要说的循环不是基于JINJA2模板语法的循环,而是本身ansible提供的对于playbook逻辑的循环。试想这样一些场景,比如你要在新服务器上一次性新增多个用户,或者要通过yum一次性安装好多包。当然你可以把每一个用户/每一个包写成一个task,但这样会很麻烦。通过循环结构,只要控制每次的用户名/包名不同,其他操作都是相同的,就可以更加轻松方便了:

- name: add many users
user: name={{item.name}} state=present groups={{item.group}}
with_items:
- {"name": "Frank","group": "FrankG"}
- {"name": "Takanashi", "group": "TakanashiG"}

  with_items,其中item是前面循环每个单元的代号,是固定的,事实上下面所有循环的方法的循环体内单元的代号都是item。像这个例子给出的是对一个字典的列表的循环,而一般情况下也可以单纯的对一个列表循环。

  如果指出是with_nested,那么在下面可以指出多个列表,进行笛卡尔积式的作业。比如:

- name: test
shell: echo "{{item[0]}}: {{item[1]}}"
with_nested:
- ['a','b']
- ['1','2','3']

  这个task最终的输出是在每台机子上分别都输出了a:1,a:2,a:3,b:1,b:2,b:3。(实验了下,with_nested出来的result不是一个和其他简单输出一样的带有stdout什么的结构,而是有一个字段名为results的列表)

  除了with_items和with_nestsed,ansible中还有许多这种内置定义了的循环关键字:

  with_fileglob  以非遍历的方式循环一个指定目录下的文件名,通常可以和template,copy等模块相结合

  with_subelements  对于一些层级比较复杂的数据结构来说,可以直接循环遍历其指定名字的一个子字段

  with_sequence  类似于range函数,可以指定start,end,stride,format等,通过它来生成一个有数字规律的字符串列表供playbook使用如with_sequences: start=0 end=10 stride=2 format=var%d

  with_random_choice  下可跟若干个字符串,随机选中一个

■  其他一些playbook的特性

  ●  加速模式

  对于较老版本的ansible用户,以及还在使用比较老的系统版本主机的用户,ansible提供了所谓的加速模式可以在操作上加快很多。使用方法就是在play中指出accelerate: true。

  ●  异步和轮询

  在默认情况下,ansible会在操作过程中一直保持SSH连接,当操作任务耗时较长,并且操作主机较多时维护这样的连接显然有些成本过高。所以ansible也提供了异步的模式。在异步模式下,操作请求发出之后每隔一个轮询时间去查询一次,当查询到操作结果则返回,并且设置有一个超时时间。

  使用方法是在task中指出ansyc: nn,nn是超时时间的指定。同时也可通过poll: n来指出轮询间隔时间。若不设置轮询时间默认是10秒。

  ●  检查

  对于某个playbook会影响哪些主机,之前说过只要加上--list-hosts参数即可。

  那么对于其到底做哪些变化,可以用--check参数来检查。同时还可以加上--diff参数,这样还可以看到本次playbook对目标主机上的文本会做出什么变化。在--check模式下的所有变更都不是真实的变更,而只是做一个预览,比较方便。

  ●  错误处理

  前面说过了,当设置一个task的ignore_error为true或者yes的时候,这个task即使出错也会跳过它继续执行下面的几个task。与之相对的,也可以手动抛出错误。方法如下:

  fail: msg="the task is failed"

  failed_when: "'ERROR' in res.stderr"  这个是有条件的发起失败。当然,也可以通过fail+when两个子句来实现。

更多的一些关于模块的内容我打算另开一篇写写

【Ansible】 基于SSH的远程管理工具的更多相关文章

  1. linux远程管理工具

    一.常见的远程管理控制方式主要有以下几种 ①RDP(remote desktop protocol)协议 远程桌面协议,我们常用的windows操作系统就是的远程桌面管理就是基于该协议的. ②teln ...

  2. 【Linux远程管理】SSH协议远程管理

    SSH(Secure Shell)协议.命令行界面(CLI)下的远程管理工具,几乎所有的操作系统都有,区别于Telnet,SSH在进行数据传送时会对数据进行加密,所以SSH是比较安全的协议.几乎所有的 ...

  3. 基于Web的IIS管理工具

    Servant:基于Web的IIS管理工具   Servant for IIS是个管理IIS的简单.自动化的Web管理工具.安装Servant的过程很简单,只要双击批处理文件Install Serva ...

  4. Linux学习--第二天--分区、格式化、系统安装、vmware、远程管理工具

    分区 主分区加上扩展分区只能有四个,其中扩展分区只能有一个,扩展分区不能写入数据,不能格式化,只能包含逻辑分区.这是硬盘的限制. 格式化 分为高级与低级.文件系统是高级格式化.低级是硬盘操作. 扩展分 ...

  5. 强大的安卓手机远程管理工具 – Droidjack

    免责声明:本站提供安全工具.程序(方法)可能带有攻击性,仅供安全研究与教学之用,风险自负! Droidjack是一款针对安卓手机远程管理工具,你可以利用它在PC上对手机进行远程操控,不仅功能强大,使用 ...

  6. 使用远程管理工具Xshell

    介绍 目前常用的远程管理工具 Xshell -- 免费版/收费版 SecureCRT Putty 安装Xshell 选择免费版即可 连接服务器 连接成功 Xshell连接不上排查流程 还有可能是Lin ...

  7. 给ambari集群里的kafka安装基于web的kafka管理工具Kafka-manager(图文详解)

    不多说,直接上干货! 参考博客 基于Web的Kafka管理器工具之Kafka-manager的编译部署详细安装 (支持kafka0.8.0.9和0.10以后版本)(图文详解)(默认端口或任意自定义端口 ...

  8. win7利用tsmmc.msc远程管理工具

    win7和xp默认不带tsmmc.msc远程管理工具.我们只需要从2003的windows\system32目录下复制 mstsmhst.dll ,mstsmmc.dll 和tsmmc.msc文件放到 ...

  9. 10.Windows远程管理工具RAT----Metasploit基础----Metasploit模块----fsociety工具包

    Windows远程管理工具RAT QuasarRAT github.com/quasar/QuasarRAT 命令环境 MINGW64 (GCC编译器) mkdir RAT cd RAT git cl ...

随机推荐

  1. SQL Server使用侦听器IP访问时遇到"The target principal name is incorrect. Cannot generate SSPI context"

    在测试SQL Server 2016 Always On时,在创建侦听器后,在客户端使用SSMS, 可以用侦听器名称访问Always On集群,但是使用侦听器IP访问时遇到"The targ ...

  2. android自定义Notification通知栏实例

    项目有个需求,需要在发送Notification的时候动态给定url的图片.大概思路如下:自己定义一个Notification的布局文件,这样能够很方便设置View的属性. 首先加载网络图片,使用Bi ...

  3. Jenkins Android 自动打包配置

    一.Jenkins自动打包配置 目标:1. 自动打包:2. 自动上传:3. 友好下载 1. Jenkins简介 Jenkins是基于Java开发的一种持续集成工具,用于监控持续重复的工作. 减少重复劳 ...

  4. 使用WinDbg内核调试

    首先你要配置好测试环境:参考VMware+Windgb+Win7 内核驱动调试 在你的主机上配置Symbols 配置sympath,C:\Users\Admin\Desktop\first\objch ...

  5. Java Web项目报错总结

    Java Web项目报错总结 1.java.lang.IllegalStateException java.lang.IllegalStateException Caused by:java.lang ...

  6. Maven入门(含实例教程)

    原文地址:http://blog.csdn.net/u013142781/article/details/50316383 Maven这个个项目管理和构建自动化工具,越来越多的开发人员使用它来管理项目 ...

  7. FusionCharts报错收录

    FusionCharts报错 1.错误一 DesignTimeError:#25081843 flash-chart render Error >>#25081843:IECompatib ...

  8. 芝麻HTTP:TensorFlow LSTM MNIST分类

    本节来介绍一下使用 RNN 的 LSTM 来做 MNIST 分类的方法,RNN 相比 CNN 来说,速度可能会慢,但可以节省更多的内存空间. 初始化 首先我们可以先初始化一些变量,如学习率.节点单元数 ...

  9. freemarker获取封装类中对象的属性(六)

    freemarker获取封装类中对象的属性 1.设计思路 (1)封装学生类 (2)创建数据模型 (3)新建student.ftl (4)运行Junit测试文件,生成HTML文件 2.封装学生类 Stu ...

  10. 从零一起学Spring Boot之LayIM项目长成记(三) 数据库的简单设计和JPA的简单使用。

    前言 今天是第三篇了,上一篇简单模拟了数据,实现了LayIM页面的数据加载.那么今天呢就要用数据库的数据了.闲言少叙,书归正传,让我们开始吧. 数据库 之前有好多小伙伴问我数据库是怎么设计的.我个人用 ...