playbook可以理解成剧本,即一份文件可以存放多个ansible任务。后续的操作全部按照playbook中定义的动作执行

playbook使用YAML格式

YAML有自己的书写格式,操作时一定要严格按照此格式执行,后面会详细介绍其格式

playbook示例:

首先编辑yaml格式的文件,而此文件中统一定义要执行的操作:vim  test.yaml     - hosts: webservers   #指定操作的远程主机   remote_user: root   #以root身份执行以下tasks  tasks:   - name: install nginx               #任务的名称,即在执行时显示的标题名称    yum: name=nginx state=latest      #调用yum模块,与单独使用yum模块时的用法是一样的  - name: start nginx     service: name=nginx enabled=true state=started  #service模块- hosts: dbservers     #另一组远程主机  remote_user: root  tasks:   - name: install redis     yum: name=redis state=latest   - name: install conf file    copy: src=/root/redis.conf dest=/app/ owner=redis group=root mode=0644  - name: start redis     service: name=redis state=started#以上注意hosts与name前要有短横线打头,这是yaml的格式要求#而且tasks和其后面的具体任务要错开,即不能顶格配置name、service等ansible-playbook  --list-hosts test.yaml#主机检查ansible-playbook  --list-tasks test.yaml#任务检查ansible-playbook  --syntax-check test.yaml#语法检查

存在两个问题

1)只想执行test.yaml中的某一个任务怎么做

2)配置文件修改了,服务怎么重启,要知道service模块的配置中state已经配置为started了,不会再添加state为restarted

上述两个问题都需要执行任务但是只能将所有任务重新执行一遍,效率不高

问题1)的解决方案:给任务加标签

vim test.yaml tasks:   - name: install redis     yum: name=redis state=latest   - name: install conf file    copy: src=/root/redis.conf dest=/app/ owner=redis group=root mode=0644    tags: install    #加此标签,执行时指定此标签则只执行此任务,未加标签的任务不执行  - name: start redis     service: name=redis state=started    tags: start#而且可以指定多个标签,多个任务也可以使用同一个标签,当调一个标签时可以执行多个任务ansible-playbook  --list-tags test.yaml #查看哪些hosts打了标签ansible-playbook  -t install,start test.yaml#指定标签执行

问题2)的解决方案:

条件式触发任务,在配置文件被修改时会触发handlers机制vim test.yaml- hosts: dbservers  remote_user: root  tasks:   - name: install redis     yum: name=redis state=latest   - name: install conf file    copy: src=/root/redis.conf dest=/etc/ owner=redis group=root mode=0644    tags: install     notify: restart redis service   #条件通知,当此任务即要复制的文件被修改了notify就会通知handlers执行触发任务  - name: start redis     service: name=redis state=started    tags: start  handlers:    #条件触发器,只有满足特定条件才会执行后续任务  - name: restart redis service     service: name=redis state=restarted#handlers依然调用service模块重启,这样只有配置文件修改才会触发handlers,才会执行此处的service。#正常配置文件未改变的情况下不会触发此任务ansible-playbook  -t install  test.yaml  #将redis.conf的bind端口修改后,测试即可

还有一个问题需要注意,即如何根据实际情况调整参数

如redis.conf配置文件中有maxmemory字段,表示用于redis的内存容量,如果想将此容量调整为当前主机的内存容量的一半该怎么做。

要知道多个远程主机的内存容量不一定是一样的,有的是4G有的是16G如何根据主机自身的内存容量来配置呢?解决方案如下:

这个就用到了变量variablesfacts变量:ansible dbservers -m setup |  less用户自定义变量:    a、在playbook中定义变量,如下:     vim tree.yml  - hosts: webservers  remote_user: root  vars:   #定义变量,其格式是 变量名+冒号+值  - pkgname: tree  tasks:  - name: install {
{ pkgname }} pkg   #调用变量使用花括号    yum: name={
{ pkgname }} state=latest   #在执行任务时就可以调用变量然后测试即可ansible-playbook  -C tree.yml       b、在ansible-playbook命令中指定变量,其优先级高于playbook中定义的,如下:     接着上述步骤a进行操作     ansible-playbook -e "pkgname=memcached" -C tree.yml      #在命令行中使用-e指定变量的键值,tree.yml只是本次测试使用         c、通过roles传递的变量,后续介绍        d、host inventory主机列表中定义的变量:    vim /etc/ansible/hosts     [webservers]    192.168.1.106 pkgname=redis    192.168.1.107 pkgname=redis    #在定义主机列表时定义    如果同一组内主机变量全部相同,即向一个组传递相同变量,还可以使用下述方法定义:    [webservers:var]    pkgname=redis

