playbook 剧本是由一个或多个“play”组成的列表
play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作
playbook 采用yaml 语言编写
YAML 语言#
YAML是一个可读性高的用来表达资料序列的格式。
语言特性:
- YAML的可读性好
- YAML和脚本语言的交互性好
- YAML使用实现语言的数据类型
- YAML有一个一致的信息模型
- YAML易于实现
- YAML可以基于流来处理
- YAML表达能力强,扩展性好
语法简介:
- 在单一文件第一行,用连续三个连字号“-” 开始,还有选择性的连续三个点号( … )用来表示文件的结尾
- 次行开始正常写Playbook的内容,一般建议写明该Playbook的功能
- 使用#号注释代码
- 缩进必须是统一的,不能空格和tab混用
- 缩进的级别也必须是一致的,同样的缩进代表同样的级别,程序判别配置的级别是通过缩进结合换行来实现的
YAML文件内容是区别大小写的,key/value的值均需大小写敏感
- 多个key/value可同行写也可换行写,同行使用,分隔
- v可是个字符串,也可是另一个列表
- 一个完整的代码块功能需最少元素需包括 name 和 task
- 一个name只能包括一个task
- YAML文件扩展名通常为yml或yaml
List 列表
列表由多个元素组成,每个元素放在不同行,且元素前均使用“-”打头,或者将所有元素用 [ ] 括起来放在同一行
1
2
3
4
5
|
# A list of fruits
- Apple
- Orange
- Strawberry
- Mango
|
Dictionary 字典
字典由多个key与value构成,key和value之间用 :分隔
1
2
3
4
|
# An employee record
name: Example Developer
job: Developer
skill: Elite
|
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
---
name: John Smith
age: 41
gender: Male
spouse:
name: Jane Smith
age: 37
gender: Female
children:
- name: Jimmy Smith
age: 17
gender: Male
- name: Jenny Smith
age: 13
gender: Female
|
核心元素和组件#
- Hosts 执行的远程主机列表
- Tasks 任务集
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
hosts 组件#
playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts用于指定要执行指定任务的主机,须事先定义在主机清单中
1
2
3
4
5
6
7
|
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集
Websrvs:&dbsrvs #与,两个组的交集
webservers:!phoenix #在websrvs组,但不在dbsrvs组
|
案例:
1
|
- hosts: websrvs:appsrvs
|
remote_user 组件#
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
1
2
3
4
5
6
7
8
9
|
- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: magedu
sudo: yes #默认sudo为root
sudo_user: wang #sudo为wang
|
task列表和action组件#
playbook的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个task后,再开始第二个task
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致。
每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出
task 两种格式:
- action:module arguments
- module:arguments 建议使用
注意:shell和command模块后面跟命令,而非key=value
范例:
1
2
3
4
5
6
7
8
|
---
- hosts: websrvs
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
|
其他组件#
某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers
任务可以通过"tags“打标签,可在ansible-playbook命令上使用-t指定进行调用
Shell VS Playbook 案例#
1
2
3
4
5
6
7
8
9
|
#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#Playbook实现
---
- hosts: websrvs
remote_user: root
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
|
1
|
ansible-playbook <filename.yml> ... [options]
|
常见选项
1
2
3
4
5
6
|
-C --check #只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的主机执行
-v -vv -vvv #显示过程
|
范例
1
2
3
|
ansible-playbook file.yml --check #只检测
ansible-playbook file.yml
ansible-playbook file.yml --limit websrvs
|
创建 mysql 用户#
范例:mysql_user.yml
1
2
3
4
5
6
7
8
|
---
- hosts: dbsrvs
remote_user: root
tasks:
- {name: create group, group: name=mysql system=yes gid=306}
- name: create user
user: name=mysql shell=/sbin/nologin system=yes group=mysql uid=306 home=/data/mysql create_home=no
|
安装 nginx#
范例:install_nginx.yml (在我的虚拟机上没运行成功)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
---
# install nginx
- hosts: websrvs
remote_user: root
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: web page
copy: src=files/index.html dest=/usr/share/nginx/html/index.html
- name: Start Nginx
service: name=nginx state=started enabled=yes
|
自己写的用编译方法安装 nginx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
---
- hosts: all
remote_user: root
tasks:
- name: add group nginx
group: name=nginx state=present
- name: add user nginx
user: name=nginx state=present group=nginx
- name: 创建目标目录
file:
path: /root/nginx-1.26.1
state: directory
- name: 解压缩 nginx 到原地
unarchive:
src: /root/nginx-1.26.1.tar.gz
dest: /root/
copy: yes
when: not ansible_check_mode
- name: Install required dependencies
yum:
name:
- pcre-devel
- openssl-devel
- zlib-devel
- gcc-c++
state: present
- name: Configure Nginx
command: "./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module --with-http_ssl_module"
args:
chdir: /root/nginx-1.26.1
when: not ansible_check_mode
- name: Compile Nginx
command: make
args:
chdir: /root/nginx-1.26.1
- name: Install Nginx
shell:
cmd: make install
chdir: /root/nginx-1.26.1
when: not ansible_check_mode
- name: 创建一个软链接
file:
src: /usr/local/nginx/sbin/nginx
dest: /usr/local/bin/nginx
state: link
when: not ansible_check_mode
- name: Start Nginx
command: nginx
|
安装和卸载 httpd#
范例:install_httpd.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
---
#install httpd
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
- name: web html
copy: src=files/index.html dest=/var/www/html/
- name: start service
service: name=httpd state=started enabled=yes
ansible-playbook install_httpd.yml --limit 10.0.0.8
|
范例:remove_httpd.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#remove_httpd.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: remove httpd package
yum: name=httpd 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=/var/www/html/index.html state=absent
|
handlers 和 notify#
handlers 本质是 task list,类似 MySQL 中的触发器的行为,其中的 task 与前述的 task 并没有本质的不同,主要用于当关注的资源发生变化时,才会采取一定的操作,而 notify 对应的 action 可用于在每个 play 的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,仅在所有的变化发生完成后一次性地执行指定操作。在 notify 中列出的操作成为 handler,也即 notify 中调用 handler 中定义的操作。
handlers 使用#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
notify: restart httpd
- name: ensure apache is running
service: name=httpd state=started enabled=yes
handlers:
- name: restart httpd
service: name=httpd state=restarted
|
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
- hosts: websrvs
remote_user: root
tasks:
- name: add group nginx
tags: user
user: 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
copy: src=/root/config.txt dest=/etc/nginx/nginx.conf
notify:
- Restart Nginx
- Check Nginx Process
handlers:
- name: Restart Nginx
service: name=nginx state=restarted enabled=yes
- name: Check Nginx process
shell: killall -0 nginx > /tmp/nginx.log
|
tags: 可以指定某一个任务添加一个标签,添加标签以后,想执行某个动作可以做出挑选来执行
多个动作可以使用同一个标签
示例:httpd.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
|
- hosts: websrvs
remote_user: root
tasks:
- name: Install httpd
yum: name=httpd state=present
tage: install
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: conf
- name: start httpd service
tags: service
service: name=httpd state=started enabled=yes
|
ansible-playbook –t install,conf httpd.yml // 指定执行install,conf 两个标签
示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
- hosts: testsrv
remote_user: root
tags: inshttpd // 针对整个playbook添加tage
tasks:
- name: Install httpd
yum: name=httpd state=present
- name: Install configure file
copy: src=files/httpd.conf dest=/etc/httpd/conf/
tags: rshttpd
notify: restart httpd
handlers:
- name: restart httpd
service: name=httpd status=restarted
|
ansible-playbook –t rshttpd httpd2.yml
变量名:仅能由字母、数字和下划线组成,且只能以字母开头
变量定义#
范例:
变量调用方式#
通过{{ variable_name }} 调用变量,且变量名前后建议加空格,有时用“{{ variable_name }}”才生效
变量来源#
1.ansible 的 setup facts 远程主机的所有变量都可直接调用
2.通过命令行指定变量,优先级最高
1
|
ansible-playbook -e varname=value
|
3.在playbook文件中定义
1
2
3
|
vars:
- var1: value1
- var2: value2
|
4.在独立的变量YAML文件中定义
1
2
3
|
- hosts: all
vars_files:
- vars.yml
|
5.在 /etc/ansible/hosts 中定义
主机(普通)变量:主机组中主机单独定义,优先级高于公共变量
组(公共)变量:针对主机组中所有主机定义统一变量
6.在role中定义
使用 setup 模块中变量#
本模块自动在playbook调用,不要用ansible命令调用
案例:使用setup变量
1
2
3
4
5
6
7
8
9
10
11
|
---
#var.yml
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: create log file
file: name=/data/{{ ansible_nodename }}.log state=touch owner=wang mode=600
ansible-playbook var.yml
|
在playbook 命令行中定义变量#
范例:
1
2
3
4
5
6
7
8
9
|
vim var2.yml
---
- hosts: websrvs
remote_user: root
tasks:
- name: install package
yum: name={{ pkname }} state=present
ansible-playbook –e pkname=httpd var2.yml
|
在playbook文件中定义变量#
范例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
vim var3.yml
---
- hosts: websrvs
remote_user: root
vars:
- username: user1
- groupname: group1
tasks:
- name: create group
group: name={{ groupname }} state=present
- name: create user
user: name={{ username }} group={{ groupname }} state=present
ansible-playbook -e "username=user2 groupname=group2” var3.yml
|
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法
jinja2 语言使用字面量,有下面形式:
1
2
3
4
5
6
7
8
9
10
|
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[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 允许用计算值。支持下面的运算符
1
2
3
4
5
6
7
|
+:加法或字符串连接。 {{ 1 + 1 }} 等于 2
-:用第一个数减去第二个数。 {{ 3 – 2 }} 等于 1
/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }}
//:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
*:乘 {{ 2 * 2 }} 返回4, {{ ‘=’ * 80 }} 会打印 80 个等号
*:次幂。 {{ 2**3 }} 会返回 8
|
emplate#
xxx
role#