一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
Hosts 执行的远程主机列表
Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最
少元素需包括 name 和 task,一个name只能包括一个task
Variables 内置变量或自定义变量在playbook中调用
Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此
会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地
长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
常见选项
语法:ansible-playbook <filename.yml> ... [options]
常见选项:
--syntax-check #语法检查,可缩写成--syntax, 相当于bash -n
-C --check #模拟执行,只检测可能会发生的改变,但不真正执行操作,dry run
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
例:[root@node01 ansible]# ansible-playbook --syntax-check 文件名 --limit 10.0.0.150
-i INVENTORY #指定主机清单文件,通常一个项对应一个主机清单文件
[root@node01 ansible]# ansible-playbook hello,yml -i hosts 这会扫描 hosts 里面的主机地址,host 可以从/etc/ansible/hosts 拷贝过来,然后,里面添加删除自己想要的IP
--start-at-task START_AT_TASK #从指定task开始执行,而非从头开始,START_AT_TASK为任务的
name
-v -vv -vvv #显示过程
执行:
用法:[root@node01 ansible]# ansible-playbook 文件名
范例1:安装httpd
---
#This is a playbook file
- hosts: webservers #主机名,取的是/etc/ansible/hosts 里面,自己定义的webservers 下面的IP
remote_user: root #用户,指明是root 用户执行
tasks: #这是固定格式
- name: install httpd #- name 是固定格式,后面的install httpd 解释说明的意思,意思是告诉我们,我要装httpd
yum: name=httpd # yum: 模块,ansibles 里面的功能模块,后面跟 name=httpd 意思就是 yum install httpd
- name: start httpd service #- name 是固定格式,后面的start httpd servic解释说明的意思,意思是告诉我们,我要启动httpd服务
service: name=httpd state=started enabled=yes # 具体启动命令,service: ansibles 的功能模块,
解释一下,--- 是固定格式 #注释说明,这种脚本要注意空格缩进,同级别的前面的空格一样多
范例2:卸载httpd
---
#This is a playbook file,remove httpd
- hosts: webservers
remote_user: root
gather_facts: no #收集机器信息,no 是不收集,yes 是收集 在用变量的时候,如果要取stetup 自带的变量,必须用yes
tasks:
- name: remove httpd package
yum: name=httpd state=absent #state=absent 代表卸载
- name: remove apache user
user: name=apache state=absent
- name: remove config file
file: name=/etc/httpd state=absent
- name: remove web html
file: name=/data/html/ state=absent
具体里面这些service yum shell ping file 都是ansible 的模块功能。
还可以扫描文件执行,比如,在/etc/ansible/hosts 文件拷贝到当前路径下
[root@node01 ansible]# ansible-playbook hello,yml -i hosts 这会扫描 hosts 里面的主机地址,然后取执行
忽略错误 ignore_errors
如果一个task出错,默认将不会继续执行后续的其它task
利用 ignore_errors: yes 可以忽略此task的错误,继续向下执行playbook其它task
---
- hosts: websrvs
tasks:
- name: error
command: /bin/false
ignore_errors: yes
- name: continue
command: wall continue
Playbook中使用handlers和notify
Handlers本质是task list ,类似于MySQL中的触发器触发的行为,其中的task与前述的task并没有本质
上的不同,主要用于当关注的资源发生变化时,才会采取一定的操作。而Notify对应的action可用于在
每个play的最后被触发,这样可避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完
成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操
作
注意:
如果多个task通知了相同的handlers, 此handlers仅会在所有tasks结束后运行一 次。
只有notify对应的task发生改变了才会通知handlers, 没有改变则不会触发handlers
handlers 是在所有前面的tasks都成功执行才会执行,如果前面任何一个task失败,会导致handler跳
过执行,可以使用force_handlers: yes 强制执行handler
#install nginx
- hosts: webservers
remote_user: root
gather_facts: no
force_handlers: yes #无论task中的任何一个task失败,仍强制调用handlers
tasks:
- name: add group nginx
group: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: install nginx
yum: name=nginx state=present
- name: config file
copy: src=files/nginx.conf dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: web page
copy: src=files/index.html dest=/usr/share/nginx/html/index.html
- name: start nginx
service: name=nginx state=started enabled=yes
handler:
- name: restart nginx #名字和上面的notify一样
service: name=nginx state=restart
tags组件 贴标签
在playbook文件中,可以利用tags组件,为特定 task 指定标签,当在执行playbook时,可以只执行特
定tags的task,而非整个playbook文件
可以一个task对应多个tag,也可以多个task对应一个tag
还有另外3个特殊关键字用于标签, tagged, untagged 和 all,它们分别是仅运行已标记,只有未标记和所
有任务
#install nginx
- hosts: webservers
remote_user: root
gather_facts: no
force_handlers: yes #无论task中的任何一个task失败,仍强制调用handlers
tasks:
- name: add group nginx
group: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: install nginx
yum: name=nginx state=present
- name: config file
copy: src=files/nginx.conf dest=/etc/nginx/nginx.conf
notify: restart nginx
tags: conf #一个标签的时候这么写
#多个标签可以成下面的格式
tsgs: [conf,file] #写在一行
- conf #写成多行
- file #写成多行
- name: web page
copy: src=files/index.html dest=/usr/share/nginx/html/index.html
- name: start nginx
service: name=nginx state=started enabled=yes
[root@ansible ~]#ansible-playbook --list-tags httpd.yml #列表,显示有几个标签
[root@ansible ~]#ansible-playbook -t conf,service httpd.yml
[root@ansible ~]#ansible-playbook --skip-tags conf httpd.yml # 只执行conf 这个标签
[root@ansible ~]#ansible-playbook httpd.yml --skip-tags untagged
Playbook中使用变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量定义
variable=value
variable: value
范例
http_port=80
http_port: 80
变量调用方法
通过 {{ variable_name }} 调用变量,且变量名前后建议加空格,有时用"{{ variable_name }}"才生效
变量来源有多种:
1. ansible 的 setup facts 远程主机的所有变量都可直接调用
2. 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value test.yml
3. 在playbook文件中定义
vars:
var1: value1
var2: value2
4. 在独立的变量YAML文件中定义
- hosts: all
vars_files:
- vars.yml
5. 在主机清单文件中定义
主机(普通)变量:主机组中主机单独定义,优先级高于公共变量
组(公共)变量:针对主机组中所有主机定义统一变量
6. 在项目中针对主机和主机组定义
在项目目录中创建 host_vars和group_vars目录
7. 在role中定义
变量的优先级从高到低如下
-e 选项定义变量 -->playbook中vars_files --> playbook中vars变量定义 -->host_vars/主机名
文件 -->主机清单中主机变量--> group_vars/主机组名文件-->group_vars/all文件--> 主机清单组
变量
使用 setup 模块中变量
本模块自动在playbook调用,不要用ansible命令调用,生成的系统状态信息, 并存放在facts变量中
facts 包括的信息很多,如: 主机名,IP,CPU,内存,网卡等
facts 变量的实际使用场景案例
通过facts变量获取被控端CPU的个数信息,从而生成不同的Nginx配置文件
通过facts变量获取被控端内存大小信息,从而生成不同的memcached的配置文件
通过facts变量获取被控端主机名称信息,从而生成不同的Zabbix配置文件
.范例:
---
#var.yml
- hosts: webservers
remote_user: root
gather_facts: yes
tasks:
- name: create log file
file: name=/data/{{ ansible_nodename }}.log state=touch
~
在playbook 命令行中定义变量
vim var2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
[root@ansible ~]#ansible-playbook -e pkname=httpd var2.yml
#也可以将多个变量放在一个文件中
[root@ansible ~]#cat vars
pkname1: memcached
pkname2: vsftpd
[root@ansible ~]#vim var2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package {{ pkname1 }
yum: name={{ pkname1 }} state=present
- name: install package {{ pkname2 }
yum: name={{ pkname2 }} state=present
[root@ansible ~]#ansible-playbook -e pkname1=memcached -e pkname2=httpd
var5.yml
[root@ansible ~]#ansible-playbook -e '@vars' var2.yml
#在文件中创建并引用
cat vars2.yml
---
var1: httpd
var2: nginx
cat var6.yml
---
- hosts: web
remote_user: root
vars_files:
- vars2.yml
tasks:
- name: create httpd log
file: name=/app/{{ var1 }}.log state=touch
- name: create nginx log
file: name=/app/{{ var2 }}.log state=touch