写第一个 playbook,并用检查模式跑一遍
目标
使用 playbook 声明服务器的期望状态,并在执行前通过检查模式确认影响范围。
为什么重要
shell 脚本描述“要做什么”,而 playbook 描述“结束时应处于什么状态”。正因如此,同一个 playbook 无论运行多少次,结果都应一致。实现这一特性的不是语法,而是模块——file 模块发现目录已经存在时不会做任何事,如果只有权限不同,也只会修正权限。相反,command/shell 不知道当前状态,因此总会报告发生了变更。所以,“有专用模块就不用 shell”并非风格偏好,而是正确性问题。最后,--check --diff 是首次接触生产服务器前的最后一道安全措施。
步骤
- 创建
/root/ans/play/site.yml。其中只有一个 play,必须有name,hosts为web,并且要通过ansible-playbook -i /root/ans/inventory/hosts.ini --syntax-check。 - 添加并执行一个
file模块 task,用于创建/root/ans/artifacts/app目录,并将权限设为0755。 - 使用
copy模块创建/root/ans/artifacts/app/app.conf。文件中必须分别有一行listen_port=8080和env=lab。其中不要把env的值硬编码,而应提取为app_env变量并将默认值设为lab(第 6 步会修改该值)。 - 至少创建 3 个 task,并为每个 task 添加
name。 - 给处理配置的 task 添加
config标签,使用--tags config执行,并将输出保存到/root/ans/out/tags.txt。 - 使用
--check --diff -e app_env=stage运行 playbook,并将输出保存到/root/ans/out/check.txt。输出的 diff 中应显示env=stage,但实际的/root/ans/artifacts/app/app.conf仍必须保持env=lab。此步骤绝对不要真正应用变更。 - 将
/opt/lab/fixtures/ansible/motd.seed复制到/root/ans/artifacts/motd,再用lineinfile修改为Welcome=labhub和Owner=platform-team。必须保留Banner=unset行,并且以Welcome=开头的行只能有一行。 - 将
/opt/lab/fixtures/ansible/broken-play.yml复制到/root/ans/play/fixed.yml,修复其中四处错误并运行。最终/root/ans/artifacts/fixed/report.txt中要包含fixed by student,同时保留 handler 定义和 notify。
参考
- 每个实验都会启动全新的实验 Pod。如果
/root/ans/inventory/hosts.ini不存在,请先重新创建与第一个实验相同的 inventory(web1·web2·db1,ansible_host=127.0.0.1、ansible_port=2222、ansible_user=root,并在[prod:children]中加入 web·db)。结构可以参考/opt/lab/fixtures/ansible/inventory.sample.ini。 ansible-playbook -i 인벤토리 플레이북.yml是基本执行形式;增加-v的数量可以查看更详细的信息。- 使用标签执行时,不在目标范围内的 task 会显示为
skipping。 - 常见错误 1:第 7 步中没有为
lineinfile设置regexp,导致同一行不断追加。 - 常见错误 2:把第 8 步的所有错误都当作 YAML 语法问题。参数名或参数值也可能有误,请查看模块文档。
创建 playbook 骨架并通过语法检查
创建 /root/ans/play/site.yml。其中只有一个 play,必须有 name,hosts 为 web,并且要通过 ansible-playbook -i /root/ans/inventory/hosts.ini --syntax-check。
playbook 顶层是列表。每个 play 都要包含 name、hosts、tasks,然后用 --syntax-check 验证。
用 file 模块创建目录
添加并执行一个 file 模块 task,用于创建 /root/ans/artifacts/app 目录,并将权限设为 0755。
不要使用 shell 命令,请使用 file 模块。检查 state 的值和 mode 的写法(引号)。
用 copy 模块部署配置文件
使用 copy 模块创建 /root/ans/artifacts/app/app.conf。文件中必须分别有一行 listen_port=8080 和 env=lab。其中不要把 env 的值硬编码,而应提取为 app_env 变量并将默认值设为 lab(第 6 步会修改该值)。
copy 模块也可以不使用 src,而通过 content 直接提供内容。多行内容使用 YAML 块标量。把环境值提取为变量,以便稍后修改。
为所有 task 添加名称
至少创建 3 个 task,并为每个 task 添加 name。
至少要有 3 个 task,不能有任何一个 task 缺少 name。
添加标签并只运行部分 task
给处理配置的 task 添加 config 标签,使用 --tags config 执行,并将输出保存到 /root/ans/out/tags.txt。
给配置相关 task 添加 tags: [config],并使用 --tags config 运行。务必至少保留一个没有标签的 task,这样才能看出执行范围确实被缩小。
一个容易误解的点:被 --tags 过滤掉的 task 不会显示为 skipping,而是完全不出现在输出中,skipped= 也仍为 0。这与被 when: 过滤的情况不同——后者已进入执行范围,只是在条件判断时被跳过,因此会留下记录。
使用检查模式预览变更
使用 --check --diff -e app_env=stage 运行 playbook,并将输出保存到 /root/ans/out/check.txt。输出的 diff 中应显示 env=stage,但实际的 /root/ans/artifacts/app/app.conf 仍必须保持 env=lab。此步骤绝对不要真正应用变更。
在 --check --diff 后通过 -e 传入不同的值。输出中应显示将要发生的变化,但实际文件必须保持不变。
只修改现有文件中的指定行
将 /opt/lab/fixtures/ansible/motd.seed 复制到 /root/ans/artifacts/motd,再用 lineinfile 修改为 Welcome=labhub 和 Owner=platform-team。必须保留 Banner=unset 行,并且以 Welcome= 开头的行只能有一行。
先把 fixture 复制到 /root/ans/artifacts/motd,再用 lineinfile 修改。必须通过 regexp 找到已有行,避免重复增加。
修复损坏的 playbook
将 /opt/lab/fixtures/ansible/broken-play.yml 复制到 /root/ans/play/fixed.yml,修复其中四处错误并运行。最终 /root/ans/artifacts/fixed/report.txt 中要包含 fixed by student,同时保留 handler 定义和 notify。
其中有两个模块参数名、一个 state 值和一个顶层键名是错误的。请查看错误信息指向哪一行。