ansible笔记(10):初识ansible playbook 假设,咱们想要在test70主机上安装nginx并启动,咱们能够在ansible主机中执行以下3条命令 ansible test70 -m yum_repository -a 'name=aliEpel description="alibaba EPEL" baseurl=http://mirrors.aliyun.com/epel/7/$basearch' ansible test70 -m yum -a 'name=nginx disable_gpg_check=yes enablerepo=aliEpel' ansible test70 -m service -a "name=nginx state=started" 咱们经过上述3条命令,先肯定配置了对应的yum源,而后使用yum模块安装了nginx,最后使用service模块启动了nginx,最终达到了咱们的目的。 可是在实际的工做环境中,咱们可能须要常常在新主机上安装nginx,难道每次有新的服务器加入工做环境,咱们都要修改上述3条命令中的主机名而且从新将每一条命令执行一遍吗?这样彷佛有些麻烦,确定有更好的办法,没错,咱们能够将上述命令写成脚本,每次修改一些变量,而后执行脚本就好了,这样彷佛方便了很多,而ansible天生就提供了这种相似"脚本"的功能,在ansible中,相似"脚本"的文件被称做"剧本",'剧本'的英文名称为'playbook',咱们只须要将要作的事情编写成playbook,把不一样的模块按照顺序编排在剧本中,ansible就会按照剧本一步一步的执行,最终达到咱们的目的,虽然playbook的功能与脚本相似,可是剧本并非简单的将ad-hoc命令按照顺序堆砌在一个可执行文件中,编写剧本须要遵循YAML语法,若是你没有接触过YAML语法,不用惧怕,坚持看完后面的示例,熟悉一些固定套路之后,你也能够本身编写playbook。 那么怎样编写playbook呢?咱们先从一个简单的示例开始 首先,咱们须要建立一个YAML格式的playbook文件。 playbook文件以".yaml"或者".yml"做为文件名后缀,此处咱们建立一个名为"test.yml"的剧本文件。 在编写剧本以前,咱们先来回顾两个简单的ad-hoc命令,好比以下两条命令: [root@node1 data]# ansible test211 -m ping [root@node1 data]# ansible test211 -m file -a "path=/data/test211 state=directory" 上述命令表示使用ping模块去ping主机test70,而后再用file模块在test70主机上建立目录,那么,若是把上述命令转换成playbook的表现形式,该如何书写呢?示例以下 (此处先进行示例,后文会说明怎样执行playbook) --- - hosts: test211 remote_user: root tasks: - name: ping the host ping: - name: make directory test file: path: /data/testfile state: directory 如上所示,第一行使用三个横杠做为开始,在YAML语法中,"---"表示文档开始。 第二行使用"- "做为开头(注意:横杠后面有空格),若是你了解过YAML语法,那么你必定知道YAML使用"- "表示一个块序列的节点,若是你不了解YAML语法,不用在此处纠结,先这么写,写的多了,天然会理解,从上例能够看出,"- "后面使用hosts关键字指定了要操做的主机,hosts关键字对应的值为test70,表示咱们要在test70主机上进行操做,"hosts: test70"是一个键值对,注意,在YAML语法中使用冒号映射键值对时,'冒号'后面必须有'空格',这也是语法,没有为何,记住就好,若是你想要一次性在多台主机上进行操做,能够同时写多个主机,每台主机使用逗号隔开,好比'hosts: test70,test61',若是你在清单中对主机进行了分组,也可使用组名。 第三行,使用remote_user关键字能够指定在进行远程操做时使用哪一个用户进行操做,'remote_user: root'表示test70的root用户进行操做,上图中,remote_user关键字与hosts关键字对齐,表示它们是平级的,以前的文章中提到过,在YAML语法中进行缩进时,不能使用tab键进行缩进,必须使用空格,因此,为了兼容使用tab键进行缩进的使用习惯,能够将vim编辑器设置为自动将tab转成空格。 第四行,使用tasks关键字指明要进行操做的任务列表,以后的行都属于tasks键值对中的值。 以后的行都属于tasks任务列表中的任务,能够看出,整个任务列表一共有两个任务组成,每一个任务都以"- "开头,每一个任务都有本身的名字,任务名使用name关键字进行指定,第一个任务使用ping模块,使用ping模块时没有指定任何参数。第二个任务使用file模块,使用file模块时,指定了path参数与state参数的值。 好了,test.yml已经编写完成了,可是,咱们尚未运行这个剧本,运行剧本须要使用'ansible-playbook'命令,示例以下 [root@node1 data]# ansible-playbook test.yml PLAY [test211] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************************** TASK [Gathering Facts] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************** ok: [test211] TASK [ping the host] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************** ok: [test211] TASK [make directory test] ********************************************************************************************************************************************************************************************************************************************************************************************************************************************** changed: [test211] PLAY RECAP ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** test211 : ok=3 changed=1 unreachable=0 failed=0 如上图所示,playbook执行后返回了一些信息,这些信息是此次剧本运行的概况。 'PLAY [test211]'表示此次运行的playbook中有一个'play'是针对test211这台主机运行的,一个'playbook'是由一个或多个'play'组成的,这样说可能不太容易理解,那么咱们打个比方,一个'剧本'是由一个或多个'桥段'组成的,每一个桥段都有不一样的场景、人物、故事,全部的桥段组合在一块儿,组成一个完整的剧本,剧本就是playbook,桥段就是play,而上例中,整个剧本中只有一个桥段,也就是说,上例的playbook中,咱们只写了一个play,在下文中咱们会举例说明怎样书写多个play,到时候你会更加明白到底什么是所谓的'play',固然,'桥段'只是我本身为了方便理解给'play'起的中文名,官方名称只叫"play"。 从上述信息能够看出,仅有的这个play是针对test211运行的,这个play一共包含三个任务,第一个任务的名字叫作'Gathering Facts',第二个任务的名字叫作'Ping the host',第三个任务的名字叫作'make directory test',看到此处你会发现,咱们在playbook中明明只写了两个任务,为何最后执行时却有三个任务呢?这是由于,每一个play在执行时,都会先执行一个默认任务,这个默认任务就是'Gathering Facts','Gathering Facts'任务会收集当前play对应的目标主机的相关信息,收集完这些基础信息后,才会执行咱们指定的任务,因为上例中,hosts的值只有test211一个主机,因此这个play只针对test211运行,因此'Gathering Facts'这个任务只收集了test211的相关信息,执行完默认任务后,开始执行'Ping the host'任务和'make directory test'任务,因为在执行playbook以前,/testdir/test目录已经存在于test211主机中,因此'make directory test'任务返回的信息是绿色的,若是对应的目录并不存在,'make directory test'任务返回的信息应该是黄色的,这是由于幂等性的缘故,前文已经解释过,此处再也不赘述。 当playbook中的全部play执行完毕后,在返回信息的'PLAY RECAP'中能够对全部目标主机的执行状况进行'回顾',因为咱们的目标主机只有test211一台,因此只看到了test211的执行归纳信息。 咱们已经执行了一个playbook,这个playbook中只有一个play,咱们也能够在这个playbook中多写几个play,示例以下: --- - hosts: test211 remote_user: root tasks: - name: pint the host ping: - name: make directory test211 file: path: /data/test211 state: directory - hosts: test212,test215 remote_user: root tasks: - name: touch file file: path: /touchfile state: touch - hosts: test212 test215 remote_user: root tasks: - name: create user jack user: name: jack 如上所示,上例中有多个play,第一个play针对test211执行,这个play会执行两个任务。 第二个play针对test212和test215执行,第二个play只包含一个任务,即在对应的目标主机上建立/touchfile文件 第三个play针对test212和test215执行,细心如你必定发现了,当你须要在play中指定多个主机时,有两种语法可使用,第二个play和第三个play中的语法均可以指定多个主机,第三个play也只包含一个任务,即在test212和test215主机上建立jack用户。 多个play写完之后,咱们来运行一下剧本试试 以下所示,每一个play执行时都会显示当前play对应的目标主机,而且每一个play执行时都会先执行默认的facts任务,收集对应目标主机的信息,当全部play都执行完毕后,会出现'PLAY RECP',至关于一个小的报告信息,看到这里,你应该已经理解了到底什么是所谓的'play'了吧。 [root@node1 data]# ansible-playbook test2.yml PLAY [test211] **************************************************************** TASK [Gathering Facts] ******************************************************** ok: [test211] TASK [pint the host] ********************************************************** ok: [test211] TASK [make directory test211] ************************************************* ok: [test211] PLAY [test212,test215] ******************************************************** TASK [Gathering Facts] ******************************************************** ok: [test215] ok: [test212] TASK [touch file] ************************************************************* changed: [test212] changed: [test215] PLAY [test212 test215] ******************************************************** TASK [Gathering Facts] ******************************************************** ok: [test215] ok: [test212] TASK [create user jack] ******************************************************* changed: [test215] changed: [test212] PLAY RECAP ******************************************************************** test211 : ok=3 changed=0 unreachable=0 failed=0 test212 : ok=4 changed=2 unreachable=0 failed=0 test215 : ok=4 changed=2 unreachable=0 failed=0 若是你并非很熟悉YAML语法,你能够不用过于深究YAML语法,只须要死记硬背,记住某些"固定套路"便可编写playbook,写的多了,天然会对这些语法有所理解 若是你的playbook写完了,可是你不能肯定playbook文件中是否存在语法错误,那么你可使用以下命令对playbook进行语法检查 [root@node1 data]# ansible-playbook --syntax-check /data/test2.yml 执行上述命令后,若是只返回了playbook的名称,就表示没有语法错误。 除了对playbook进行语法测试,咱们还可以'模拟执行'playbook,'模拟执行'并非真正的执行,只是'伪装'执行一下,playbook中的任务并不会真正在目标主机中运行,因此你能够放心大胆的进行模拟,使用以下命令便可模拟运行playbook,模拟运行功能能够帮助咱们'预估'playbook是否可以正常执行。 [root@node1 data]# ansible-playbook --check test2.yml 注意:使用上述命令进行'模拟'时,一些任务可能会报错,这多是由于报错的任务在执行时须要依赖以前的其余任务的完成结果,可是由于是'模拟'执行,因此以前的任务并不会真正的执行,既然以前的任务没有真正的执行,天然不会产生对应的结果,因此后面的任务就报错了,也就是说,咱们并不能彻底以'模拟'的反馈结果做为playbook是否可以正常运行的判断依据,只能经过'模拟'大概的'预估'一下而已。