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如何根据主机自身的内存容量来配置呢?解决方案如下:
这个就用到了变量variables
facts变量:
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模块,其提供模板功能,用法类似于copy
vim 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和conf
ansible-playbook tomcat.yml
#完成上述步骤,就可以到远程主机上查看指定路径的文件是否已经修改过roles 角色:
vim /etc/ansible/ansible.cfg
roles_path = /etc/ansible/roles #roles的路径
/etc/ansible/roles/nginx/
#其中nginx就是一个角色,在nginx目录下应该具有特定的目录层级结构,如:handlers tasks templates vars
cat /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: 8888
nginx_server_name: www.abc.com
nginx_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
第五步测试i
ansible-playbook websrv.yml
#执行完上述操作,在远程webservers主机的/etc/nginx/conf.d/web.conf文件中就会有nginx模板下web-conf.j2文件的内容
#本文出自 “a_pan” 博客,谢绝转载!
原文地址:http://panpangao.blog.51cto.com/10624093/1983203