Playbook简介
playbook是ansible用于配置,部署,和管理被控节点的剧本。 通过playbook的详细描述,执行其中的一系列tasks,可以让远端主机达到预期的状态。playbook就像Ansible控制器给被控节点列出的的一系列to-do-list,而被控节点必须要完成。 也可以这么理解,playbook 字面意思,即剧本,现实中由演员按照剧本表演,在Ansible中,这次由计算机进行表演,由计算机安装,部署应用,提供对外服务,以及组织计算机处理各种各样的事情。
Playbook的使用优势
- 功能比ansible命令更强大
- 能很好的控制先后执行顺序, 以及依赖关系
- 语法展现更加的直观
- ansible命令无法持久使用, playbook 可以持久使用
剧本的书写格式要求
语法格式
ansible剧本格式:遵循yaml语法格式(类似python脚本编写格式) rsync配置文件格式:ini语法格式 sersync配置文件格式:xml语法格式(标签格式)
注意缩进
合理的信息缩进,两个空格表示一个缩进关系 一定不要使用tab
代码语言:javascript复制标题一
_ _ 标题二
_ _ _ _ 标题三
冒号
所有冒号后面都要加上空格
代码语言:javascript复制- hosts: 10.1.1.20
tasks:
yum: name=rsync state=installed
短横线 - 列表功能
使用短横线构成列表信息,短横线后面需要有空格
代码语言:javascript复制- boysec
man
- 爱好
台球
剧本书写
文件名格式
剧本文件拓展名为xxx.yaml
- 方便识别文件是一个剧本文件
- 文件编写时会有颜色提示
练习: 写一个剧本,使用yum/copy/service模块安装部署启动rsync服务
代码语言:javascript复制---
- hosts: rsync # 指定主机组或主机
remote_user: root # 远程用户
gather_facts: no # 是否先执行setup模块获取主机相关信息。
tasks: # 固定格式
- name: "01-add-user" # 指定名称
user: name=rsync create_home=no shell=/sbin/nologin uid=2021 # user模块
- name: "02-installed-rsync"
yum: name=rsync state=installed
- name: "03-copy rsync.conf"
copy: src=/playbook/rsync/rsyncd.conf dest=/etc/
- name: "04-create passwd conf"
copy: content="rsync_backup:123456" dest=/etc/rsync.passwd mode=0600
- name: "05-create rsync dir"
file: path=/backup state=directory owner=rsync group=rsync
- name: "06-started rsync service"
service: name=rsyncd state=started
- name: "07-enabled rsync service"
service: name=rsyncd enabled=yes
剧本检查模拟
代码语言:javascript复制## 检查
ansible-playbook --syntax-check rsync.yaml
## 模拟执行
ansible-playbook -C rsync.yaml
## 执行
ansible-playbook rsync.yaml
nfs服务剧本
服务端
代码语言:javascript复制- hosts: nfs_server
tasks:
- name: 01-add user
user:
name: www
shell: /sbin/nologin
create_home: no
state: present
uid: 1010
- name: 02-installed nfs server
yum: name=nfs-utils state=latest
- name: 03-copy nfs exports
copy: src=/playbook/exports dest=/etc/
- name: 04-create data dir
file: path=/nfs-data state=directory owner=www group=www
- name: 05-start rpcbind
service: name=rpcbind state=started enabled=yes
- name: 06-start nfs
service: name=nfs state=started enabled=yes
客户端
代码语言:javascript复制- hosts: nfs_client
tasks:
- name: 01-add user
user: name=www create_home=no shell=/sbin/nologin uid=1010
- name: 02-installed nfs-client
yum: name=nfs-utils state=latest
- name: 03-create mount data
file: path=/mnt/data state=directory owner=www
- name: 04-mount data
mount: path=/mnt/data src=10.1.1.60:/nfs-data fstype=nfs opts=defaults state=mounted
剧本高级特性
我们已经体验了使用剧本来安装服务,但是上述的简单ansible剧本存在一定的局限性
- 全部写成一行虽然看起来整洁,但是有一些特性没办法使用
- 比如同时需要创建多个目录,启动多个服务,需要重复写多条语句
- 参数不直观,不好修改
- 剧本里写的是启动服务,如果配置文件发生变化,重复执行不会重启服务
不过没有关系,等学习了下面的高级特性,然后我们可以换一种写法
循环(loop)
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html
使用情景:
- 需要创建多个目录
- 需要启动多个服务
具体实现: 同时创建2个目录/data和/backup
代码语言:javascript复制- hosts: 10.1.1.20
tasks:
- name: 01-create dir data and backuo
file:
path: "{{ item }}"
state: directory
owner: www
group: www
loop:
- /data
- /backup
同时创建多个用户(字典类型)
代码语言:javascript复制---
- name: create user
hosts: 10.1.1.20
tasks:
- name: create user and group
user:
name: "{{ item.name }}"
group: "{{ item.groups }}"
loop:
- {name: 'user01', groups: 'wheel'}
- {name: 'user02', groups: 'root'}
变量(vars)
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html 使用情景:
- 自定义某个名称,在任务中会多次引用
- 从主机收集的系统信息中提取某个变量并引用,例如网卡信息
具体实现:
自定义一个文件名变量,创建文件时引用:
代码语言:javascript复制- hosts: 10.1.1.20
vars:
file_name: boysec
tasks:
- name: 01-create vars dir
file:
path: "/data/{{ file_name }}"
state: directory
owner: www
group: www
使用变量获取主机的eth1地址:
代码语言:javascript复制- hosts: 10.1.1.20
tasks:
- name: 01-get ip address
shell: "echo {{ ansible_facts.eth0.ipv4.address }}" >/root/ip.txt
在主机hosts中指定变量:
代码语言:javascript复制tail -5 /etc/ansible/hosts
[backup]
10.1.1.30
[backup:vars]
file_name="boysec"
软件安装:
代码语言:javascript复制- hosts 10.1.1.20
vars:
- web_packages: nginx-1.15.2
- ftp_packages: vsftp
tasks:
- name: Installed {{ web_packages }} and {{ ftp_packages }}
yum:
name:
- "{{ web_packages }}"
- "{{ ftp_packages }}"
state: present
注册变量(register)
使用情景:将配置文件的状态注册成一个变量,方便其他任务引用 具体实现: 1.将配置文件的状态注册成一个服务变量并打印出来
代码语言:javascript复制- hosts: 10.1.1.20
tasks:
- name: 01-register nginx status
shell: netstat -lnpt|grep nginx
register: nginx_port
- name: 02-out nginx status
debug:
msg: "{{ nginx_port.stdout_lines }}"
2.打印多个信息:
代码语言:javascript复制- hosts: rsync
tasks:
- name: 01-echo hostname
shell: echo $(hostname)
register: rsync_hostname
- name: debug rsync_hostname
debug:
msg: "{{ item }}"
loop:
- "{{ rsync_hostname.stdout }}"
- "{{ rsync_hostname.cmd }}"
服务管理(service)
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html?highlight=handlers 使用情景:如果配置文件发生了变化,就重启服务,否则什么都不操作 具体实现:
代码语言:javascript复制- hosts: 10.1.1.80
tasks:
- name: 01-if nfs conf changed,then restart nfs service
copy:
src: /playbook/exports
dest: /etc/
notify: Restart_nfs
handlers:
- name: Restart_nfs
service:
name: nfs
state: restarted
标签(tags)
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_tags.html 使用情景:从我们指定的任务开始执行,而不是从头到尾执行一遍
代码语言:javascript复制- hosts: rsync
tasks:
- name: "01-add-user"
user: name=rsync create_home=no shell=/sbin/nologin uid=2021
tags: 01-add-user
- name: "02-installed-rsync"
yum: name=rsync state=installed
tags: 02-install-rsync
- name: "03-copy rsync.conf"
copy: src=/playbook/rsync/rsyncd.conf dest=/etc/
tags: 03-copy-rsync.conf
- name: "04-create passwd conf"
copy: content="rsync_backup:123456" dest=/etc/rsync.passwd mode=0600
tags: 04-create passwd conf
- name: "05-create rsync dir"
file: path=/backup state=directory owner=rsync group=rsync
tags: 05-create dir
- name: "06-started rsync service"
service: name=rsyncd state=started enabled=yes
tags: 06-start rsync
调用标签: 1.打印出playbook里要执行的所有标签
代码语言:javascript复制ansible-playbook --list-tags tags.yaml
2.指定运行某个标签
代码语言:javascript复制ansible-playbook -t "04-create passwd conf" tags.yaml
3.指定运行多个标签,使用逗号隔开
代码语言:javascript复制ansible-playbook -t "04-create passwd conf","06-start rsync" tags.yaml
4.指定不运行某个标签
代码语言:javascript复制ansible-playbook --skip-tags="04-create passwd conf" tags.yaml
5.指定不运行多个标签
代码语言:javascript复制ansible-playbook --skip-tags="04-create passwd conf","06-start rsync" tags.yaml
触发器(handlers)
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_handlers.html
handlers(触发器): 定义一些task列表,与之前剧本中task没有关系,只有资源发送变化才会采取一定的操作;
notify(告警器):notify中调用handler中定义的操作;
例如: 我们来试试,此处我们使用httpd作为示例,虽然httpd可以使用systemctl restart httpd命令重载配置,但是此处的示例中并不会使用这个命令,而是用httpd类比那些需要重启生效的应用。
假设我们想要将httpd的端口从80改成8088,并且在修改配置以后重启httpd,那么我们可以编写如下剧本。
代码语言:javascript复制---
- hosts: webserver
remote_user: root
tasks:
- name: Modif the configuration
lineinfile:
path=/etc/httpd/conf/httpd.conf
regexp="^Listen 80"
line="Linsten 8080"
backrefs=yes
backup=yes
notify:
- restart httpd
handlers:
- name: restart httpd
service:
name=httpd
state=restarted
注意:无论多少个task通知相同的handlers,handlers仅会在tasks
结束后运行一次。
条件判断(when)
官方文档:https://docs.ansible.com/ansible/latest/user_guide/playbooks_conditionals.html#basic-conditionals-with-when 通常,您希望根据事实执行或跳过任务。事实是单个主机的属性,包括 IP 地址、操作系统、文件系统的状态等等。基于事实的条件:
- 只有在操作系统是特定版本时,才能安装特定包。
- 您可以跳过在具有内部 IP 地址的主机上配置防火墙。
- 只有在文件系统已满时,才能执行清理任务。
实例: 1.只关闭关闭Debian系统
代码语言:javascript复制tasks:
- name: Shut down Debian flavored systems
ansible.builtin.command: /sbin/shutdown -t now
when: ansible_facts['os_family'] == "Debian"
2.关闭系统为CentOS系统版本为6的
代码语言:javascript复制tasks:
- name: Shut down CentOS 6 systems
ansible.builtin.command: /sbin/shutdown -t now
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "6"
回顾运行检查规范与补充
00.检查剧本拼写规范
代码语言:javascript复制ansible-playbook --syntax-check check.yaml
01.检查这个任务执行的主机对象
代码语言:javascript复制ansible-playbook --list-host check.yaml
02.检查这个剧本需要执行哪些任务
代码语言:javascript复制ansible-playbook --list-tasks check.yaml
03.检查这个剧本执行哪些tag
代码语言:javascript复制ansible-playbook --list-tags check.yaml
04.模拟执行剧本
代码语言:javascript复制ansible-playbook -C check.yaml
05.针对某台主机执行剧本
代码语言:javascript复制ansible-playbook --limit 10.1.1.60 check.yaml
template 模板
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法
jinja2语言
网站:https://jinja.palletsprojects.com/en/2.11.x/
jinja2 语言使用字面量,有下面形式:
代码语言:javascript复制字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, …]
元组:(item1, item2, …)
字典:{key1:value1, key2:value2, …}
布尔型:true/false
算术运算: , -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When
字面量:
表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。如“Hello World” 双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),如42,42.23 数值可以为整数和浮点数。如果有小数点,则为浮点数,否则为整数。在 Python 里, 42 和 42.0 是不一样的
算术运算:
Jinja 允许用计算值。支持下面的运算符
代码语言:javascript复制 :把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 1 }} 等于 2
-:用第一个数减去第二个数。 {{ 3 – 2 }} 等于 1
/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }}
//:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
*:用右边的数乘左边的操作数。 {{ 2* 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ *80 }} 会打印 80 个等号的横条
**:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8
比较操作符
代码语言:javascript复制== 比较两个对象是否相等
!= 比较两个对象是否不等
如果左边大于右边,返回 true
= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true
逻辑运算符
代码语言:javascript复制对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
and 如果左操作数和右操作数同为真,返回 true
or 如果左操作数和右操作数有一个为真,返回 true
not 对一个表达式取反
(expr)表达式组
true / false true 永远是 true ,而 false 始终是 false
template
template功能:可以根据和参考模块文件,动态生成相类似的配置文件 template文件必须存放于templates目录下,且命名为 .j2 结尾 yaml/yml 文件需和templates目录平级,目录结构如下示例:
代码语言:javascript复制./
├── temnginx.yml
└── templates
└── nginx.conf.j2
范例:利用template 同步nginx配置文件
代码语言:javascript复制#准备templates/nginx.conf.j2文件
vim temnginx.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
ansible-playbook temnginx.yml
template变更替换
范例:
代码语言:javascript复制#修改文件nginx.conf.j2
mkdir templates
vim templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus }};
vim temnginx2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install nginx
yum: name=nginx
- name: template config to remote hosts
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
- name: start service
service: name=nginx state=started enable=yes
ansible-playbook temnginx2.yml
template算术运算
范例:
代码语言:javascript复制vim nginx.conf.j2
worker_processes {{ ansible_processor_vcpus**2 }};
worker_processes {{ ansible_processor_vcpus 2 }};
template中使用流程控制for和if
for单一值范例:
代码语言:javascript复制vim nginx.conf2.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost }}
}
{% endfor %}
for键值对范例:
代码语言:javascript复制vim nginx.conf3.j2
{% for vhost in nginx_vhosts %}
server {
listen {{ vhost.listen }}
}
{% endfor %}