把一次全量改成一批一批
默认情况下,一个 play 里每个任务会在所有主机上并行推完,再进下一个任务:等于全量同时变更。给 play 加 serial 后,Ansible 会把主机分成若干批,一批走完整个任务链再换下一批,未轮到的机器保持原状。这正是滚动发布、灰度验证需要的执行顺序:先动一小部分,确认没问题再扩散。
基本信息
| 关键字 | serial,写在 play 上,作用于该 play 的全部任务 |
|---|---|
| 取值形式 | 整数(每批台数)、百分比(如 25%)、列表(逐批递增) |
| 配套项 | max_fail_percentage 控制单批失败比例上限,order 控制批次内主机顺序 |
| 执行语义 | 每批相当于完整跑一遍该 play,处理器在该批结束时触发 |
| 权限要求 | 与任务本身一致,serial 不改变提权行为 |
| 平台范围 | 任何被管对象,适用于 Linux、Windows 与网络设备清单 |
典型使用场景
- 服务滚动升级:每批重启一台或固定比例,保证集群始终有可用副本
- 灰度试点:serial 写 1,先在一台机器上验证,人工确认后再放开其余批次
- 失败影响控制:一次只让一台脱离服务,出问题也只影响这一台
- 分批下发配置:避免所有节点同一瞬间重载造成后端压力峰值
- 顺序敏感的操作:如主从切换、证书轮换,需要严格一批做完再下一批
- 与 max_fail_percentage 搭配,实现“失败超过阈值就停止扩散”
三种批次写法
三种批次写法
- hosts: web
serial: 1 # 每批一台,最保守,适合首次上线
max_fail_percentage: 0 # 任一批失败即停止,不再动后面的机器
tasks:
- name: 下发配置
ansible.builtin.template:
src: app.conf.j2
dest: /etc/app/app.conf
notify: 重启应用
- hosts: web
serial: "25%" # 按清单比例分批,机器数变化时自适应
order: shuffle # 批次内打散顺序,避免总是同几台先变更
tasks:
- name: 滚动重启
ansible.builtin.service:
name: app
state: restarted
- hosts: web
serial: [1, 5, -1] # 第一批 1 台,第二批 5 台,最后一批剩余全部
tasks:
- name: 分阶段放量
ansible.builtin.command: /usr/local/bin/upgrade.sh取值与效果
| 写法 | 含义 | 适用 |
|---|---|---|
| serial: 1 | 每批一台,完全串行 | 高风险变更、首次试点 |
| serial: 5 | 每批五台 | 容量已知、可接受小范围影响 |
| serial: "30%" | 按清单比例切分,向上取整 | 机器数量会变的动态清单 |
| serial: [1, 10, -1] | 逐批放量,最后一批为剩余全部 | 典型的灰度到全量 |
| serial: 0 或省略 | 不分批,所有主机同时推进 | 只读巡检、无中断风险的操作 |
每批都会完整跑一遍 play,因此 play 内的处理器会在该批结束时触发,而不是等所有机器都跑完。反过来说,写在 play 外的 handler 语义与批量升级的预期可能不一致,规划时先确认触发时机。
serial 只控制执行顺序,不会自动做健康检查与回滚。批次结束后如果服务实际起不来,Ansible 依然会继续下一批。要真正做到“失败了就停”,需要把检查动作(探测端口、跑 smoke 命令)写成任务并用 failed_when 判定,再配合 max_fail_percentage。
怎么定批大小
批大小来自业务能承受的容量损失:集群有多少冗余副本、单批变更后剩余容量能否扛住峰值流量。有冗余就按“同时下线不超过冗余数”的规则定批;没有冗余时批只能是 1。定了批还要配失败阈值,通常首次上线用 0(全停),成熟之后按冗余能力放宽到能接受的损失比例。