Ansible 2.10+ 模块拆分:ansible.builtin与ansible.posix选型指南

发布时间:2026/10/8 18:08:58
Ansible 2.10+ 模块拆分:ansible.builtin与ansible.posix选型指南
1. 为什么会出现 ansible.builtin 和 ansible.posix 两个命名空间1.1 Ansible 2.10 之后的模块拆分如果你和我一样是从 Ansible 2.9 一路用过来的第一次看到ansible.builtin和ansible.posix的时候大概率会愣一下这俩看起来都像“Ansible 官方出的东西”凭什么要分两个名字尤其当你看到文档里的示例一会儿写ansible.builtin.copy一会儿写ansible.posix.sysctl很容易觉得自己是不是漏学了什么。其实答案并不复杂。Ansible 2.10 之后原来的“一大包模块”不再全部堆在 ansible-base 里面而是按照场景拆分成了很多集合Collection。这个拆分的本质是把原本混在一起的代码重新组织成可独立发布、独立版本、独立维护的包。你可以把它理解成一套工具箱被重装了以前所有工具都挂在一块木板上想要啥直接拿现在分成了好几个抽屉每个抽屉负责一类任务。ansible.builtin就是那个始终放在手边的“基础抽屉”里面是 Ansible 核心引擎直接依赖、并且随 ansible-core 一起发布的模块。而ansible.posix是新拆出来的“POSIX 系统配置抽屉”专门放那些和 Linux/Unix 系统底层配置强相关的模块。1.2 ansible.builtin 到底是什么ansible.builtin不是某个可以在 Galaxy 上单独下载的包它是 ansible-core 的一部分。换句话说只要你安装了 ansible-coreansible.builtin里的模块就已经可用了不需要额外安装也装不了、卸不掉。它包含的东西非常杂但都是“通用自动化操作”的底子比如执行命令ansible.builtin.command、ansible.builtin.shell、ansible.builtin.script文件操作ansible.builtin.file、ansible.builtin.copy、ansible.builtin.template、ansible.builtin.lineinfile软件包管理ansible.builtin.apt、ansible.builtin.dnf、ansible.builtin.yum、ansible.builtin.package服务管理ansible.builtin.service、ansible.builtin.systemd、ansible.builtin.sysvinit流程控制ansible.builtin.debug、ansible.builtin.assert、ansible.builtin.set_fact、ansible.builtin.include_tasks所以ansible.builtin更像是“Ansible 这个语言本身的标准库”。哪怕你后面的 playbook 一个第三方集合都不用靠这些模块已经能完成绝大多数日常任务。1.3 ansible.posix 到底是什么ansible.posix是 Red Hat 维护的一个独立集合随 Ansible 社区发行版默认安装但如果你用的是最小化安装的ansible-core它不一定在环境里。这个集合的定位非常明确处理 POSIX 系统层面的专项配置。看名字里有 POSIX但别被名字骗了它不是要覆盖所有类 Unix 系统而是收编了那些“跟系统底层工具强相关”的模块比如管理挂载点、调整内核参数、处理 SSH 授权密钥、控制 SELinux 状态、配置防火墙、设置 ACL 等等。常见模块包括ansible.posix.mount管理挂载点和 fstabansible.posix.sysctl管理内核参数ansible.posix.authorized_key管理 SSH 公钥授权ansible.posix.firewalld管理 firewalld 防火墙规则ansible.posix.acl管理 POSIX ACLansible.posix.synchronize包装 rsync 做文件同步ansible.posix.selinux、ansible.posix.seboolean、ansible.posix.sefcontextSELinux 相关配置正是因为这些模块看起来都很“系统”如果你之前只熟悉老版本 Ansible会误以为它们本来就该属于ansible.builtin。实际上在 2.10 拆分时它们被明确归到了ansible.posix这个集合里。2. 一张表看懂 ansible.builtin 和 ansible.posix 的核心差异2.1 核心对比表下面这张表基本可以覆盖日常判断时需要用到的信息维度ansible.builtinansible.posix定位Ansible 核心引擎自带的标准库POSIX 系统专项配置集合安装方式随 ansible-core 自动提供不可单独安装随 Ansible 发行版默认安装也可用 galaxy 单独安装版本管理跟随 ansible-core 版本独立版本号可单独升级维护方Ansible Core TeamRed Hat / Ansible Collections 团队典型模块copy、file、command、shell、apt、servicemount、sysctl、authorized_key、firewalld、acl、synchronize依赖大多数基于 Python 标准库和常见系统命令更依赖外部系统工具如 mount、sysctl、rsync、patch、firewall-cmd适用范围通用任务、流程控制、基础文件/包/服务操作Linux/Unix 系统配置专项操作升级风险必须随 ansible-core 一起评估可以在 requirements.yml 中单独锁定版本这张表说明了一个关键点这不是“新写法”和“旧写法”的对比而是“基础库”和“系统工具集合”的对比。ansible.builtin永远都在ansible.posix则需要考虑是否随环境安装。2.2 ansible.posix 里具体有哪些模块我接触过的项目里出现频率最高的ansible.posix模块大概是下面这些。记住这个清单你遇到“系统配置类任务”时就知道该往哪里找了模块作用依赖的外部工具ansible.posix.sysctl管理/etc/sysctl.conf或/etc/sysctl.d/下的内核参数sysctlansible.posix.mount管理 fstab 挂载条目和当前挂载状态mount、umount、findmnt 等ansible.posix.authorized_key管理用户的~/.ssh/authorized_keys文件ssh-keygen 等ansible.posix.firewalld管理 firewalld 的端口、服务、富规则firewall-cmdansible.posix.acl给文件/目录设置 POSIX ACLsetfacl、getfaclansible.posix.synchronize封装 rsync 做增量同步rsyncansible.posix.patch使用 patch 命令应用补丁文件patchansible.posix.at通过 atd 调度一次性任务atansible.posix.selinux修改 SELinux 状态和策略SELinux 相关 Python 绑定ansible.posix.seboolean切换 SELinux booleansetsebool 等ansible.posix.sefcontext管理 SELinux 文件上下文映射semanage 等实际项目中不一定要全用上但知道边界很重要如果某个任务的官方文档写的是ansible.posix.xxx但你安装的只是ansible-core那你必须先确认这个集合是否在当前执行环境里。2.3 ansible.builtin 里最常用的模块ansible.builtin的模块数量很多背下来不现实但可以按照职能分类记文件与内容copy、template、file、lineinfile、blockinfile、stat、find命令与执行command、shell、script、raw、expect包管理package、apt、dnf、yum、pip服务与进程service、systemd、sysvinit、service_facts流程控制与变量debug、assert、fail、set_fact、include_vars、include_tasks、import_tasks、block、rescue远程信息gather_facts、slurp、fetch、wait_for网络与下载get_url、uri这些模块解决的问题更偏“Ansible 任务本身”文件要拷过去、包要装好、服务要起来、命令要在远端执行。它们不一定非要是某个操作系统特有的能力而是各种场景下都会用到的基础操作。3. 同一个任务到底选哪一个边界和选型逻辑3.1 先用“操作对象”划边界我的一个简单判断方法是先看这个任务是在操作“Ansible 能控制的东西”还是在操作“操作系统本身的配置”。如果是前者比如我要复制配置文件、安装软件包、启动服务那就优先用ansible.builtin。它的模块足够泛化跨 Linux 发行版时会尽量帮你抹平差异。如果是后者比如我要改内核参数、改 fstab、配 firewalld、设置 SSH authorized_keys、应用 AC L规则那就去看ansible.posix。因为这类操作往往直接和系统里的某个工具对应写进ansible.posix反而更合理。举个例子复制一个 nginx 配置到目标机器用ansible.builtin.copy就够了。但如果想让某个目录对某个用户开放可读权限而且这个权限不是简单的755能表达的那我就会考虑ansible.posix.acl。3.2 三组容易被误用的场景我以前踩过几个坑也见过同事在这几个地方犹豫这里单独拿出来说一下。第一组是ansible.builtin.file和ansible.posix.acl的选择。file模块能设置 owner、group、mode但它处理的是传统权限模型。如果你需要让“某个特定用户”对某个目录拥有读权限同时不影响其他用户权限就不可能只靠mode实现。这种时候用ansible.posix.acl就非常合适。第二组是手动管理 SSH 公钥和ansible.posix.authorized_key的选择。有些人会用copy或者template把整个authorized_keys文件覆盖上去。这种做法在“一次性初始化”时没问题但如果你在多台机器上持续管理很容易出现两个问题一是把别人机器上已有的管理员公钥覆盖掉二是重复执行任务时文件内容可能不一致。authorized_key模块会自己维护文件结构保证幂等而且可以精确地只添加或删除某一个公钥。所以我后来只要涉及 SSH 公钥管理一律用ansible.posix.authorized_key。第三组是用command还是mount来写挂载。早期我看到过有人在 playbook 里用shell直接执行echo ... /etc/fstab然后又用mount -a。这种写法风险非常高重复执行会写重复条目fstab 写错会导致机器重启起不来而且完全没有任何校验。ansible.posix.mount这个模块虽然也要调系统命令但它会管理 fstab 的条目格式能避免重复还能在检查模式下预览变更这是 shell 加 echo 完全没有的保障。3.3 三条选型规则如果你不想每条任务都翻文档可以直接按这三条规则来判断只要是“Ansible 引擎层面的动作”比如执行命令、拷贝文件、设置变量、控制流程、安装包、启停服务默认找ansible.builtin。只要是“系统专项配置”比如内核参数、挂载、防火墙、SSH 公钥、ACL、SELinux优先去ansible.posix里查一下有没有对应模块。如果ansible.posix里没有再考虑其他专业集合比如 Windows 相关任务找ansible.windows网络设备任务找对应的厂商集合。这套规则能解决 90% 的纠结。剩下 10% 的边界情况以官方文档的模块归属和版本说明为准。4. 从短模块名到 FQCN两种写法和它们的兼容层4.1 短模块名为什么还能用ansible.legacy 路由很多人升级到新版 Ansible 后发现自己还在写authorized_key:、mount:这种短模块名而且居然能跑。这不是魔法是 Ansible 保留了一个名为ansible.legacy的兼容路由层。当你没有在 playbook 里声明任何集合直接写mount:时Ansible 会按兼容规则找到ansible.legacy.mount然后通过路由表映射到实际模块也就是ansible.posix.mount。这样做的好处是旧 playbook 不会被立刻打破。坏处是如果你用短模块名但没有安装ansible.posix很可能报错得很突然而且报错信息不一定立刻告诉你要装哪个集合。所以我的建议是旧项目可以暂时保留短模块名但新项目尽量用 FQCN。所谓 FQCN就是完全限定模块名例如ansible.posix.mount、ansible.builtin.copy。它最大的价值是一眼就能看出模块属于哪个集合别人接手你的 playbook 时也不会猜“这个 mount 是哪来的”。4.2 推荐写法一直接写 FQCN如果某个 playbook 里只用了一两个ansible.posix模块我会直接写 FQCN不用额外声明collections。比如- hosts: all become: true tasks: - name: 开启 IP 转发 ansible.posix.sysctl: name: net.ipv4.ip_forward value: 1 sysctl_set: true reload: true - name: 部署 SSH 公钥 ansible.posix.authorized_key: user: deploy key: {{ lookup(file, files/deploy.pub) }} state: present这种写法的好处是显式、可靠。哪怕是完全陌生的环境看到ansible.posix.sysctl也能立刻知道这个任务需要安装ansible.posix集合。4.3 推荐写法二playbook 级 collections 声明如果整个 playbook 里有十几个ansible.posix模块每个任务都写ansible.posix.前缀会非常啰嗦。这时候可以在 playbook 顶部声明collections然后继续用短模块名- hosts: all become: true collections: - ansible.posix tasks: - name: 设置内核参数 sysctl: name: net.ipv4.ip_forward value: 1 - name: 挂载 NFS mount: path: /mnt/data src: 192.168.1.10:/srv/data fstype: nfs opts: rw,sync state: mounted需要注意的是collections声明的作用范围是当前 playbook。如果某个角色内部也用到了sysctl最好在角色的 meta 配置里也声明集合或者直接写 FQCN否则会出现“模块找不到”的尴尬。4.4 放到版本库里requirements.yml 与执行环境如果是团队项目我强烈建议把集合依赖写进collections/requirements.yml而不是只在某台机器上手动装。比如collections: - name: ansible.posix version: 1.5.0然后执行ansible-galaxy collection install -r collections/requirements.yml如果你们用的是 AWX / Automation Controller 这类带执行环境的产品也要把ansible.posix加进执行环境的构建文件里。因为执行环境是一个相对干净、可控的镜像不会自动包含你本地手动安装的集合。把依赖写进 requirements.yml再配合构建执行环境才不会出现“本机能跑构建环境里跑不了”的情况。5. 升级后最常见的坑和我怎么排查5.1 “couldnt resolve module/action ansible.posix.xxx”的处理这是我在 ansible-core 裸安装环境里最常遇到的报错。你写好了ansible.posix.sysctl执行时却提示无法解析某个模块。原因很简单当前环境没有安装ansible.posix。排查步骤通常是这样的先确认集合是否真的没有安装ansible-galaxy collection list | grep posix如果没有输出直接安装ansible-galaxy collection install ansible.posix安装完再看一眼能不能在 ansible-doc 里找到ansible-doc -l ansible.posix | grep sysctl如果是在 ansible-core 环境里跑并且你不确定 Ansible 发行版里是否默认包含这个集合那就以上面的命令输出为准。不要想当然认为“Ansible 装了就应该有”。5.2 用短模块名但没装 posix 集合还有一类坑是playbook 里写的是sysctl:这种短模块名但执行环境里没有ansible.posix。由于短模块名依赖ansible.legacy兼容路由一旦对应集合缺失报错信息可能比较绕不一定直接告诉你“去装 ansible.posix”。我的排查习惯是三步走。第一步看报错里有没有“couldnt resolve module”这类关键词。第二步去ansible-galaxy collection list看关键集合是否齐全。第三步如果缺失安装后再跑。如果你希望在报错一开始就明确一点那就老老实实用 FQCN至少报错时能直接告诉你缺的是哪个集合。5.3 两个容易写错的参数习惯排错之外参数也容易踩坑。我讲两个最典型的。第一个是ansible.posix.sysctl的value参数。看起来应该是整数但写代码时最好用字符串。比如ansible.posix.sysctl: name: net.ipv4.ip_forward value: 1为什么因为 YAML 本身在某些场景下会把数字当成不同进制解析尤其是一些带前导零的权限位或者掩码值。用字符串能避免这种隐藏的类型转换问题。第二个是ansible.posix.firewalld的permanent和immediate参数。如果只写permanent: true规则会持久化到配置但当前会话不一定立刻生效如果只写immediate: true当前会生效重启后可能又没了。大多数时候你需要两个都写ansible.posix.firewalld: port: 8080/tcp state: enabled permanent: true immediate: true这个细节在排障时经常被忽略但实际影响非常大你以为规则加上了结果服务重启后防火墙又回到原来的状态。6. 我的使用习惯和一些补充说明6.1 项目里的最小配套现在我自己写 playbook 时默认会做几个固定动作。第一新写的内容一律用 FQCN不靠短模块名的兼容层。第二涉及ansible.posix模块时先把集合依赖写进collections/requirements.yml避免别人拉代码后少装集合。第三在ansible.cfg里设置好collections_path如果是项目级安装通常会指向项目内部的collections/目录ansible-galaxy collection install ansible.posix -p ./collections[defaults] collections_path ./collections这样做之后即使我换了服务器、换了执行环境也能很快把整套依赖恢复出来。6.2 什么时候我仍然刻意不用 posix不过我也不是所有系统配置都会无脑上ansible.posix。如果目标机器环境被压得很小比如容器刚起来、连 rsync 都没有又或者只是临时执行一次简单任务我会优先考虑ansible.builtin里的基础模块。比如文件拷贝用copy命令执行用command而不是为了用某个模块额外引入一整包依赖。但这只是一个“省事”的取舍不是长期方案。真正需要稳定管理的系统配置比如挂载、内核参数、SSH 公钥最终还是要落到ansible.posix上来做因为它能把“系统工具调用”变成“可重复、可检查、幂等”的 Ansible 任务。如果你现在正处在 Ansible 2.9 到 2.10 的升级路上或者刚开始写新 playbook我建议你不要纠结“为什么文档里一会儿 builtin 一会儿 posix”只需要记住ansible.builtin是 Ansible 自带的基础能力ansible.posix是系统专项配置集合。任务涉及系统底层配置时优先去ansible.posix里找工具涉及通用文件、包、服务、流程时回到ansible.builtin。这个思路能帮你少走很多弯路。