playbook介绍
在 Ansible 中,Playbook 是一个用 YAML 格式编写的文本文件,它描述了一系列任务,每个任务又是一个或多个 action 的集合。Playbook 通过在远程主机上执行任务来实现自动化。
在 playbook 中,可以指定主机、变量、任务、处理器、模块等等。通过对这些组件的组合和配置,可以实现对主机的配置、安装软件包、启动服务、文件复制等任务的自动化执行。
Playbook 的执行过程如下:
- Ansible 解析 playbook,读取其中的变量、主机和任务等信息;
- Ansible 通过 SSH 或 WinRM 连接到目标主机;
- Ansible 将 Playbook 中的任务分发给目标主机;
- 目标主机执行任务,并将执行结果返回给 Ansible;
- Ansible 汇总执行结果,并输出结果。
Playbook 可以按照需要进行分组,可以将一组任务作为一个单独的 playbook 运行,也可以将多个 playbook 组合成一个更复杂的工作流程。这使得可以在自动化过程中实现更高级别的控制和逻辑。
yaml语言
YAML("YAML Ain't Markup Language")是一种人类可读的数据序列化格式,被广泛应用于配置文件、数据交换、协议中等场景。它使用空白字符缩进来表示层级关系,使用冒号“:”分隔键值对,使用短横线“-”来表示列表。它与JSON、XML等其他数据格式相比,更加简洁、易读、易写。
下面是一些基本的语法规则:
- 在单一文件第一行,用连续三个连字号"-" 开始,还有选择性的连续三个点号( ... )用来表示文件的 结尾
- 使用缩进表示层级关系,每个层级需要缩进两个空格(也可以是其他空白字符,比如Tab键);
- 键值对使用冒号“:”来分隔,键和值之间需要有一个空格;
- 列表使用短横线“-”来表示,每个元素需要独占一行;
- 字符串需要使用单引号“'”或者双引号“"”来表示,其中双引号支持转义符,可以表示更复杂的字符串;
- 支持注释,注释使用井号“#”表示,从井号到行末的部分都是注释内容。
列表
在YAML中,可以使用“-”符号来表示列表。以下是一个简单的示例,其中列出了几个编程语言的名称:
- Python
- JavaScript
- Ruby
- Java
- C++
在这个示例中,“-”后面的文本是列表中的一个项,因此这个YAML文档表示一个包含五个元素的列表,每个元素都是一个编程语言的名称。
[python, JavaScript,Ruby,Java]
- name: Alice
age: 25
- name: Bob
age: 30
- name: Charlie
age: 35
在这个示例中,每个列表项都是一个包含两个键值对的映射,其中“name”和“age”是键,而姓名和年龄则是相应的值。
字典
在YAML中,字典可以使用冒号和缩进来表示,其中每个键值对使用冒号分隔,冒号后面跟着一个空格,值可以是任何数据类型。下面是一个简单的示例,其中包含一个名为"person"的字典,其中包含姓名、年龄和电子邮件键:
person:
name: John
age: 30
email: [email protected]
{name: "John", age: 30, email: "[email protected]"}
palybook核心组件
一个playbook 中由列表组成,其中所用到的常见组件类型如下:
- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典
- Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断一个完整的代码块功能需最少元素需包括 name 和 task,一个name只能包括一个task
hosts组件
在 Ansible 的 playbook 中,hosts 组件用于指定要在哪些主机上执行任务。可以将主机定义为一个列表,也可以使用 Ansible 动态主机发现机制自动获取主机。
以下是 hosts 组件的一些常见用法:
指定一个固定的主机列表:
- hosts:
- webserver1.example.com
- webserver2.example.com
使用模式匹配匹配主机名:
- hosts: webservers
webservers 可以是一个主机组名称,也可以是一个 Ansible 的 inventory 中定义的其他模式。
动态获取主机列表:
- hosts: "{{ groups['webservers'] }}"
这个例子会从 Ansible 的 inventory 中获取 webservers 主机组的成员列表,然后将其用于 hosts 组件。
使用 all 关键字匹配所有主机:
- hosts: all
这个例子会将任务发送到 Ansible 的所有主机上。
此外,还可以使用一些高级的主机匹配方式,比如根据主机的 IP 地址、操作系统类型、标签等来匹配主机。
remote_user 组件
remote_user 是 Ansible playbook 的一个核心组件,它用于指定远程主机的连接用户。当 Ansible playbook 与远程主机通信时,需要指定一个用户名和密码(或 SSH 私钥),以便连接到目标主机。通过指定 remote_user,可以让 Ansible playbook 自动使用指定的用户名和密码(或 SSH 私钥)来连接目标主机。
在 playbook 中,可以通过在 hosts 部分使用 ansible_user 或者 ansible_ssh_user 指定连接到远程主机的用户名。也可以在 playbook 的 vars 部分设置全局的 ansible_user 或者 ansible_ssh_user。
- name: Example playbook
hosts: example.com
remote_user: user
tasks:
- name: Run a command on the remote host
command: whoami
task列表和action组件
在 Ansible 的 playbook 中,任务(task)是一个包含一个或多个操作(action)的列表。任务定义了一个要在目标主机上执行的操作列表,其中每个操作(action)是执行的一项具体任务。任务和操作都可以使用 Ansible 模块执行特定的操作,例如安装软件包、创建文件、运行命令等等。
tasks:
- name: Install Apache web server
apt:
name: apache2
state: present
become: true
- name: Copy configuration file
copy:
src: /path/to/config/file
dest: /etc/apache2/
become: true
在这个 playbook 中,第一个任务安装了 Apache web 服务器,并使用 apt 模块来执行这个任务。第二个任务复制了一个配置文件,并使用 copy 模块来执行这个任务。在每个任务中,都包含了一个 name 和 become 组件,分别用于定义任务名称和切换到特权模式。
playbook命令
格式
ansible-playbook <filename.yml> ... [options]
常见选项
-C --check #只检测可能会发生的改变,但不真正执行操作
--list-hosts #列出运行任务的主机
--list-tags #列出tag
--list-tasks #列出task
--limit 主机列表 #只针对主机列表中的特定主机执行
-v -vv -vvv #显示过程
利用playbook创建用户
利用playbook安装httpd
利用playbook卸载httpd
Playbook中使用handlers和notify
在Ansible Playbook中,handlers是一种特殊的任务,它们只在特定情况下执行。通常,handlers与notify一起使用。notify可以触发handlers的执行,而handlers本身可以确保在某些条件下执行一次。这个机制通常用于重启服务或重新加载配置等操作。
下面是一个使用handlers和notify的例子:
---
- hosts: webserver
tasks:
- name: Install Apache web server
yum:
name: httpd
state: present
notify: Restart Apache
handlers:
- name: Restart Apache
service:
name: httpd
state: restarted
在上面的例子中,当安装Apache Web服务器时,notify: Restart Apache将发送通知来重新启动Apache服务。handlers定义了在收到通知后要执行的操作,即重启Apache服务。当接收到通知时,handlers只会运行一次,而不是每次任务运行时都运行。
Playbook中使用tags组件
在Ansible的Playbook中,可以使用tags组件来标记不同的任务,以便在运行Playbook时只运行标记了特定标签的任务。
使用tags组件的方法如下:
在需要标记的任务中添加tags属性,如下所示:
- name: Install and start Apache web server
yum:
name: httpd
state: present
tags:
- webserver
在运行Playbook时,使用--tags或--skip-tags参数来指定需要或不需要运行的标签,如下所示:
# 只运行标记了"webserver"的任务
ansible-playbook example.yml --tags "webserver"
# 不运行标记了"database"的任务
ansible-playbook example.yml --skip-tags "database"
通过使用tags组件,可以方便地控制哪些任务需要运行,哪些任务需要跳过,从而更灵活地管理Ansible Playbook的运行。
Playbook中使用变量
在Ansible的Playbook中,使用变量可以更加灵活地管理主机的配置,使其更加可维护和可扩展。以下是一些使用变量的方法:
1、在Playbook中直接定义变量,例如:
- name: Example playbook
hosts: all
vars:
http_port: 8080
db_name: mydb
db_user: dbuser
tasks:
- name: Task using variables
debug:
msg: "The database {{ db_name }} is owned by {{ db_user }} and is running on port {{ http_port }}"
在上面的示例中,定义了三个变量:http_port、db_name和db_user。在后续的任务中,可以使用这些变量。在debug任务中,使用{{ db_name }}和{{ db_user }}引用了相应的变量。
2、从外部文件中导入变量。例如,可以在Playbook中使用vars_files指令来导入一个YAML文件中的变量:
- name: Example playbook
hosts: all
vars_files:
- vars.yaml
tasks:
- name: Task using variables
debug:
msg: "The database {{ db_name }} is owned by {{ db_user }} and is running on port {{ http_port }}"
在上面的示例中,vars.yaml是一个包含变量定义的YAML文件。
3、使用group_vars和host_vars来定义主机和主机组特定的变量。例如,可以在一个名为all的主机组的group_vars目录下创建一个名为web的文件,定义该主机组的变量:
$ tree group_vars/
group_vars/
├── all
├── db
│ └── vars.yml
└── web
└── vars.yml
$ cat group_vars/web/vars.yml
http_port: 8080
在上面的示例中,web主机组定义了一个名为http_port的变量,可以在Playbook中使用该变量。
其他变量来源:
1. ansible 的 setup facts 远程主机的所有变量都可直接调用
2. 通过命令行指定变量,优先级最高
ansible-playbook -e varname=value test.yml
3、在role中定义
template 模板
模板是一个文本文件,可以做为生成文件的模版,并且模板文件中还可嵌套jinja语法
jinja2 语言使用字面量,有下面形式:
字符串:使用单引号或双引号
数字:整数,浮点数
列表:[item1, item2, ...]
元组:(item1, item2, ...)
字典:{key1:value1, key2:value2, ...}
布尔型:true/false
算术运算:+, -, *, /, //, %, **
比较操作:==, !=, >, >=, <, <=
逻辑运算:and,or,not
流表达式:For,If,When
算术运算:
Jinja 允许用计算值。支持下面的运算符
+:把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接
它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2
-:用第一个数减去第二个数。 {{ 3 - 2 }} 等于 1
/:对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 0.5
//:对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2
%:计算整数除法的余数。 {{ 11 % 7 }} 等于 4
*:用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ '=' * 80 }}
会打印 80 个等号的横条\
**:取左操作数的右操作数次幂。 {{ 2**3 }} 会返回
比较操作符
== 比较两个对象是否相等
!= 比较两个对象是否不等
> 如果左边大于右边,返回 true
>= 如果左边大于等于右边,返回 true
< 如果左边小于右边,返回 true
<= 如果左边小于等于右边,返回 true
逻辑运算符
对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式
and 如果左操作数和右操作数同为真,返回 true
or 如果左操作数和右操作数有一个为真,返回 true
not 对一个表达式取反
(expr)表达式组
true / false true 永远是 true ,而 false 始终是 false
功能
template功能:可以根据和参考模块文件,动态生成相类似的配置文件
template文件必须存放于templates目录下,且命名为 .j2 结尾
yaml/yml 文件需和templates目录平级,目录结构如下示例:
./
├── temnginx.yml
└── templates
└── nginx.conf.j2
template中使用流程控制 for 和 if
yml文件
---
- hosts: 10.0.7.207:10.0.7.206
vars:
vhost:
- listen: 80
servername: "www.baidu.com"
- listen: 82
servername: "www.ali.com"
tasks:
- name: copy conf
template: src=nginx.conf.j2 dest=/etc/httpd/conf/nginx
~
j2文件
{% for host in vhost %}
server {
listen {{ host.listen}}
servername {{ host.servername }}
}
{% endfor %}
if判断
yml文件
---
- hosts: 10.0.7.207:10.0.7.206
vars:
vhost:
- listen: 80
- listen: 82
servername: "www.ali.com"
- listen: 8000
servername: www.qq.com
tasks:
- name: copy conf
template: src=nginx.conf.j2 dest=/etc/httpd/conf/nginx
j2文件
{% for h in vhost %}
server {
{% if h.listen < 100 %}
listen {{ h.listen }}
{% endif %}
{% if h.servername is defined %}
servername {{ h.servername }}
{% endif %}
}
{% endfor %}
在j2模板文件中,可以使用标准的Python语法和Jinja2的语法进行条件判断。如果要在if语句中设置and条件,可以使用如下的语法:
{% if condition1 and condition2 %}
# do something
{% endif %}
其中,condition1和condition2可以是任意合法的条件表达式,可以是变量、比较表达式、函数调用等。在这个if语句中,只有当condition1和condition2都为真时,才会执行# do something这段代码。如果有一个条件为假,那么就不会执行这段代码。
playbook使用 when
when语句,可以实现条件测试。如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提时要用到条件测试,通过在task后添加when子句即可使用条件测试,jinja2的语法格式
---
- hosts: all
tasks:
- name: reboot
shell: reboot
when: ansible_distribution_major_version == "6"
playbook 使用迭代 with_items
迭代:当有需要重复性执行的任务时,可以使用迭代机制对迭代项的引用,固定变量名为"item"要在task中使用with_items给定要迭代的元素列表
列表元素格式:字符串、字典
删除列表中的用户
---
- hosts: all
tasks:
- name: delete user
user: name={{ item }} state=absent remove=yes
with_items:
- user1
- user2
- user3
- user4
- user5
- user6
- user7
- user8
- user9
- user20
迭代嵌套子变量:在迭代中,还可以嵌套子变量,关联多个变量在一起使用
在这个例子中,Ansible将会在目标主机上安装httpd、php和mysql这三个包。
你还可以使用with_items的简写方式:
- name: Install necessary packages
yum:
name: "{{ item }}"
state: present
vars:
packages:
- httpd
- php
- mysql
with_items: "{{ packages }}"
这个例子与前面的例子效果相同,只是使用了变量packages来代替直接列出包名。
如果你使用的是Ansible 2.5及以上版本,建议使用loop关键字来替代with_items,因为loop支持更多的选项和功能。以下是一个使用loop的示例:
- name: Install necessary packages
yum:
name: "{{ item }}"
state: present
loop:
- httpd
- php
- mysql
这个例子与前面的例子效果相同,只是使用了loop关键字来代替with_items。
- name: Example playbook with nested loop
hosts: all
vars:
users:
- name: user1
groups:
- group1
- group2
- name: user2
groups:
- group2
- group3
tasks:
- name: Create user accounts and groups
user:
name: "{{ item.name }}"
groups: "{{ item.groups }}"
with_items: "{{ users }}"
loop_control:
label: "{{ item.name }}"
管理节点过多导致的超时问题解决方法
当管理节点管理的主机数量过多时,可能会导致Ansible的执行超时问题。这可能是由于管理节点在与所有主机通信时花费了过多的时间,从而导致执行时间超过了预期。
有几种方法可以缓解这个问题:
1、调整Ansible的SSH连接超时时间。在ansible.cfg文件中,可以通过将ssh_timeout选项设置为较高的值来延长SSH连接的超时时间。例如:ssh_timeout = 60,表示将SSH连接的超时时间设置为60秒。
2、将主机划分为多个组,并将任务分配给不同的组。这样可以将任务的执行时间分散到不同的时间段,从而减轻管理节点的负载。
3、使用异步任务。异步任务允许Ansible将任务发送到主机并立即返回,而不必等待任务完成。这样可以在执行任务时节省时间,并且可以将任务分散到不同的时间段。在Playbook中,可以使用async和poll选项来配置异步任务。例如:
- name: Install packages asynchronously
package:
name: "{{ item }}"
state: present
async: 10
poll: 0
with_items:
- httpd
- php
- mysql
sync参数用于指定任务的超时时间,单位为秒,表示任务最多可以执行多长时间。poll参数用于指定在检查异步任务结果之前要等待的时间间隔,单位也是秒。在指定的时间间隔内,Ansible会每隔一段时间(由poll指定)检查一次异步任务是否完成。
async: 60表示任务最多执行60秒,而poll: 10表示每隔10秒检查一次异步任务是否完成。如果异步任务在60秒内完成,则任务正常结束;如果60秒后任务还未完成,则会被强制终止。
4、可以使用serial关键字定义Ansible一次应管理多少主机
- name: 在多台主机上安装 Nginx
hosts: all
gather_facts: no
serial: 10 或者设置百分比 10%
tasks:
- name: 安装 Nginx
yum:
name: nginx
state: latest
在这个示例中,serial 参数被设置为 10,这意味着 Ansible 每次只会对 10 台主机进行操作。当这 10 台主机操作完成后,才会开始下一轮操作,直到所有的主机操作完成。
5、调整并发数限制:可以在ansible.cfg文件中调整并发数限制。例如,在ansible.cfg文件中设置以下参数:
forks = 50
标签:name,主机,ansible,任务,Ansible,playbook,71,使用
From: https://blog.51cto.com/gavenlee/6231824