分发文件要选对工具
Ansible 分发文件有几种粒度不同的手段:单个小文件用文件复制,需要按变量渲染用模板,成百上千个文件的目录用打包或同步工具,需要从目标机取回用抓取。选错的代价很直接:用文件复制去推一个大目录,会变成几百次远程调用,几分钟的任务拖成几十分钟;用同步工具去管单个配置,则引入不必要的依赖与删除风险。
基本信息
| 单文件 | 文件复制与模板模块,按内容校验判断是否需要更新 |
|---|---|
| 整目录 | 同步类模块(基于 rsync,需两端都有相关工具)或打包后解压 |
| 取回文件 | 抓取类模块把目标机文件拉回控制节点或指定主机 |
| 属性控制 | 属主、属组、权限、目录默认权限、备份开关 |
| 安全写入 | 可先做语法校验再落盘,校验失败则回滚不覆盖 |
| 幂等基础 | 按内容或校验值比对,而不是按时间戳 |
典型使用场景
- 配置文件下发:模板渲染后落地,并通过校验命令确认语法正确
- 证书与密钥分发:设置严格权限并避免内容出现在日志中
- 发布包部署:把构建产物打包推送后解压到版本目录
- 大量小文件发布(前端静态资源):用同步或打包而非逐文件复制
- 从目标机回收文件:日志、检查结果、备份文件拉回归档
- 配置片段管理:对已存在的文件做定点插入或删除某一段
写法与校验
写法与校验
- name: 下发并校验配置文件(校验失败不落盘)
ansible.builtin.template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.conf
owner: root
group: root
mode: "0644"
backup: true
validate: /usr/sbin/nginx -t -c %s # 先用临时文件校验再替换
notify: 重载 nginx
- name: 整目录同步(大量文件时更高效)
ansible.posix.synchronize:
src: dist/
dest: /var/www/app/
delete: false # 谨慎开启:会删除目标端多余文件
rsync_opts:
- "--exclude=.git"
- "--compress"
- name: 用打包方式分发(避免逐文件调用)
ansible.builtin.unarchive:
src: app-{{ app_version }}.tar.gz
dest: /opt/app
remote_src: true
owner: appsvc
group: appsvc
mode: "0750"
- name: 从目标机取回结果文件
ansible.builtin.fetch:
src: /var/log/app/report.json
dest: /var/log/collected/{{ inventory_hostname }}/
flat: false手段与取舍
| 手段 | 适用 | 代价与风险 |
|---|---|---|
| 文件复制 | 少量、内容固定的文件 | 逐文件一次远程调用,目录大时很慢 |
| 模板渲染 | 内容随变量变化的配置 | 渲染结果与模板复杂度正相关 |
| 同步类模块 | 成百上千个文件的目录 | 需要两端具备 rsync;开启删除会真的删文件 |
| 打包解压 | 带目录结构的发布包 | 需要额外的打包与校验步骤 |
| 抓取 | 把目标机文件拉回 | 大量小文件逐次拉取同样很慢 |
| 定点编辑 | 在已有文件里增删一段 | 正则写错会反复追加或删错位置 |
校验后再落盘是配置文件分发里性价比最高的做法:模板先写到临时位置,用目标程序自带的语法检查命令验证,通过才替换正式文件,配置写错时不会把服务弄成无法启动。多数配置类模块都支持校验命令参数。
同步类模块的删除选项会真的移除目标端多余文件,目标路径写错时等于清空一个目录。开启前先确认路径变量与实际目标,并保留备份或先预演;分发证书、密钥类文件还应配合权限收紧与日志抑制。
内容比对怎么才可靠
幂等判定依赖内容比对而非时间戳:文件被手工改动过但时间戳更旧的情况很常见,按时间戳判断会漏掉更新。文件类模块默认按内容校验,能正确反映是否需要变更;这也是“连跑两次第二次无变更”的基础。