Ansible剧本 --- playbook的yaml文件编写¶
一. playbook基础¶
1. 基础知识¶
我们在执行大量ansible时候,如果在终端中一个一个敲就太麻烦了。这时候可以通过某种特殊方式将各种命令组合到一起,形成一个"剧本"文件。通过执行该文件就能匹配执行所有ansible命令。
2. 关键点¶
- playbook是由一个一个任务组合而成的
- playbook中的指令是基于ansible命令演变来的
- playbook的专用执行命令时ansible-playbook
3. 样式示例¶
- hosts: 10.0.0.13
remote_user: root
tasks:
- name: Hello World
command: echo "Hello World"
tags:
- hello world
- name: extra vars
debug: msg-{{ extra_vars }}
4. 功能解析¶
对于ansible的局部playbook文件来说,主要有四部分组成
| 组成部分 | 功能描述 | 常见属性 | 备注 |
|---|---|---|---|
| Target section | 执行playbook的目标主机 | hosts、remote_user、order | 必备内容 |
| Variable section | 执行playbook所需的变量 | vars | 可选内容 |
| Task section | playbook中的功能任务 | task(name、模块名称) | 必备内容 |
| Handler section | 各任务之间的关联关系 | handler(name、模块名称) | 可选内容 |
注意:
- 可选内容的意思是说,可以使用ansible的默认的,我们不一定需要自己自定义
- task部分的作用就是各自ansible模块的使用
- playbook文件内容格式是yaml文件
二. 核心功能¶
1. playbook的常见组件¶
一个playbook中由多个组件组成,其中所用到的常见组件类型如下
Hosts: 执行的远程主机列表
Tasks: 任务集,由多个tasks的元素组成的列表实现,每个tasks是一个字典。
Variables: 内置变量或者自定义变量在playbook中调用。
Templates: 模板,可以换模板文件中的变量并实现一些简单的逻辑文件。
Handlers: 和notify结合使用,由特定条件触发操作,满足条件方可执行。否则不执行。
tags: 标签,指定某条任务执行。用于选择playbook中的部分代码。ansible具有幂等性,因此会自动跳过没有变化的部分。即便如此有些代码为测试其确实没有发生变化的实践依然会非常长。因此如果确信其没有变化,就可以通过tags跳过此些代码的片段。
一个完整代码块功能最少元素需要包括name和task,一个name只能包括一个task。
2. hosts属性¶
1) 简介¶
playbook的作用就是自动化批量执行各种ansible命令来实现特定功能。而这些ansible指令最终都是要到某个或某些主机上执行。所以playbook文件中必须要制定某些特定的ansible指令操作地方 --- 也就是目标主机
playbook中专门指定目标主机的属性叫hosts,而这个里面定义的目标主机必须在ansible主机列表或清单文件中。
2) 属性样式¶
由于hosts的配置目的与ansible主机列表文件目的一致,所以他们的编写方法也一样,主要有这么几种表示样式
单个主机:
- hosts: 192.168.100.100
- hosts: master.ansible.com
多个主机:
- hosts: 192.168.100.*
- hosts: *.ansible.com
特定主机:
- hosts: web:mysql
- hosts: web:&mysql
- hosts: web:!mysql
注意:
如果主机数量过多的话,我们可以通过serial属性来限制一次性多少台主机执行任务,从而减轻所有任务执行时候的并行压力
- serial:"20%" # 每次只同时处理20%的主机
- serial:"2" # 每次只同时处理2台主机
3. remote_user属性¶
1) 简介¶
因为ansible是基于ssh协议与明白通信的,所以ansible肯定以某个指定用户身份到目标主机上执行任务。所以playbook在执行各种ansible指令是,肯定有一个属性是来指定这些ansible指定以什么样的身份到目标主机执行,这个属性就是remote_user
用户身份虽然简单,但它不仅仅涉及到了登录用户,也涉及到了用户在执行命令时候的权限控制,即sudo的方式
remote_user的作用就类似于ansible命令中"-u 登录用户" + "-k 登录密码" + "-K 提权密码"
2) 属性样式¶
由于playbook是由大量功能任务组成的,而这些功能任务有可能在不同的目标主机上以不同用户来运行。所以在playbook中remote_user基于使用范围和目的的不同,有两种表现形式
默认登录用户:
默认登录用户也称全局登录用户,用于所有task任务的默认执行用户
表现形式是:
- hosts: web
remote_user: root
或者:
- hosts: mysql
remote_user: othername
特殊登录用户:
特殊登录用户是针对task人物列表中某个具体任务来说的,我们需要在task任务中采取如下形式切换用户,实现特定效果
表现形式:
- hosts: web
remote_user: root # 默认连接用户
tasks:
- name: 以普通用户连接,再提权到其他用户
ping: # 没错,可以不写值
remote_user: putong # 用 putong 连接 SSH
become: yes # 开启提权(替代 sudo: yes)
become_user: othername # 提权到 othername(替代 sudo_user)
注意:
- 在具体的task中想要使用become_user必须要先开启提权功能,即要有
become: yes,如果只有become: yes而没有become_user,则会以root用户身份执行任务 - 子任务在切换任务时,要和全局默认的登录用户识别清楚。
4. tasks属性¶
1) 简介¶
playbook文件的主要作用就是实现各种各样的功能。每一个功能都是由大量的ansible指令来组成的。所以对于playbook来说每一个特定的ansible动作都是一个子功能任务。所以playbook的功能主题就是大量的task列表。而且这些任务在执行的时候有一个非常重要的功能特性:幂等性。简单来说就是执行多次任务和执行一次任务的效果是相同的。
playbook在执行的时候,根据task列表的顺序,诸葛在hosts目标主机上执行。默认情况下任何一个任务中途发生错误整个任务都会自动中断。所以默认的task在执行时有一个隐患:在某些条件长江下的逻辑感不强。
我们有相应的属性来解决这种隐患:notify+handler
每一个具体的task主要有两部分组成
- task名称: 通过name属性来设定该任务中的子命令名称,建议详细一些
- task动作: ansible命令实现特定功能的模块及其使用方法
2) 属性样式¶
task名称,我们使用name属性表示就可以了,格式如下:
- hosts: web
remote_user: root
tasks:
- name: test connection
注意:
name的内容尽量详细一点,但是不需要过于详细,能看明白就可以了
task动作,主要涉及到了ansible的模块及可执行命令两部分内容,它一般有两种格式:
1) action: 模块 具体动作
2) 模块: 具体动作
注意:
方法2一目了然,所以我们推荐使用方法2
"具体动作"会根据模块的不同,编写的样式也不一样
对于其他模块来说,具体动作就是"key=value"样式
3. tasks示例¶
1) 查看hosts主机的文件示例¶
查看host主机文件示例
03-playbook-action.yml 文件内容如下:
- hosts: web
remote_user: root
tasks:
- name: test connection
ping:
- name: hostname
shell: hostname
2) 文件执行¶
# 测试
ansible-playbook /etc/ansible/my-playbook.yaml --syntax-check
# 模拟执行
ansible-playbook /etc/ansible/my-playbook.yaml --check --diff
# 逐步执行
ansible-playbook /etc/ansible/my-playbook.yaml --step
# 执行
ansible-playbook /etc/ansible/my-playbook.yaml -v # -v的作用时显示信息多一点
在一个任务中,如果存在多个action动作,只有最后一个action动作生效
检查效果
[root@my-project playbook]# ansible-playbook abc.yaml -v
Using /etc/ansible/ansible.cfg as config file
[WARNING]: While constructing a mapping from /root/playbook/abc.yaml, line 5, column 5, found a duplicate dict key (shell). Using last defined value only.
PLAY [3] ************************************************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************************************
ok: [3]
TASK [hostname] *****************************************************************************************************************************************************************************************
changed: [3] => {"changed": true, "cmd": "ls -a", "delta": "0:00:00.004367", "end": "2026-08-21 11:12:37.040147", "msg": "", "rc": 0, "start": "2026-08-21 11:12:37.035780", "stderr": "", "stderr_lines": [], "stdout": ".\n..\nanaconda-ks.cfg\n.ansible\n.bash_history\n.bash_logout\n.bash_profile\n.bashrc\n.cache\n.copilot\n.cshrc\n.dotnet\n.lesshst\n.ssh\n.tcshrc\n.vscode-server", "stdout_lines": [".", "..", "anaconda-ks.cfg", ".ansible", ".bash_history", ".bash_logout", ".bash_profile", ".bashrc", ".cache", ".copilot", ".cshrc", ".dotnet", ".lesshst", ".ssh", ".tcshrc", ".vscode-server"]}
PLAY RECAP **********************************************************************************************************************************************************************************************
3 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
结果显示:
- 我们要看详情应该结合-v或者-vv更详细的信息来辨别
- 一个任务中只能有一个action动作执行成功,默认是最后一条
三. 简单实践¶
# 使用playbook给web_servers部署zabbix_agent
- name: 部署zabbix-agent
hosts: "2"
become: yes
gather_facts: yes
# 修改阿里云yum源
# mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup
# mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm
# sed -i 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.aliyun.com|' /etc/yum.repos.d/epel*
# sed -i 's|^metalink|#metalink|' /etc/yum.repos.d/epel*
tasks:
- name: 挂载光盘
mount:
src: /dev/sr0
path: /media/cdrom
state: mounted
fstype: iso9660
- name: 备份原epel
shell: mv /etc/yum.repos.d/epel.repo /etc/yum.repos.d/epel.repo.backup ; mv /etc/yum.repos.d/epel-testing.repo /etc/yum.repos.d/epel-testing.repo.backup
ignore_errors: yes
- name: 更新阿里云epel
yum:
name: https://mirrors.aliyun.com/epel/epel-release-latest-9.noarch.rpm
state: present
disable_gpg_check: yes
- name: 修改yum源文件
shell: sed -i -e 's|^#baseurl=https://download.example/pub|baseurl=https://mirrors.aliyun.com|' -e 's|^metalink|#metalink|' /etc/yum.repos.d/epel*
# 安装依赖
# yum -y install pcre pcre-devel net-snmp net-snmp-devel curl-devel libssh2-devel libevent libevent-devel curl curl-devel perl-DBI gcc make
- name: 安装依赖工具
yum:
name:
- pcre
- pcre-devel
- net-snmp
- net-snmp-devel
- libssh2-devel
- libevent-devel
- libevent
- curl
- curl-devel
- perl-DBI
- gcc
- make
state: present
#groupadd zabbix
#useradd -M -s /sbin/nologin -g zabbix zabbix
- name: 创建组
group:
name: zabbix
system: yes
- name: 创建用户
user:
name: zabbix
system: yes
group: zabbix
shell: /sbin/nologin
state: present
create_home: yes
# 下载
# wget -O zabbix-7.0.29.tar.gz https://cdn.zabbix.com/zabbix/sources/stable/7.0/zabbix-7.0.29.tar.gz
# wget https://cdn.zabbix.com/zabbix/sources/stable/7.0/zabbix-7.0.29.tar.gz.sha256
# 3. 校验:-c 读取 sha256 文件里的值,和同名文件比对,输出 OK 即通过
# printf '%s %s\n' "$(cat zabbix-7.0.29.tar.gz.sha256)" "zabbix-7.0.29.tar.gz" | sha256sum -c -
- name: 下载源码包
get_url:
url: https://cdn.zabbix.com/zabbix/sources/stable/7.0/zabbix-7.0.29.tar.gz
dest: /root/zabbix-7.0.29.tar.gz
checksum: "sha256:https://cdn.zabbix.com/zabbix/sources/stable/7.0/zabbix-7.0.29.tar.gz.sha256"
force: no
timeout: 60
# 解压编译安装
# tar xf zabbix-7.0.29.tar.gz
# 2. 配置
# cd zabbix-7.0.29
# ./configure --prefix=/usr/local/zabbix --enable-agent
# 3. 编译安装
# make && make install
- name: 解压
unarchive:
remote_src: yes
src: /root/zabbix-7.0.29.tar.gz
dest: /usr/local
- name: 配置编译参数
shell: ./configure --prefix=/usr/local/zabbix --enable-agent
args:
chdir: /root
- name: 编译安装
make:
chdir: /root/zabbix-7.0.29
target: install
# ln -s /usr/local/zabbix/bin/* /usr/local/bin/;ln -s /usr/local/zabbix/sbin/* /usr/local/sbin/
# - name: 创建软链接
# shell: ln -s /usr/local/zabbix/bin/* /usr/local/bin/ && ln -s /usr/local/zabbix/sbin/* /usr/local/sbin/
- name: 创建软链接
file:
src: /usr/local/zabbix/bin/zabbix_get
dest: /usr/local/bin/zabbix_get
state: link
file:
src: /usr/local/zabbix/bin/zabbix_sender
dest: /usr/local/bin/zabbix_sender
state: link
# mkdir -p /usr/local/zabbix/etc/zabbix_agentd.conf.d
# mkdir /usr/local/zabbix/logs
# chown -R zabbix:zabbix /usr/local/zabbix/logs
- name: 创建数据存放目录并授权1
file:
path: /usr/local/zabbix/etc/zabbix_agentd.conf.d
owner: zabbix
group: zabbix
state: directory
- name: 创建数据存放目录并授权2
file:
path: /usr/local/zabbix/logs
owner: zabbix
group: zabbix
state: directory
# 修改配置文件
- name: 复制zabbix配置文件
copy:
dest: /usr/local/zabbix/etc/zabbix_agentd.conf
src: /root/zabbix_agentd.conf
backup: yes
owner: zabbix
group: zabbix
# 写启动脚本
- name: 写启动脚本
copy:
dest: /lib/systemd/system/zabbix-agent.service
src: /root/zabbix-agent.service
backup: yes
# 重新加载
- name: 重新加载
shell: systemctl daemon-reload
# 启动服务
- name: 启动服务并设置开机自启动
service:
name: zabbix-agent.service
state: started
enabled: yes