模板与变量引用:通常需要在模板中调用变量

template模块:jinja2语法格式,类似于copy模块vim redis.yml  - hosts: webservers  remote_user: root  tasks:  - name: install redis maxmem    template: src=/root/redis.conf dest=/tmp/ owner=redis mode=666 #在此任务中我们使用template模块,其提供模板功能,用法类似于copyvim redis.conf maxmemory {
{ ansible_memtotal_mb /2 }}mb#ansible_memtotal_mb是ansible内置变量,可以参与多种运算#在控制端,定义ansible内置变量并进行除法运算,即取本本机内存空间的一半#这样即使远程多台主机的内存大小不一致,此变量仍会取内存大小的一半并将取出的最终结果定义在此配置文件中传给远程主机ansible-playbook  redis.yml   #template支持嵌套脚本的文本文件这是与copy模块的主要区别#此示例可以上述提到的根据具体主机分别设置参数的问题。关键就是使用template模块并使用正确的变量

条件测试:

when语句,只有满足when条件才会执行任务cat dfile.yml  - hosts: webservers  remote_user: root  tasks:  - name: copy file    copy: src=/root/diff1.txt dest=/app/    when: ansible_default_ipv4['address'] == '172.18.251.244'  #只有满足此条件才能够执行此任务    #此条件说明当地址为127.18.251.244时执行copy模块的操作,ansible_default_ipv4是ansible的内置变量,中括号[]表示调用变量的子键    #  - name: copy file2    copy: src=/root/diff2.txt dest=/app/    when: ansible_default_ipv4['address'] == '192.168.1.107'    #ansible-playbook  --syntax-check dfile.yml #检查语法ansible-playbook  dfile.yml

循环:迭代

需要重复执行任务,如在远程主机上安装多个程序包cat tomcat.yml  - hosts: dbservers  remote_user: root  vars:  - jdk_version: 1.8.0   #定义变量  tasks:  - name: install  pkgs    yum: name={
{ item }} state=latest   #变量的调用方法是{
{ }},而item是变量,其内容就是with_items中的    with_items:     - nginx    - java-{
{ jdk_version }}-openjdk   #此处使用变量调用上文的内容    - tomcat     - tomcat-webapps    - tomcat-docs-webapp    - tomcat-admin-webapps    #以上是在一个任务中要安装的软件包    扩展:以上是在一个任务中安装多个软件包,如果是创建多个用户、组也是类似的方法    总结:迭代循环配合变量,迭代的关键字段是with_items,变量的调用使用{
{ }}    ansible-playbook  tomcat.yml   #执行操作

下面思考一个问题:

如果使用循环方式安装多个软件包,而每个软件包的版本号基本是不一样的,那如何动态的在安装软件包时添加版本号,而不是事先写好在yaml文件中?

解决上述问题需要调用字典cat tomcat.yml  - hosts: dbservers  remote_user: root  tasks:  - name: install  pkgs    yum: name={
{ item.name }}-{
{ item.version }} state=latest   #item是使用循环的固定变量,此处item变量调用字典内容    with_items:    #此处即所谓的字典,定义好软件包名称和版本号    - { name: 'nginx', version: 1.10.2 }    - { name: 'tomcat',version: 7.0.69 } #在一个任务中使用字典安装软件ansible-playbook  -C tomcat.yml再来看下面这个例子:循环加字典的使用在控制端修改了两份文件:tomcat-users.xml和 server.xml现在要是先的是将此二份文件通过copy模块复制到远程主机cat tomcat.yml - hosts: dbservers  remote_user: root  tasks:  - name: install config file     copy: src={
{ item.file }} dest={
{ item.conf }}    with_items:    - { file: '/root/server.xml',conf: '/etc/tomcat/server.xml' }    - { file: '/root/tomcat-users.xml',conf: '/etc/tomcat/tomcat-users.xml' }#在字典中我们定义file和confansible-playbook  tomcat.yml#完成上述步骤,就可以到远程主机上查看指定路径的文件是否已经修改过

roles  角色:

