简介:Ansible 2.9.27 是面向 CentOS 7 / RHEL 7 运维环境的自动化管理工具包,适合系统管理员、运维工程师及正在学习自动化配置的开发者。压缩包集成了 Ansible 主程序及其依赖的 Python 模块与 SSH 辅助组件,可帮助用户在没有额外代理的情况下,通过 Playbook 完成批量配置、软件部署和服务管理。资源共 29 个文件,主要包含 rpm 安装包、gz 压缩文件、bz2 数据库备份及 xml 元数据文件,总大小约 19.29MB,结构接近本地 YUM 仓库布局,便于离线安装和内网快速部署。目前已有 632 人学习下载,适合需要在内网环境搭建自动化运维基础平台的场景。包内除核心的 Ansible 2.9.27 RPM 外,还附带 paramiko、Jinja2、PyYAML、cryptography、sshpass 等关键依赖,以及仓库元数据文件,用户可直接用于构建本地安装源。借助这些组件,读者可快速掌握 Ansible 的模块调用、Playbook 编写和主机清单管理,提升批量运维效率。 最近不少朋友私信问我:明明 Ansible 已经出了 2.10、2.11 甚至更新的版本,为什么生产环境里还要守着 ansible-2.9.27 这个版本不放?实际上,如果你去翻一翻那些跑了两三年、几百台机器的存量集群,会发现 2.9 系仍然占据很大比例。2.9.27 作为整个 2.9 分支的最后一个维护版本,兼顾了模块稳定性、Python 2/3 双兼容和 playbook 语法一致性,对很多运维团队来说,够用、稳定、文档全,就是它最大的价值。
这篇文章我会从版本选型开始,讲清楚 ansible-2.9.27 到底适合什么场景,然后完整演示从安装部署、SSH 打通、inventory 配置,到批量复制文件到所有节点并授权 777 权限的整套操作。不管你是刚入手 Ansible 的菜鸟,还是已经写过不少 playbook 的老手,只要你的环境还停留在 2.9.x,这篇内容都能直接拿去做参考。
1. 为什么还在守着 2.9.27:版本选型背后的考量
1.1 2.9.27 到底是个什么版本
Ansible 的版本号体系在 2.9 之后发生了一个比较大的变化:从 2.10 开始,原来的“大而全”的 ansible 包被拆分成 ansible-core 和一堆按功能拆分的 collection 集合包。这意味着如果你从 2.9 升级到 2.10+,很多以前直接可用的模块名称可能就变了,或者需要额外安装 collection 才能使用。对于已经写好几千行 playbook 的团队来说,这种不兼容改动带来的迁移成本远远大于升级本身带来的收益。
2.9.27 是整个 2.9 系列的最后一个发布版本,发布于 2021 年。它修复了 2.9 分支上的一批已知 bug,同时保持了与早期 2.9.x 的完全兼容。换句话说,它就是 2.9 系列的“最终形态”。这个版本最舒服的地方在于:你不需要关心 collection 的依赖关系,不需要担心某个模块被迁移到别的命名空间,所有常用的模块(copy、command、shell、yum、service、template 等)都在同一个安装包里,装完就能用。
我还特意对比过 2.9 和 2.11 在批量任务上的表现,对于日常的 copy、shell、yum 这类操作,两者的执行效率几乎没有肉眼可见的差别。既然功能上没有本质提升,那待在稳定区反而是更理性的选择。
1.2 这个版本的适用场景和边界
我自己的判断是,下面这几类环境最适合跑 2.9.27:
- 存量服务器数量多、系统版本杂,比如 CentOS 6、CentOS 7、Ubuntu 16.04 混合存在的机房。2.9.27 对被管端 Python 版本的要求很宽松,Python 2.6 以上就能跑 raw 和 script 模块,Python 2.7 或 3.5 以上就能跑完整模块,这对老系统非常友好。
- 已经有大量 playbook 和 roles 积累,贸然升 2.10+ 会导致角色里的模块引用失效。
- 企业内部对软件版本有严格的变更流程,升级 Ansible 这种底层工具需要走一堆审批,既然 2.9.27 没出大问题,那就没必要折腾。
当然,这个版本也有明显的短板:官方已经停止了对 2.9 系列的维护,包括安全补丁。如果你管理的节点暴露在公网,或者需要对接一些很新的云厂商 API,建议还是评估升级计划。但在内网隔离、环境稳定的前提条件下,2.9.27 的生产价值依然很高。
2. 部署与初始化:从控制端到被管节点的打通
2.1 控制端安装与版本验证
Ansible 是典型的无代理(Agentless)架构,它只需要在一台控制机上安装,被管节点不需要装任何客户端。控制端建议用一台专门的 Linux 机器,CentOS 7/8 或者 Ubuntu 18.04/20.04 都可以。Windows 上虽然可以通过 WSL 跑,但生产环境我不推荐,网络和文件路径容易出幺蛾子。
安装 2.9.27 最干净的方式是 pip。用系统自带的 Python 3 环境直接装:
python3 -m pip install ansible==2.9.27如果你的服务器上有多个 Python 版本,建议先建一个虚拟环境,避免污染系统环境:
python3 -m venv /opt/venv-ansible source /opt/venv-ansible/bin/activate python -m pip install ansible==2.9.27装完以后先看版本,确认装对了:
ansible --version正常输出里会带ansible 2.9.27以及python version信息。我遇到过一种情况是系统里已经装了低版本的 ansible,pip 安装提示成功,但ansible --version显示的仍然是老版本,这是因为 PATH 里旧命令优先级更高。用which ansible查一下路径,必要时把虚拟环境的 bin 目录加到 PATH 最前面。
2.2 SSH 免密与 inventory 配置
控制端装好之后,下一步就是打通到被管节点的 SSH 通道。Ansible 默认走 SSH 协议,最常用、最稳的方式是密钥免密登录。
在控制端生成密钥对(如果还没有的话):
ssh-keygen -t rsa -b 4096然后批量把公钥分发到所有节点。如果节点数量不多,可以一个个执行:
ssh-copy-id root@192.168.1.101 ssh-copy-id root@192.168.1.102第一次连接会提示确认指纹,输入 yes 后输入密码即可。如果节点数量多,可以写个循环脚本,但前提是你得知道所有节点的 root 密码,这在批量初始化时也算常见需求。
免密配好后,别急着写 playbook,先手动 SSH 到每个节点确认能无密码登录。这一步能帮你把“连接失败”和后面的“任务执行失败”彻底隔离开。
接下来是 inventory 文件。默认位置在/etc/ansible/hosts,但更推荐在项目目录里用自定义 inventory,这样每个项目可以维护自己的主机列表。创建一个hosts.ini:
[web] 192.168.1.101 192.168.1.102 [db] 192.168.1.201 [all:vars] ansible_user=root ansible_ssh_port=22[all:vars]这段表示对所有主机生效的变量。如果你的节点有不属于默认 22 端口的,可以在主机后面单独用ansible_port=2222覆盖。
2.3 ansible.cfg 的关键参数调优
很多人安装完就开始写命令,完全没碰过 ansible.cfg,这会导致两个很常见的问题:第一次连接卡在确认 SSH 指纹的交互提示上,以及并发执行太慢。
在项目根目录创建一个 ansible.cfg,内容如下:
[defaults] inventory = ./hosts.ini host_key_checking = False forks = 20 interpreter_python = auto_silent log_path = ./ansible.log retry_files_enabled = False逐个解释一下:
host_key_checking = False:跳过 SSH 指纹确认。新节点第一次连接时,不会卡在Are you sure you want to continue connecting (yes/no)?。forks = 20:默认并发数是 5,对几十台节点的批量任务来说太慢了。调到 20 通常够用,调太高反而可能因为 SSH 连接数太多触发被管端限制。interpreter_python = auto_silent:让 Ansible 自动探测被管端的 Python 解释器,而不是默认死磕/usr/bin/python。这个对 CentOS 8 这类默认没有 Python 2 的系统特别重要。log_path:把日志写到文件,排查问题时非常有用。retry_files_enabled = False:不生成.retry文件,省得目录里堆一堆垃圾。
配置完成后,用 ping 模块验证连通性:
ansible all -m ping如果全部返回"pong",说明控制端和所有节点的通道已经打通,可以开始写真正的任务了。
3. 批量复制文件到所有节点并授权 777:核心实战
3.1 需求拆解与 copy 模块参数速览
“复制文件到所有节点,并授权 777 权限”这个需求,表面上很简单,但实际操作中有一个容易踩坑的点:如果只写了mode=0777,老手都知道要关注文件所有者和目标路径的父目录权限;而如果目标文件已存在,还要考虑是否强制覆盖。为了让你能完整复现,我们先拆一下需求:
- 源文件:控制端上的一个文件(比如
app.sh)。 - 目标位置:所有被管节点的某个路径(比如
/usr/local/bin/app.sh)。 - 权限要求:777,也就是
rwxrwxrwx。
ansible-2.9.27 的 copy 模块常用参数如下:
| 参数 | 作用 | 说明 |
|---|---|---|
src | 源文件路径 | 可以是相对路径或绝对路径 |
dest | 目标文件路径 | 必填 |
mode | 权限设置 | 支持0777、'0777'、u=rwx,g=rwx,o=rwx等写法 |
owner | 目标文件属主 | 不指定时保持默认或沿用已有文件 |
group | 目标文件属组 | 同上 |
backup | 覆盖前是否备份 | 设为yes会在目标目录生成带时间戳的备份 |
force | 是否强制覆盖 | 默认为yes,设为no时仅在目标文件不存在时才复制 |
这里有个细节:mode=0777的写法在 YAML 或命令行里有时会被解析成十进制 511,导致最终权限变成---x--x--x之类奇怪的结果。保险的做法是加引号:mode='0777',或者直接用符号模式mode=u=rwx,g=rwx,o=rwx。
3.2 用一条命令完成批量分发
如果你只是临时一次性的分发,用 ad-hoc 命令最快捷:
ansible all -m copy -a "src=/data/app.sh dest=/usr/local/bin/app.sh mode='0777' owner=root group=root" -f 20执行完以后,你会看到每个节点返回一个"changed": true或者"changed": false。changed 为 true 表示文件被复制或权限被修改了;false 表示目标文件内容和权限已经和源一致,这是 Ansible 的幂等性在起作用。
需要说明的是,copy 模块只适合复制单个文件或目录。如果要同步大量文件,或者目标文件特别大,建议用 synchronize 模块,它底层走 rsync,增量传输效率会高很多。不过对于分发一个脚本、一个配置文件这种场景,copy 足够用了。
3.3 用 Playbook 固化分发流程
ad-hoc 命令适合临时操作,但如果你需要每周或者每次发版都执行同样的操作,那必须写成 playbook。它不仅能重复执行,还能把分发、权限、验证、通知等逻辑固化下来,方便团队协作和代码审查。
创建一个deploy.yml:
--- - name: 分发脚本到所有节点并授权 777 hosts: all become: yes tasks: - name: 复制 app.sh 到目标路径 copy: src: /data/app.sh dest: /usr/local/bin/app.sh mode: '0777' owner: root group: root backup: yes - name: 验证目标文件权限 command: ls -l /usr/local/bin/app.sh register: result - name: 输出验证结果 debug: var: result.stdout这个 playbook 里我加了become: yes,因为默认情况下用 root 登录时其实不需要 sudo,但如果你用普通用户连接,再用 sudo 提权,就必须加这个参数。register把命令输出存到变量里,然后通过debug打印出来,方便观察每次执行的效果。
执行:
ansible-playbook -i hosts.ini deploy.yml如果你的节点不是全部都要部署,而是只想对某一组,比如只给 web 组分发,把 hosts 改成hosts: web即可。如果你需要灵活指定分组,可以用参数:
ansible-playbook -i hosts.ini deploy.yml --limit web--limit的作用是在 playbook 指定的范围之上再做一层过滤,非常实用。
3.4 分发后的批量验证与权限核对
文件分发完,不能只看返回结果就完事,还要实际确认所有节点上的文件权限和目标状态。用 ad-hoc 或者 playbook 都能验证。
命令行的方式:
ansible all -m shell -a "ls -l /usr/local/bin/app.sh && md5sum /usr/local/bin/app.sh"对比每个节点的 MD5 值是否与控制端源文件一致,这是最基础的完整性校验。
也可以用 stat 模块,直接读取文件的权限、大小、修改时间等元信息:
ansible all -m stat -a "path=/usr/local/bin/app.sh"输出里能看到mode: '0777'、uid: 0等字段。用 stat 的好处是不会像 shell 那样拼接命令,结果格式是结构化的,适合后续用register配合条件判断。
这里还要提醒一句:777 权限意味着任何用户都能读写执行这个文件。如果是把脚本放到生产环境,我建议先把脚本内容给安全同事看一眼,确认文件里没有敏感信息或可被利用的注入点。很多团队在文件分发后出现安全问题,不是 Ansible 的锅,而是权限太宽松加上脚本本身有漏洞。
4. 常见问题与排查技巧实录
4.1 连接阶段的坑
我在实际部署中踩到的第一个坑,就是新节点第一次执行时报错:
Host key verification failed.原因就是没设置host_key_checking = False,ssh 在首次连接时要求确认指纹,而 Ansible 的非交互执行直接被卡住。解决方式很简单,就是在 ansible.cfg 里加那行配置,或者在 inventory 主机变量里写ansible_ssh_common_args='-o StrictHostKeyChecking=no'。
第二个常见问题是 SSH 连接超时。如果节点数量多、网络有延迟,默认的 10 秒超时时间可能不够。可以在 ansible.cfg 里加:
[ssh_connection] timeout = 30 ssh_args = -o ControlMaster=auto -o ControlPersist=60sControlMaster和ControlPersist这两个参数是给 SSH 连接复用的,当你对同一台机器连续执行多个任务时,可以复用同一个 SSH 连接,大幅提升执行速度。
4.2 权限与解释器问题
用非 root 用户连接时,如果 sudo 密码没配置,执行任务会报:
Missing sudo password解决方式是在 inventory 里给目标主机指定密码变量:
[web] 192.168.1.101 ansible_user=deploy ansible_become_pass='xxxxx'不过把密码写在文件里有泄露风险,更推荐用ansible-vault加密 inventory 或 vars 文件。
还有个高频问题是:
The Python 2 bindings were not found on the target host这通常是因为目标系统是 CentOS 8/Ubuntu 20.04 这类默认不带 Python 2 的新系统,而 Ansible 默认找/usr/bin/python。我在前面 ansible.cfg 里配置的interpreter_python = auto_silent能解决大部分情况,但如果你的主机比较特殊,手动指定 Python 解释器也挺简单:
ansible all -m ping -e 'ansible_python_interpreter=/usr/bin/python3'建议把解释器变量放在 inventory 的组变量里,而不是每次手动传。
4.3 批量操作安全的底线建议
最后聊一点批量操作的安全底线。在几百上千台机器上执行chmod 777或者rm -rf这种命令,一旦出错就是事故级别。我有几个习惯,分享给你:
- 每次批量操作前用
--check(试运行)模式先跑一遍,看 Ansible 会做哪些变更。虽然 check 模式对 copy 和 command 这类模块的模拟能力有限,但它至少能过滤掉一部分明显错误。 - 使用
--step参数,让 Ansible 在每台机器执行前交互确认。节点少的时候这个参数很有用。 - 在 playbook 里用
when加一些保险条件,比如只在某个文件存在、或者只在某个版本号匹配时才执行。 - 涉及覆盖文件时,尽量在 copy 任务里加
backup: yes,万一覆盖错了可以快速回滚。
这些习惯并不能保证 100% 不出事,但能让你在一个晚上连续操作几十个批次的时候,心里稍微踏实一点。
另外还有一个小技巧:用 ansible-vault 加密敏感变量
ansible-vault encrypt group_vars/all.yml之后执行 playbook 时需要加--ask-vault-pass,适合存放 sudo 密码、API 密钥等明文内容。虽然 2.9.27 不是最新版本,但 ansible-vault 这个功能在 2.9 里已经完全成熟,完全可以放心用。
写到这里,我把自己在 ansible-2.9.27 上最常用的一套部署和文件分发流程完整过了一遍。如果你还是新手,建议先把前面控制端和被管端的连通性打通,再用个测试节点跑一遍 copy 分发和权限设置,最后再操作生产环境。把 ad-hoc 命令的返回结果仔细看一遍,你会发现 Ansible 的日志输出里几乎把每一台机器的状态都交代清楚了,多读日志比到处问人更管用。
本文还有配套的精品资源,点击获取