首页/系统与基础设施/自动化运维速查/剧本的分层设计与职责划分
Ansible 核心70 条

剧本的分层设计与职责划分

自动化仓库按清单、变量、角色、剧本分层:各自回答“操作谁、差异是什么、这类主机怎么配、按什么顺序组合”。每类内容只在一层定义一次,改动只影响一层;角色对外只暴露变量接口,剧本保持环境无关。

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‌​‌‌‌‌​​‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌​‌​‌‌​​‌​‌‌​‌​‌‌​‌‌​​​‌‌​​​​‌​‌‌‌‌​​‌​‌‌​​‌​‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌‌​​‌‌​‌‌​‌​​‌​‌‌​​‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​‌‌‌​​‌‌​‌‌​‌​​‌​‌‌​​​‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​​‌​‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​

分层是为了能改

一份能长期维护的自动化仓库,通常分成几层:清单回答“操作谁”,变量回答“各地差异是什么”,角色回答“这类主机该怎么配”,剧本回答“按什么顺序把哪些角色用到哪些分组上”。分层的价值不在整齐,而在于改动被限制在一层里:换参数不动逻辑,逻辑升级不影响参数,新增一类主机只需组合已有角色。

基本信息

清单层主机与分组,以及连接方式;不含业务参数
变量层分组变量、主机变量、秘密文件;不含流程逻辑
角色层可复用的配置能力,参数从外部传入,自带默认值
剧本层编排:哪些分组、按什么顺序、用哪些角色,尽量少写具体步骤
实现层角色内部的任务文件、模板、处理器,对外只暴露变量接口
判断标准每项内容只在一个地方定义,改动只影响一层

典型使用场景

  • 多环境多角色:剧本保持环境无关,环境差异留在清单与变量层
  • 能力复用:把“装好并加固某中间件”固化成角色,多个项目直接引用
  • 职责划分:平台团队维护角色,业务团队只写编排与参数
  • 变更影响评估:知道要改的是哪一层,就能预估影响范围
  • 新人上手:从剧本读流程、从角色读实现,路径清晰不跳层
  • 逐步重构:把散落在剧本里的实现细节逐步下沉到角色

层与层的调用关系

层与层的调用关系
- name: 剧本层只做编排
  hosts: web
  roles:
    - role: common            # 基线:用户、时区、基础包
      tags: [common]
    - role: nginx             # 能力:装好并配置
      vars:
        nginx_worker_processes: "{{ web_worker_processes }}"   # 参数来自变量层
      tags: [nginx]

# 角色内部:tasks 是步骤,templates 是内容,defaults 是对外参数
# roles/nginx/defaults/main.yml     对外可见、可覆盖的默认参数
# roles/nginx/vars/main.yml         角色内部使用、通常不对外开放的取值
# roles/nginx/tasks/main.yml        步骤;按需要拆成 install.yml、config.yml
# roles/nginx/handlers/main.yml     变化后要做的动作
# roles/nginx/templates/*.j2        配置文件模板

# 变量层:只放取值,不放逻辑
# group_vars/web/vars.yml
#   web_worker_processes: 4

内容该放哪一层

内容所属层放错的表现
主机与分组清单层把主机名写进剧本,换环境必须改剧本
环境参数与阈值变量层参数写死在角色里,其它环境只能复制角色
某个软件的完整配置能力角色层剧本里堆几十个任务,无法被别的项目复用
跨角色的执行顺序剧本层顺序写进角色内部,角色变得只能用于特定场景
配置文件内容角色内的模板用多个行编辑任务拼配置,内容难以整体评审
变化后的动作角色内的处理器把重启动作写进任务,每次执行都可能触发无谓重启
角色对外只应暴露变量接口:调用者通过变量控制行为,而不需要关心角色内部任务怎么拆。若某个角色必须靠调用者了解内部细节才能正确使用,说明接口没设计好,或者它本就不该被拆成角色。
同一份取值出现在多层时,最终生效的是优先级更高的那一层,而阅读者往往只看其中一层:这会制造“我明明改了却没生效”的典型问题。任何变量只定义一次,是分层设计里最该守住的纪律。

重构路径

面对一个大剧本,先按“谁、差异、能力、编排”把内容分类,再把能力部分整段搬进角色并把取值改成变量,最后让剧本只留角色调用与顺序。每次只搬一类,搬完做一次幂等验证,避免一次性重构后无法定位问题出在哪个环节。

易错点

  • 剧本里直接写实现细节(几十个任务加行编辑),无法复用也难以评审
  • 角色里写死环境取值,同一种软件在第二个环境就必须复制一份角色
  • 同一个变量在清单、分组变量、角色默认值里各定义一次,改了不生效
  • 执行顺序需求被塞进角色内部,角色只能服务于某一个场景
  • 所有内容挤在一个目录,改动前无法判断会影响哪些主机与哪些环境

数据来源与参考

  • Ansible 官方文档 Roles 与可复用内容组织
  • Ansible 官方文档 Sample Ansible setup(分层建议)
  • Ansible 官方文档 Variable precedence: where should I put a variable

整理校对:其其网ICT文档中心 · 本页地址:docs.qiqicto.com/automation/playbook-layered-design-responsibilities.html

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌​​‌​‌‌‌‌​‌‌​​​​‌​‌‌‌​‌​‌​‌‌‌​‌​​​‌‌​‌‌‌‌​‌‌​‌‌​‌​‌‌​​​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​‌‌‌‌​‌‌​‌‌‌​​​‌​‌‌‌‌​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‌​‌‌‌‌​​‌​‌‌​​​‌​​‌‌​‌‌‌‌​‌‌​‌‌‌‌​‌‌​‌​‌‌​​‌​‌‌​‌​‌‌​‌‌​​​‌‌​​​​‌​‌‌‌‌​​‌​‌‌​​‌​‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌​​‌​​​​‌​‌‌​‌​‌‌​​‌​​​‌‌​​‌​‌​‌‌‌​​‌‌​‌‌​‌​​‌​‌‌​​‌‌‌​‌‌​‌‌‌​​​‌​‌‌​‌​‌‌‌​​‌​​‌‌​​‌​‌​‌‌‌​​‌‌​‌‌‌​​​​​‌‌​‌‌‌‌​‌‌​‌‌‌​​‌‌‌​​‌‌​‌‌​‌​​‌​‌‌​​​‌​​‌‌​‌​​‌​‌‌​‌‌​​​‌‌​‌​​‌​‌‌‌​‌​​​‌‌​‌​​‌​‌‌​​‌​‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌​‌​​​​‌‌‌​‌​​​‌‌​‌‌​‌​‌‌​‌‌​​