简介在ansible中playbook是由多个play组成的列表paly的主要功能在于将事先归并为⼀组的主机装扮成事先通过ansible中的task定义好的⾓⾊,从根本上讲,所谓的task⽆⾮是调⽤ansible的module讲多个play组织在⼀个playbook中,即可以让它们连同起来按事先编排好的机制运⾏
palybook采⽤的是YAML语⾔编写的
palybook核⼼元素
hosts # 执⾏的远程主机列表
tasks # 任务集
varniables # 内置变量或者⾃定义变量在playbook中调⽤
templates # 模板,可替换模板⽂件中的变量并实现⼀些简单的逻辑⽂件
handlers和notify # 两个集合使⽤,由特点条件触发的操作,满⾜条件⽅才执⾏,否则不执⾏
tags # 标签,指定某条件任务执⾏,⽤于选择运⾏playbook中的部分代码
# ansible具有幂等性,因此会⾃动跳过没有变化的代码,即便如此,有些代码为测试其确实没有发⽣变化的时间依然会⾮常的长,此时,如果确信其没有变化,就可以通过tags跳过这些代码
常⽤元素⽰例
hosts元素
hosts元素
指定被控端的远程主机列表
[root@ansible ~]# vim /root/ansible/hosts.yml
---
- hosts: web
remote_user: root
在hosts后⾯的主机列表形式可以是单个主机的主机名、IP地址、组名,或者两个组的并集、交集、差集,⽐如:
brian.com # 单个主机名
192.168.192.129 # 单个IP
web # ⼀个组名
web:db # 两个组的并集
web:!db # 两个组的差集
web:&db # 两个组的交集
remote_user表⽰的是执⾏远程的⽤户,⼀般为root
tasks元素
tasks元素
指定要执⾏的任务集
[root@ansible ~]# vim /root/ansible/tasks.yml
---
- hosts: web
remote_user: root
tasks:
- name: create new file
file: name=/root/ansible/newfile state=touch
- name: create new user
user: name=zhujingzhi state=present system=yes shell=/sbin/onlogin
这⾥tasks元素⾥⾯写的就是要执⾏的任务
name 表⽰⼀个描述信息
file和user表⽰使⽤的模块名,后⾯跟着的就是使⽤模块操作的具体的使⽤⽅法(这⾥使⽤file模块在/root/ansible/创建了⼀个新的⽂件,使⽤user模块创建了⼀个zhujingzhi的⽤户)
handlers和notify元素
handlers和notify元素
notify元素,在tasks中的某段代码中定义,作为handlers的触发器(当tasks中的代码中触发到notify的元素,则会执⾏notify指定的handlers中的代码)
handlers元素属于和tasks同级的列表,其主要作⽤是定义⼀个任务(和tasks中的任务是⼀样的)等待tasks中任务触发notify后执⾏
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: copy nginx config file
copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
notify:
- restart nginx
- check service
- name: start nginx
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: check service
shell: killall -0 nginx > /tmp/nginx.log
这⾥在运⾏的时候出现了在被管理机器上没有killall的命令的错误,解决⽅法(yum -y install psmisc)
killall -0 nginx 的意思就是检查nginx的进程有没有启动返回0启动,返回⾮0服务有问题
tags元素
tags元素
tags元素为tasks⾥⾯的任务打上⼀个标签,⽅便在执⾏的时候单独执⾏tasks⾥⾯的单独的任务和被其他调⽤
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
tags: installnginx
- name: copy nginx config file
copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
notify:
- restart nginx
- check service
- name: start nginx
service: name=nginx state=started enabled=yes
tags: startnginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: check service
shell: killall -0 nginx > /tmp/nginx.log
可单独执⾏tasks⾥⾯的startnginx任务
[root@ansible ~]# ansible-playbook -t startnginx /root/ansible/nginx.yml
也可以指定两个标签执⾏
[root@ansible ~]# ansible-playbook -t installnginx,startnginx /root/ansible/nginx.yml
温馨提⽰:
这⾥多个任务也是可以使⽤⼀个标签的名字的
⽐如:
[root@ansible ~]# vim /root/ansible/nginx.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
tags: nginx
- name: copy nginx config file
copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
notify:
- restart nginx
- check service
- name: start nginx
service: name=nginx state=started enabled=yes
tags: nginx
handlers:
- name: restart nginx
service: name=nginx state=restarted
- name: check service
shell: killall -0 nginx > /tmp/nginx.log
使⽤ansible执⾏(加-t参数)
[root@ansible ~]# ansible-playbook -t nginx /root/ansible/nginx.yml
vars元素
vars元素
vars元素指的是定义变量
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
可以在什么地⽅定义变量呢?如下:
1.ansible setup facts 远程主机的所有变量都是可以被直接调⽤的
2.在/etc/ansible/hosts中定义
普通变量:主机组中主机单独定义,优先级⾼于公共变量
公共(组)变量:针对主机组中所有主机定义统⼀的变量
3.通过命令⾏指定变量,优先级最⾼
ansible-playbook -e varname=value
4.在playbook中定义
vars:
- var1: value1
- var2: value2
5.在role中定义(role是模块化的设置模式,在role中var可以定义在⼀个单独的⽂件中)
⽰例:
1.ansible setup查看变量
# 查看所有的远程主机上的可⽤变量
[root@ansible ~]# ansible all -m setup
# grep过滤查看主机名的变量
[root@ansible ~]# ansible all -m setup | grep ansible_fqdn
# setup模块的filter⽅法过滤查看主机名
[root@ansible ~]# ansible all -m setup -a "filter=ansible_hostname"
2.在/etc/ansible/hosts中定义
[root@ansible ~]# vim /etc/ansible/hosts
[testserver]
192.168.192.129 http_port=8080
在playbook中使⽤
---
- hosts: web
remote_user: root
tasks:
- name: set hostname
hostname: name=brian{{ http_port }}.python.com
详细的设置请查看:https://www.cnblogs.com/brianzhu/p/10188676.html
3.通过命令⾏指定变量,优先级最⾼
playbook的定义如下(使⽤{{}}双⼤括号定义中间是变量名):
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name={{ pkname1 }}
- name: install nginx
yum: name={{ pkname1 }}
- name: copy nginx config file
copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
- name: start nginx
service: name={{ pkname }} state=started enabled=yes
在命令⾏执⾏指定(使⽤ -e 参数指定变量变量赋值的定义格式是k=v格式)
[root@ansible ~]# ansible-playbook -e 'pkname1=nginx pkname2=vsftpd' /root/ansible/nginx.yml 4.在playbook中定义
直接是⽤vars元素定义变量列表
---
- hosts: web
remote_user: root
vars:
- pkname1: nginx
- pkname2: vsftpd
tasks:
- name: install nginx
yum: name=nginx
- name: copy nginx config file
copy: src="/etc/nginx/nginx.conf" dest="/etc/nginx/" backup=yes
- name: start nginx
service: name=nginx state=started enabled=yes
5.将使⽤的变量存放到⼀个⽂件中,在playbook⾥⾯调⽤
编辑变量⽂件
[root@ansible ~]# cat /root/ansible/vars.yml
var1: nginx
var2: nsftpd
在playbook中调⽤
---
- hosts: web
remote_user: root
vars_files:
- vars.yml
tasks:
- name: install nginx
yum: name={{ var1 }}
- name: install vsftpd
yum: name={{ var2 }}
templates元素
templates元素
主要是对配置⽂件进⾏远程主机的copy(能够实现根据不同的主机的配置修改不同的配置⽂件)
templates ⽂件也是⼀个⽂本⽂件,嵌套有脚本(使⽤模板编程语⾔编写)
模板⽂件的编程语⾔使⽤的是jinja2语⾔,⽀持下⾯的类型:
字符串: 使⽤单引号或者双引号
数字: 整数,浮点数
列表: [item1,item2,..]
元组: (item1,item2,..)
字典: {key1:value1,key2:value2,..}
布尔值: true/false
算数运算符: +,-,*,/,//,%,**
⽐较运算符: ==,!=,>,>=,<,<=
逻辑运算符: and,or,not
流表达式: for if when
⽰例:
使⽤nginx的打开的进程数为⽰例
创建模板⽬录
[root@ansible ~]# mkdir -p /root/ansible/templates
编辑模板⽂件
在ansible管理机上安装nginx,并copy nginx.conf到/root/ansible/templates中并改名为nginx.conf.j2(改名是必须的这个是模块的规定) [root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx.conf.j2
这⾥编辑nginx的模板⽂件将进程数**2
修改/root/ansible/templates/nginx.conf.j2
[root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2
将 worker_processes auto;改成 worker_processes {{ ansible_processor_vcpus**2 }};
这⾥ansible_processor_vcpus是使⽤ansible setup得到的远程主机的cpu的个数
编写playbook
[root@ansible ~]# vim /root/ansible/nginxtemp.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: copy templates file
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: start nginx
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
执⾏playbook
[root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml
查看结果
这⾥我的机器是2个CPU的,刚刚在nginx模板⽂件中设置了worker_processes {{ ansible_processor_vcpus**2 }};所有最后开启的进程是4个[root@ansible ~]# ansible all -m shell -a "ps aux |grep nginx"
192.168.192.129 | CHANGED | rc=0 >>
root 6127 0.0 0.1 125092 2256 ? Ss 17:09 0:00 nginx: master process /usr/sbin/nginx
nginx 6128 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process
nginx 6129 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process
nginx 6130 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process
nginx 6131 0.0 0.3 129348 7080 ? S 17:09 0:00 nginx: worker process
模板⽂件使⽤变量(改变nginx端⼝)
这⾥把变量定义在了/etc/ansible/hosts中为每台主机定义的(也可以使⽤上⾯提到的其他⽅式定义变量)
设置变量
[root@ansible ~]# vim /etc/ansible/hosts
[web]
192.168.192.129 http_port=8080
设置模板⽂件
[root@ansible ~]# vim /root/ansible/templates/nginx.conf.j2
修改:
listen {{ http_port }} default_server;
listen [::]:{{ http_port }} default_server;
执⾏playbook
[root@ansible ~]# ansible-playbook /root/ansible/nginxtemp.yml
查看结果
[root@ansible ~]# ansible all -m shell -a "ss -ntl | grep 8080"
192.168.192.129 | CHANGED | rc=0 >>
LISTEN 0 128 *:8080 *:*
LISTEN 0 128 :::8080 :::*
跳过错误继续执⾏
作⽤主要是为了解决在playbook中的tasks元素中某段代码执⾏出现问题是否继续往下执⾏的⼀个解决的⽅法(其默认是出错及停⽌的)
playbook⽂件
---
- hosts: web
remote_user: root
tasks: run this command and ignore the resullt
- name: shell start nginx
shell: /usr/bin/somecommand || /bin/true
或者
---
- hosts: web
remote_user: root
tasks:
- name: run this command and ignore the resullt
shell: /usr/bin/somecommand
ignore_errors: True
流程控制语句
when语句
when语句
when语句表⽰条件的测试,如果需要根据变量、facts或者此前任务的执⾏结果来做为某task执⾏与否的前提时要⽤到条件测试,通过when语句就可以实现
⽰例:
在⽣产环境中系统有6的和7的共存的情况,那么配置有些配置⽂件在不同的操作系统上是不⼀样的,这时候我们就要创建两个模板⽂件根据不同的操作系统执⾏不同的配置⽂件copy # 定义两个配置⽂件
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx6.conf.j2
[root@ansible ~]# cp /etc/nginx/nginx.conf /root/ansible/templates/nginx7.conf.j2
编写playbook
[root@ansible ~]# vim /root/ansible/nginxtemp.yml
---
- hosts: web
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: copy templates file for centos7
template: src=nginx7.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == '7'
notify: restart nginx
- name: copy templates file for centos6
template: src=nginx6.conf.j2 dest=/etc/nginx/nginx.conf
when: ansible_distribution_major_version == '6'
notify: restart nginx
- name: start nginx
service: name=nginx state=started enabled=yes
handlers:
- name: restart nginx
service: name=nginx state=restarted
with_items语句
with_items语法
with_items表⽰迭代,当需要执⾏重复性的任务的时候,就可以使⽤迭代机制来实现
对于迭代的引⽤,固定的变量名为"item"
要在tasks中使⽤with_items给定要迭代的元素列表
⽀持的列表格式:字符串、字典
⽰例:
同时执⾏创建多个⽂件的任务
编写playbook
[root@ansible ~]# vim /root/ansible/items.yml
---
- hosts: web
remote_user: root
tasks:
- name: create file
file: name=/root/ansible/{{ item }} state=touch
with_items:
- file1
- file2
- file3
- name: install packages
yum: name={{ item }}
with_items:
- htop
- sl
- hping3
迭代嵌套⼦变量
迭代嵌套⼦变量
创建多个组和⽤户将多个⽤户加⼊到不同的组中
编写playbook
[root@ansible ~]# vim /root/ansible/guser.yml
---
- hosts: web
remote_user: root
tasks:
- name: add groups
group: name={{ item }} state=present
with_items:
- g1
- g2
- g3
- name: add user for goups
user: name={{ item.name }} group={{ item.group }} state=present
with_items:
- { name: 'user1', group: 'g1'}
- { name: 'user2', group: 'g2'}
- { name: 'user3', group: 'g3'}
for语句
for语句
最后需要使⽤for语句⽣成的例⼦
server {
listen: 81
}
server {
listen: 82
}
server {
listen: 83
}
这⾥需要使⽤模板⽂件和变量来配合使⽤⽣成
palybook编写
[root@ansible ~]# vim /root/ansible/testfor.yml
---
- hosts: web
remote_user: root
vars:
ports:
- 81
- 82
- 83
tasks:
- name: create for config
template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf
模板⽂件编写
[root@ansible ~]# vim /root/ansible/testfor.conf.j2
{% for p in ports %}
server {
listen {{ p }}
}
{% enfor %}
执⾏playbook
[root@ansible ~]# ansible-playbook /root/ansible/testfor.yml
查看结果
[root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
192.168.171.129 | CHANGED | rc=0 >>
server {
listen: 81
}
server {
listen: 82
}
server {
listen: 83
}
通过模板⽂件来获取playbook⽂件中的设置好的变量并通过for语句进⾏多次循环(playbook中使⽤的变量是列表的形式),这样的⽅式使⽤起来其实是很灵活的,也可以是上⾯的列表的形式,也可以是使⽤字典的形式或者列表嵌套字典的形式⽐如:
playbook⽂件
---
- hosts: web
remote_user: root
vars:
weblist:
- web:
port: 81
name: python.brian.com
rootdir: /nginx/python
- web2:
port: 82
name: php.brian.com
rootdir: /nginx/php
tasks:
- name: create for config
template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf
模板⽂件
{% for w in weblist %}
server {
listen {{ w.port }}
servername {{ w.name }}
documentroot {{ w.rootdir }}
}
{% endfor %}
if语句
if语句
在for语句中使⽤,判断playbook中有没有设置变量,设置了⽣成,没有则不⽣成,这⾥只是举例⼦,还有其他使⽤的⽅式,⽐如⼀个变量等于⼤于⼩于多少执⾏什么任务等等
[root@ansible ~]# vim /root/ansible/testfor.yml
playbook⽂件
---
- hosts: web
remote_user: root
vars:
weblist:
- web:
port: 81
rootdir: /nginx/python
- web2:
port: 82
name: php.brian.com
rootdir: /nginx/php
tasks:
- name: create for config
template: src=/root/ansible/testfor.conf.j2 dest=/root/ansible/testfor.conf
模板⽂件
[root@ansible ~]# vim /root/ansible/testfor.conf.j2
{% for w in weblist %}
server {
listen {{ w.port }}
{% if w.name is defined %}
servername {{ w.name }}
{% endif %}
documentroot {{ w.rootdir }}
}
{% endfor %}
执⾏playbook
[root@ansible ~]# ansible-playbook /root/ansible/testfor.yml
查看结果
[root@ansible ~]# ansible all -m shell -a "cat /root/ansible/testfor.conf"
192.168.171.129 | CHANGED | rc=0 >>
server {
listen 81
documentroot /nginx/python
}
server {
listen 82
servername php.brian.com
documentroot /nginx/php
}