包管理抽象层
package 模块本身不装包,它读取目标主机的事实变量 ansible_pkg_mgr,再转发给 yum、dnf、apt、zypper、pacman 等具体后端。因此同一段任务可以同时跑在 CentOS、Ubuntu 与 openSUSE 上。代价是只能用各后端的公共参数;一旦需要模块流、enable_plugin、allow_downgrade 这类发行版特有选项,就得换回具体模块并用条件分支隔离。
基本信息
| 模块名 | ansible.builtin.package(分发到 yum/dnf/apt/zypper 等) |
|---|---|
| 依赖事实 | ansible_pkg_mgr、ansible_os_family、ansible_distribution |
| 适用平台 | Linux 各发行版;Windows 用 win_package |
| 权限要求 | 通常需要 become 提权到 root |
典型使用场景
- 同一套 playbook 覆盖 CentOS、Ubuntu、阿里云 Linux 等混合节点
- 安装各发行版都同名的基础包(curl、chrony、unzip)
- 卸载统一用 state: absent,不必记各后端命令
- 需要发行版特有参数时按 os_family 写条件任务
- 批量预置依赖前先统一基线,减少后续任务的分支
统一与分支的写法
统一与分支的写法
- name: 统一安装基础包 # package 自动选 yum/dnf/apt
ansible.builtin.package:
name: "{{ base_packages }}"
state: present
- name: Debian 系额外依赖 # 包名不同就加条件分支
ansible.builtin.apt:
name: apt-transport-https
state: present
when: ansible_os_family == 'Debian'
- name: 查询已装版本 # 用事实或 command 校验,避免反复安装
ansible.builtin.command: rpm -q chrony
changed_when: false发行版与后端
| 系统族 | 实际后端 | 常用具体模块 |
|---|---|---|
| RHEL / CentOS 8+ | dnf | ansible.builtin.dnf |
| CentOS 7 | yum | ansible.builtin.yum |
| Debian / Ubuntu | apt | ansible.builtin.apt |
| openSUSE | zypper | community.general.zypper |
| Arch | pacman | community.general.pacman |
ansible_pkg_mgr 来自事实采集。若 playbook 设了 gather_facts: false,package 可能判不出后端而报错,此时要么保留事实采集,要么显式调用具体模块。
包名跨发行版经常不一致:httpd 与 apache2、mysql-server 与 default-mysql-server。用变量映射(按 os_family 给不同包名)比在每个任务上挂 when 更易维护,也便于把差异集中到 group_vars 里。
为什么还要用具体模块
package 的公共参数只有包名、状态与少数通用开关,各后端真正的差异都藏在专有参数里:dnf 有模块流与插件开关,apt 有忽略校验与 dpkg 参数,zypper 有按类型安装与旧版本处理。跨发行版 playbook 的常见结构因此是两层:绝大多数公共包走 package,少数需要专有参数的包单独写成带条件的分支,让差异显式可见。
混用 package 与具体模块的后果:某个包已由 dnf 模块装上,再用 package 判定时仍以包数据库的实际状态为准,所以不会重复安装;但两个模块对“是否变更”的判定粒度不同,同一台机器连续跑两次可能在输出里看到 changed 与 ok 交替,属于正常现象,看包状态即可。