示例
实现Tomcat war包自动更新及重启
ansible-playbook /root/code/deploy.yml -e host=$remoteServerName -e backDir=${backDir} -e packageName=${packageName} -e tomcatDir=${remoteProjectDir}
# 指定主机名- hosts: "{{ host }}"# 定义变量vars:service_name: tomcatservice_port: 8081# 也可以通过文件来导入变量vars_files:- vars.yml# 不收集客户端信息,可以加快脚本执行速度gater_facts: no# 指定用户remote_user: root# 下面构成playbook的tasks,每个task都由 - name: 开始,name指定该任务的名称tasks:- name: shutdowm tomcatshell: source /etc/profile && bash {{ tomcatDir }}/bin/shutdown.shregister: results- name: pausepause: seconds=20- name: rm projectfile: path={{ tomcatDir }}/webapps/{{ packageName }} state=absent- name: upload warcopy: src={{ backDir}}/{{ packageName }}.war backup=no dest={{ tomcatDir }}/webapps/# 执行notify触发对应的handlersnotify:- tomcat start- tomcat status# 定义了三个handlers,和py函数类似,不会自动执行,需要notify去调用handlers:- name: tomcat shutdownshell: source /etc/profile && bash {{ tomcatDir }}/bin/shutdown.sh- name: tomcat startshell: source /etc/profile && nohup bash {{ tomcatDir }}/bin/startup.sh &- name: tomcat statusshell: ps -ef|grep {{ tomcatDir }}|grep -v 'grep {{ tomcatDir }}'
使用handlers注意点
- Handlers只有在其所在的任务被执行时,才会被运行;如果一个任务中定义了notify调用Handlers,但是由于条件判断等原因,该任务未被执行,那么Handlers同样不会被执行。
 - Handlers只会在每一个play的末尾运行一次;如果想在一个playbook中间运行Handlers,则需要使用meta模块来实现。例如: -meta: flush_handlers.
 - 如果一个play在运行到调用Handlers的语句之前失败了,那么这个Handlers将不会被执行。我们可以使用meta模块的—force-handlers选项来强制执行Handlers,即使Handlers所在的play中途运行失败也能执行。
 
注册变量
其实就是将操作结果,包括标准输出和标准错误输出,保存到变量中,然后再根据这个变量的内容来决定下一步的操作,在这个过程中用来保存操作结果的变量就叫注册变量。
一个注册变量通常会有以下4个属性:
- changed:任务是否对远程主机造成的变更。
 - delta:任务运行所用的时间。
 - stdout:正常的输出信息。
 stderr:错误信息。
- hosts: allremote_user: rootgather_facts: notasks:- name: test the register variablesshell: uptime# 使用关键字register声明注册变量,上面uptime命令产生的结果,存入到results中。结果是字典形式register: results- name: print the register result# 使用debug模块,打印出上面命令的输出结果。debug: msg="{{ results.stdout }}"
when条件判断
很多任务只有在特定条件下才能执行,这就是when语句发挥作用的地方。
一个简单的实例,关闭掉ip地址为10.0.102.162服务器上的mysql服务
- hosts: allremote_user: roottasks:- name: shut down the db serverservice: name=mysqld state=stoppedwhen: ansible_eth0.ipv4.address == "10.0.102.162"
任务委托
默认情况下,ansible所有任务都是在我们指定的机器上面运行的,当在一个独立的集群环境配置时,这并没有什么问题。而在有些情况下,比如给某台服务器发送通知或者向监控服务器中添加被监控的主机,这个时候任务就需要在特定的主机上运行,而非一开始指定的所有主机,此时就需要ansible的委托任务。
- hosts: allremote_user: roottasks:- name: stop the db serverservice: name=mysqld state=stopped# 这里使用了委托,仅关闭162这台服务器上,这个play仅在162这台服务器上执行。delegate_to: 10.0.102.162- name: check mysql statusservice: name=mysqld state=running
任务暂停
有些情况下,一些任务的运行需要等待一些状态的恢复,比如某一台主机或者应用刚刚重启,我们需要等待它上面的某个端口开启,此时我们就不得不将正在运行的任务暂停,直到其状态满足我们的需求。
这个实例中,这个任务将会每10s检查一次主机webserver1上面的80端口是否开启,如果超过了300s,80端口仍未开启,将会返回失败信息。
- name: wait for webserver to startlocal_action:module: wait_forhost: webserver1port: 80delay: 10timeout: 300state: startted
迭代
使用同一个模块循环安装软件包
- hosts: centos75-2tasks:- name: 安装软件包yum: name={{ item }}with_items:- ftp- lftp- wget
roles
将耦合较高的脚本化代码转变为目录结构化,一个分类,将web、db等分为各自的大组,在各个角色内定义具体的小任务,方便管理,另一方面,类似于php的类的自动加载,roles基于一个已知的文件结构,可以自动去加载某些vars_files、tasks、handlers等。
每个角色,以特定的层级目录结构进行组织: 注意:大多数都是复数”s”,除了meta
    web/
        files/        存放由copy或script模块等调用的文件
        templates/  template模块查找所需要的模板文件目录
        handlers/   至少应该包含一个名为main.yml文件
        vars/        至少一个main.yml
        tasks/        基本元素:至少一个名为main.yml的文件,其他的文件需要在此文件中通过include进行包含
        meta/        main.yml,定义当前角色的特殊设定,及其依赖关系
        default/      设定默认变量时使用此目录中的main.yml文件
1.tasks    
[root@localhost nginx]# vim roles/db/tasks/main.yml# This playbook will install Mysql and create db user and give permissions.- name: Install Mysql packagyum: name={{ item }} state=installedwith_items:- mysql-community-server- MySQL-python- name: Create Mysql configuration filetemplate: src=my.cnf dest=/etc/my.cnfnotify:- restart mysqld- name: Start Mysql Servicservice: name=mysqld state=started enabled=yes
templates 目录中有存放的my.cnf
2.添加handler
[root@localhost nginx]# vim roles/db/handler/main.yml# Handler to handle DB tier notifications- name: restart mysqldservice: name=mysqld state=restarted
3.变量
- hosts: websrvsremote_user: rootvars:- username: testuser1- groupname: testgroup1tasks:- name: create groupgroup: name={{ groupname }} state=present- name: create useruser: name={{ username }} group={{ groupname }} state=present
4.site
[root@localhost nginx]# vim site.yml# This playbook deploys the whole application stack in this site.- name: apply common configuration to all nodeshosts: allremote_user: rootroles:- common- name: configure and deploy the webservers and application codehosts: webserversremote_user: rootroles:- web- name: deploy MySQL and configure the databaseshosts: dbserversremote_user: rootroles:- db
5.运行playbook脚本
ansible-playbook site.yml

在vars和default中定义的变量有什么区别?
- 在(vars/main.yml)中定义的变量比在play其他地方定义vars字段的优先级高,这就造成,除非将变量座位参数显式传递给role,不然就无法覆盖变量值。
 - 后来Ansible引入了默认role变量的概念(defaults/main.yml),它的优先级低。所以如果playbook中定义了另一个同名的变量,这个值将会被覆盖。
 
总结:如果你认为可能需要变更role变量的值,那么使用默认变量(defaults/main.yml)。如果你不希望修改role变量的值,那么使用常规的role变量就行了。
