本节摘要:动手课。用一个三任务小剧本做标本,依次开到四层详细度,观察每一层日志揭示的机制;再启用计时回调测出每个任务的真实耗时;最后故意制造三种不同阶段的错误,建立"错误形态 → 所处站点"的对照直觉。本节产出的勘察手段会在第 4 章调试与第 6 章性能分析中反复使用。
准备一个足够小但覆盖三种动作的剧本:收集事实、渲染一个配置文件、重启服务并通知。目标机用上一章的两台实验机即可。
--- - name: 链路跟踪标本 hosts: web gather_facts: true tasks: - name: 渲染 nginx 工作进程数配置 ansible.builtin.template: src: nginx-workers.conf.j2 dest: /tmp/nginx-workers.conf notify: 重启模拟 - name: 打印本机核数(观察事实变量) ansible.builtin.debug: msg: "核数 {{ ansible_processor_vcpus | default(1) }}" handlers: - name: 重启模拟 ansible.builtin.debug: msg: "假装重启了服务"
配套模板只有一个变量引用:worker_processes {{ ansible_processor_vcpus | default(1) }};。整个标本的世界观很小,但每个环节都真实。
默认输出只有任务名与主机状态。加 -v 后,任务结果里的 JSON 完整展开——从此你能看到模块返回的全部字段,包括那些不打印在摘要里的细节。这是日常排障最常用的一层,代价是输出量大。
-vv 在此之上打印引擎自身的动作:加载了哪个配置文件、哪个清单、把哪些任务组成了 play。定位"配置为什么没生效"时直接跳到这一层找配置装载记录。
-vvv 加入连接层:SSH 命令的完整拼装过程、认证方式、通道建立。连通性问题的终点站在这里——多数"连不上"的谜团在这一层都有明确答案,比如实际使用的用户不是你以为的那个。
-vvvv 全开:模块代码的送达内容、远端执行命令原文、回收的原始字节。能看到引擎为每台主机生成模块包的全过程。日常几乎用不到,但看过一次终身受益——你会彻底明白"模块就是一段被送过去执行的 Python"这个架构事实。
# 四层递进的实际观察命令 ansible-playbook trace.yml -i inventory.ini # 摘要层 ansible-playbook trace.yml -i inventory.ini -v # 结果 JSON ansible-playbook trace.yml -i inventory.ini -vv # 引擎动作 ansible-playbook trace.yml -i inventory.ini -vvv # 连接细节
计时回调 profile_tasks 在 play 收尾时按累计耗时排序打印每个任务。启用后跑一次标本,输出类似:
Monday execution profile 渲染 nginx 工作进程数配置 ------------------------------- 2.41s 打印本机核数(观察事实变量) ----------------------------- 0.03s 收集事实 ------------------------------------------------- 1.87s
两个信息立刻可见。其一,收集事实本身是个不小的开销,任务越多它占比越低,但小剧本里它能占总耗时的一半——这就是第 6 章事实缓存优化的靶子。其二,模板渲染这类涉及 SSH 往返两趟(上传加执行)的任务天然比 debug 类任务慢一个量级。让数字取代猜测,是性能分析的第一原则。
现在故意弄坏三样东西,看错误在不同站点留下的不同痕迹。
破坏一:YAML 缩进写错(某行多两个空格)。进程秒退,报错指向文件与行号——这是第 2.2 节说的装载站错误,根本没走到连接。
破坏二:把清单里一台主机的地址改成不存在的 IP。运行推进到该主机时报 unreachable,其他主机不受影响,RECAP 里 unreachable 计数为 1。注意现象:错误是"按主机"隔离的,线性策略下其他主机继续完成该任务。
破坏三:模板里引用一个不存在的变量且未给默认值。渲染期的错误信息会包含"变量未定义"字样并指明主机——这类错误常被误认为目标机问题,其实是剧本自己的问题,第 7.3 节的故障实录就有一个完整案例。
三种形态对应三个不同站点,排障时先问"错误长什么样",再决定往哪个方向查,能省掉大量盲目尝试。
最后用一张图把线性与自由两种策略的差异钉死——这是观察执行节奏时最容易困惑的点。
四层日志与计时回调的价值取决于它们离你有多近,两个习惯让勘察从"救火动作"变成"日常配置"。习惯一,项目级默认详细度:项目配置里固定启用 profile_tasks 回调(2.1 节的配置示例已含),让每台开发机的每次运行都自带耗时表——性能问题在出现的当下就被看见,而不是等问题积累后专项排查。习惯二,分层提问模板:遇到异常时按固定顺序自问四题——报错在哪个站点(形态判断)、影响几台主机(范围判断)、最近什么变了(变更判断)、干跑能复现吗(环境与代码的切割)。四题的回答把大多数问题切成明确的下一跳,这个模板建议贴在团队 wiki 的排错页首。习惯的价值在于把个人技巧变成组织默认:新成员第一天起就按模板走,三个月后排查速度的团队方差会显著缩小。
给一段真实格式的勘察记录示例,示范工具的实际产出形态。某次发布预检中,干跑输出出现三台机器渲染任务失败,按四题模板记录:站点判断——渲染期报变量未定义,错误信息带主机名;范围判断——仅新加入的三台机器,存量九台正常;变更判断——这批机器是清单目录化迁移后首批新增;切割判断——干跑可稳定复现,与环境无关,是代码与数据的问题。四题答完,方向已经锁定为"新机器的变量来源断档",修复动作(补 host_vars 并加断言)在半小时内完成并合入。这段记录值得注意的不是结论,而是形态:每次勘察都留下四题的答案,问题与解法一起归档——三个月后同类问题再出现时,检索这批记录的速度远快于重新推理。勘察记录是团队排错资产的最小形态,成本一行备注,收益复利累积。