vim /etc/ansible/ansible.cfg roles_path    = /etc/ansible/roles   #roles的路径/etc/ansible/roles/nginx/   #其中nginx就是一个角色,在nginx目录下应该具有特定的目录层级结构,如:handlers  tasks  templates  varscat /etc/ansible/roles/nginx/tasks/main.yml    #tasks是nginx角色的一个任务模块,main.yml是固定格式不能改变- name: install nginx pkg  yum: name=nginx state=latest- name: start nginx service   service: name=nginx state=started enabled=true  #此任务模块完成两个动作,安装nginx和启动nginx  然后配置playbook文件cat websrv.yml - hosts: webservers  remote_user: root  roles:   #不需要像以前那样配置tasks之类的,而是直接指定角色  - nginx   #对webservers的主机以root身份调用nginx角色,而nginx橘色定义了两个task任务ansible-playbook  -C websrv.yml #测试总结:创建角色nginx,配置playbook文件,而此文件只需调用角色即可,具体操作已经在角色的模块中定义好了示例:基于模板生成nginx配置文件第一步定义nginx内的变量                    #定义变量,将被templates模板调用cat /etc/ansible/roles/nginx/vars/main.yml nginx_server_port: 8888nginx_server_name: www.abc.comnginx_doc_root: /webdata第二步配置nginx下的模板文件                #定义模板文件,调用vars变量,此模板将用于生成nginx服务的配置文件cat /etc/ansible/roles/nginx/templates/web-conf.j2 server {        listen {
{ nginx_server_port }};        server_name {
{ nginx_server_name }};        location  / {                root {
{ nginx_doc_root }};        }}第三步定义nginx下的任务文件                #定义多项任务,安装nginx、配置文件、创建文件、开启服务cat /etc/ansible/roles/nginx/tasks/main.yml  - name: install nginx pkg  yum: name=nginx state=latest- name: install conf file  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf- name: create datadir  file: path={
{ nginx_doc_root }} state=directory    #此目录即nginx模板文件中将使用的- name: start nginx service   service: name=nginx state=started enabled=true第四步配置playbook文件                #定义webservers组中主机以root身份调用nginx角色,而nginx角色能做什么上述三个步骤已定义cat /root/websrv.yml - hosts: webservers  remote_user: root  roles:  - nginx第五步测试iansible-playbook   websrv.yml #执行完上述操作,在远程webservers主机的/etc/nginx/conf.d/web.conf文件中就会有nginx模板下web-conf.j2文件的内容#

接着以上述实验为基础,再继续延伸

定义handlers模块进入nginx角色目录下cat handlers/main.yml - name: restart nginx service  service: name=nginx state=restarted然后我们修改vars下的文件内容,如将端口修改cat vars/main.yml nginx_server_port: 8888   #变量改变,templates文件就会变化,templates文件变化就会触发notify执行handlers的动作接着在tasks下修改触发条件cat tasks/main.yml - name: install conf file  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf  notify: restart nginx service   #此处notify定义的与handlers中的name对应最后playbook文件内容不变ansible-playbook  websrv.yml 试想一下,如果每次修改配置文件,都要全部执行一遍playbook操作太麻烦而且也不必要所以我们可以使用tags标签,指定标签的任务才会执行,如:vim tasks/main.yml  name: install conf file  template: src=web-conf.j2 dest=/etc/nginx/conf.d/web.conf  notify: restart nginx service  tags: changed   #指定标签,这样修改配置文件后我们只要对特定标签进行操作即可- name: create datadir  file: path={
{ nginx_doc_root }} state=directory   tags: changed   #此处使用与配置文件相同标签,因为配置文件如果修改了目录此处也要跟着修改  #完成上述操作,我们可以修改配置文件,然后ansible下发配置即可  ansible-playbook -t changed -C websrv.yml  #测试以上测试使用到模板文件、变量文件、触发器、任务管理模块 ,下面来使用静态文件复制nginx的配置文件 静态文件:  编辑在角色下的files文件,作为静态文件  vim files/nginx.conf    #随便修改写内容,如日志格式,只要能看到效果即可  cat  tasks/main.yml    #修改tasks配置文件- name: install config file2  copy: src=nginx.conf dest=/etc/nginx/nginx.conf    #复制静态文件  notify: restart nginx service    #启动触发,一旦此文件被修改就会执行handlers操作  tags: changed    #同样的此任务也加入同一标签中  然后执行即可  ansible-playbook -t changed  websrv.yml

结束