两种范式的差别
命令式(imperative)自动化写的是步骤:先停服务、再复制文件、然后重启,执行者需要自己保证步骤顺序与重复执行的安全性。声明式(declarative)自动化写的是结果:这些文件应存在、这个包的版本应为某值、这个服务应处于运行状态,工具读取现状、计算差异并执行必要的动作。前者贴近人的操作习惯、上手快;后者把幂等性交给工具,代价是需要理解工具的语义与限制。
基本信息
| 命令式代表 | Shell 脚本、命令行工具、一次性执行的任务 |
|---|---|
| 声明式代表 | 配置管理模块、容器编排清单、基础设施即代码 |
| 核心差异 | 描述步骤还是描述结果 |
| 选择依据 | 是否需要重复执行、是否需要差异可预览 |
取舍的判断点
- 需要重复执行的日常变更:优先声明式,由工具负责收敛与报告变更。
- 一次性的应急处置:命令式更快,但要事后补回声明式资产,避免留下未纳管的状态。
- 复杂条件分支:工具的声明式语法表达吃力时,用命令模块并显式写出判断条件。
- 需要执行前预览:声明式工具的干跑或计划模式能先看差异,命令式只能靠自建校验。
- 跨平台差异较大:命令式更容易按平台分别处理,但要把差异集中在少数任务里。
同一件事的两种写法
同一件事的两种写法
# 声明式:描述目标状态,工具负责判断与执行
- name: 确保 nginx 已安装且处于运行状态
ansible.builtin.package:
name: nginx
state: present # 只声明结果,不写安装步骤
# 命令式:描述步骤,需要自己保证可重复
- name: 用命令安装 nginx
ansible.builtin.shell: |
if ! rpm -q nginx >/dev/null 2>&1; then # 自行判断避免重复安装
yum install -y nginx
fi两种范式对比
| 对比项 | 命令式 | 声明式 |
|---|---|---|
| 描述对象 | 执行步骤 | 目标状态 |
| 默认幂等 | 否,需自行保证 | 是,由工具保证 |
| 执行前预览 | 通常不支持 | 多数支持干跑或计划 |
| 学习成本 | 低,会写脚本即可 | 需理解工具语义与模块 |
| 变更可读性 | 依赖注释与日志 | 任务名称即意图 |
| 适用场景 | 应急、一次性、复杂分支 | 常态化、批量、需要重复执行 |
两种范式混用是常态,关键是边界清楚:声明式任务不要偷偷塞入不可重复的命令,命令式任务必须显式写明判断条件与失败后的处理,并在文档里标注它不是收敛型任务。
声明式不等于免维护:工具只保证按你写的期望状态收敛,期望状态本身写错时它同样会稳定地把系统带偏。变更前用干跑查看差异是成本最低的防线。