ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

内网离线部署Ansible全攻略:rpm与pip wheel方案详解

内网离线部署Ansible全攻略:rpm与pip wheel方案详解 1. 离线部署Ansible的整体思路在实际运维环境里摸爬滚打过的朋友应该有同感真正让人头疼的从来不是Ansible本身怎么用而是怎么在没有外网、没有软件源、甚至连基础仓库都残缺不全的内网环境里把它顺顺利利装上去。我之前接过一个银行外包项目服务器全在内网隔离区安全策略严格到连yum源都是内部镜像版本还停留在CentOS 7.6。当时需要批量推送巡检脚本和定时任务第一反应就是用Ansible结果一看环境傻了——管控机和几百台目标机上全没有Ansible而且没法直接访问公网。最要命的是甲方还不允许临时开通外网权限所有安装包都要通过光盘和U盘拷进去。那会儿网上关于离线安装Ansible的教程又少又碎不是缺依赖说明就是只针对单一系统版本。我前前后后踩了不少坑才梳理出一套在几乎所有Linux发行版上都能用的离线安装方案。今天把它写出来希望能帮到正在内网环境里折腾的朋友。先说清楚这套方案能解决什么问题它不依赖外网、不依赖在线软件源只需要一台能上网的“制卡机”和一块U盘就能把Ansible完整装进隔离网络里的任意Linux系统。无论你是CentOS、Ubuntu、Debian还是龙蜥、麒麟这类国产发行版只要按下面的思路走基本都能成。哦对如果你只是在自己的开发机、虚拟机上装Ansible那直接yum install ansible或者pip install ansible就行不需要看这篇文章。本文面向的是那些网络受限、软件源受限、对安装包有严格审计要求的真实生产环境。1.1 离线安装为什么难很多人觉得离线安装不就是把rpm包拷过去再装一遍吗有什么难的。真做起来就会发现几个非常恶心的问题依赖关系像蜘蛛网一样Ansible本身依赖Python的paramiko、PyYAML、Jinja2等一堆库这些库又各自有依赖纯手动逐个下载非常痛苦。不同系统的软件包格式不一样CentOS用rpmUbuntu用deb即使都是RedHat系CentOS 7和CentOS 8的依赖名、版本差异也很大。系统自带Python版本不一致CentOS 7是Python 2.7CentOS 8是Python 3.6Ubuntu 22.04是Python 3.10Ansible对不同Python版本的兼容性不一样直接拿编译好的包可能会因为Python版本不匹配而失败。内网机器往往没有配置DNS解析、没有时间同步也可能影响安装脚本的执行。这套方案的核心思路就是在制卡机上准备好所有安装介质然后通过rpm包或Python wheel包两种途径实现“一个U盘走天下”的离线安装。1.2 方案选型rpm包 vs pip wheel包我在实际项目中用过两种主流的离线安装路径各有优劣简单做个对比方案适用系统优点缺点rpm包离线安装CentOS/RHEL/银河麒麟等RedHat系安装简单依赖自动解决如果配置好本地仓库与系统集成度高包体积大跨系统版本兼容性差Ubuntu/Debian系用不了pip wheel离线安装所有有Python的Linux系统跨发行版通用适合“适合任何系统”的场景包体积相对小可定制版本需要确保Python版本兼容依赖冲突需要自己处理如果你只需要在RedHat系服务器上装rpm方式省心。但标题既然是“适合任何系统”那pip wheel方式就是最通用、最稳妥的路径——只要目标机上有Python 3就一定能装。所以这篇文章会把两种方式都讲透你根据自己的环境对号入座。我个人的建议是如果你要批量部署到几十上百台不同系统的机器优先做pip wheel包如果你只是管理统一的CentOS集群rpm包方案更快。2. 制卡机环境准备与依赖打包所谓“制卡机”就是一台能访问外网的Linux机器用它来下载所有需要的安装包然后做成离线安装介质。这台机器不需要和你目标环境完全一样但系统架构必须一致x86_64的包不能装到ARM机器上这是硬性规定。2.1 确认系统架构与Python版本制卡机开机后第一件事是确认基础信息# 查看系统发行版 cat /etc/os-release # 查看系统架构 uname -m # 查看Python版本 python3 --version # 查看pip是否存在 pip3 --version用我之前的经验来说uname -m输出的是x86_64还是aarch64直接决定了你后面下载哪个架构的包。如果你目标机是ARM架构的麒麟系统那制卡机也必须是ARM机器否则拷过去的包全部装不了。Python版本这个点要格外上心。Ansible 2.9及以下版本对Python 3.8以上的兼容性很差Ansible 4.0以上又要求Python 3.8。我推荐直接使用Ansible 2.9.27或者Ansible Core 2.12.x这两个分支的兼容性最好对Python 3.6到3.10都支持得不错离线部署不容易翻车。确认好这些信息后记下来后面下载包时要用。2.2 离线rpm包下载与打包如果你走rpm路线RedHat系系统上有现成的工具可以一键下载某个包及其所有依赖。在制卡机上执行# CentOS 7/8安装yum-utils yum install -y yum-utils # 创建存放目录 mkdir -p /opt/ansible-offline/rpms cd /opt/ansible-offline/rpms # 下载ansible及其所有依赖但不安装 yumdownloader --resolve --destdir /opt/ansible-offline/rpms ansible这条命令会把ansible以及它所有的依赖rpm包全部下载到指定目录不会安装到制卡机上。下载完成后检查一下ls -lh /opt/ansible-offline/rpms/如果输出里有ansible-xxx.rpm同时还有很多python3-xxx、sshpass之类的依赖包就说明下载成功了。这里有个坑yumdownloader --resolve在某些系统上不会下载“弱依赖”可能导致目标机安装时提示缺包。保险起见我一般会再手动补几个常见的依赖yumdownloader --resolve --destdir /opt/ansible-offline/rpms sshpass python3-jinja2 python3-yaml python3-paramiko python3-cryptography如果你用的是CentOS 8或更新的系统dnf代替了yum命令稍微变一下dnf download --resolve --destdir /opt/ansible-offline/rpms ansible下载完所有rpm包后做成tar包方便拷贝cd /opt/ansible-offline tar czf ansible-offline-rpms.tar.gz rpms这样制卡机上的活就算完成了把这个tar包拷到U盘里带到内网目标机器上。2.3 pip wheel包下载与打包如果你走pip路线核心工具是pip download。在制卡机上先装好pip# CentOS/RHEL系 yum install -y python3-pip # Ubuntu/Debian系 apt install -y python3-pip然后创建目录并下载ansible及其所有依赖的wheel包mkdir -p /opt/ansible-offline/wheels cd /opt/ansible-offline/wheels pip3 download ansible2.12.5 -d /opt/ansible-offline/wheels这条命令会下载ansible以及它运行时需要的所有Python库到wheels目录。下载完成后看看文件列表ls -lh /opt/ansible-offline/wheels/正常情况下能看到ansible-2.12.5-py3-none-any.whl还有一些PyYAML-*.whl、Jinja2-*.whl、cryptography-*.whl、paramiko-*.whl等文件。这里要特别说一个容易踩的坑pip默认可能会下载源码包tar.gz而不是编译好的wheel包。源码包在目标机上安装时需要编译没有gcc、python3-dev的情况下直接失败。解决办法是加参数强制只要wheel格式pip3 download ansible2.12.5 -d /opt/ansible-offline/wheels --only-binary:all:加上--only-binary:all:后pip只会下载.whl文件不会下源码包。如果你发现某个库只有源码包没有wheel包在纯Python项目里很少见但偶尔会有就要考虑换一个版本或者干脆放弃这个依赖。打包cd /opt/ansible-offline tar czf ansible-offline-wheels.tar.gz wheels拷到U盘带走到这一步制卡机的工作全部结束。3. 目标机离线安装实操到了内网环境就是真正的“验收时刻”了。我按两种方案分别说操作步骤你根据自己的制卡机方案选择对应路径。3.1 rpm包方案在目标机的安装先把U盘或者拷贝介质接到目标机上挂载并解压mkdir -p /mnt/usb mount /dev/sdb1 /mnt/usb cd /mnt/usb tar xzf ansible-offline-rpms.tar.gz cd rpms方案A直接rpm安装所有包最简单的做法直接把目录下所有rpm包一起装rpm -Uvh *.rpm这个命令会尝试安装所有rpm包rpm本身会自动处理依赖如果当前目录下有它需要的依赖包。执行过程中如果看到warning一般问题不大但如果出现error: Failed dependencies说明还有缺失的依赖。rpm方式最怕的就是缺依赖缺失时它会明确告诉你缺哪个包但你需要自己去网上找——内网环境基本找不到所以这个方法风险偏高不太推荐。方案B搭建本地yum仓库强烈推荐更稳妥的方式是把解压出来的rpm目录做成一个本地yum源然后让yum自动解决依赖。需要用到createrepo工具# 如果系统没有createrepo先试着安装 yum install -y createrepo如果目标机上也装不了createrepo……那就有点尴尬了说明目标机的软件源也有问题。这种情况我后面会讲先在制卡机上把createrepo的rpm包一起下载带过来。创建仓库createrepo /mnt/usb/rpms编辑yum源配置vim /etc/yum.repos.d/ansible-local.repo写入内容[ansible-local] nameAnsible Local Repository baseurlfile:///mnt/usb/rpms enabled1 gpgcheck0然后清理缓存并安装yum clean all yum makecache yum install -y ansible这种方式依赖自动解决只要rpm包没下载漏基本一次就能成功。我之前在CentOS 7.6上操作全程不到五分钟就装完了。方案CCentOS 8/DNF系统CentOS 8等使用dnf的系统使用dnf install即可本地仓库配置方式一致dnf clean all dnf makecache dnf install -y ansible安装完成后验证ansible --version看到输出版本号了rpm方案就算大功告成。3.2 pip wheel方案在目标机的安装pip方式的优势在于通用性不管目标机是CentOS、Ubuntu还是麒麟只要Python 3在路径完全一致。同样先挂载U盘解压文件mkdir -p /mnt/usb mount /dev/sdb1 /mnt/usb cd /mnt/usb tar xzf ansible-offline-wheels.tar.gz cd wheels确保目标机有pip。如果系统自带Python 3但没有pip可以用以下方式之一临时装一个# CentOS/RHEL系 yum install -y python3-pip # Ubuntu/Debian系 apt install -y python3-pip # 或者用Python自带的ensurepip python3 -m ensurepip --upgrade然后离线安装所有wheel包pip3 install --no-index --find-links/mnt/usb/wheels ansible--no-index的意思是不要访问PyPI--find-links指定从本目录查找安装包。这条命令执行完后Ansible就装好了。再验证一下ansible --version如果输出版本信息就成功了。3.3 安装后快速验证与免密登录配置装完Ansible只是第一步真正用起来还需要配置目标主机的免密登录。内网环境经常没有ssh-copy-id这个工具所以我一般手动操作# 生成密钥对如果之前没有 ssh-keygen -t rsa -b 2048 # 把公钥拷到目标机器 ssh-copy-id -i ~/.ssh/id_rsa.pub usertarget_host # 如果目标机没有ssh-copy-id手动追加 cat ~/.ssh/id_rsa.pub | ssh usertarget_host mkdir -p ~/.ssh chmod 700 ~/.ssh cat ~/.ssh/authorized_keys chmod 600 ~/.ssh/authorized_keys然后写一个最简单的inventory文件测试mkdir -p /etc/ansible vim /etc/ansible/hosts写入[test_servers] 192.168.1.10 ansible_userroot 192.168.1.11 ansible_userroot执行测试命令ansible test_servers -m ping看到所有主机返回pong就说明Ansible已经能正常使用了。4. 常见问题与排查技巧离线安装这件事说简单也简单说复杂也复杂。我把自己实操中踩过的坑、见过的问题整理成了一份速查清单基本覆盖了大多数离线安装失败的场景。4.1 rpm依赖缺失这个问题在手动用rpm -Uvh时最容易碰到。报错通常长这样error: Failed dependencies: python3-jinja2 is needed by ansible-2.9.27-1.el7.noarch解决思路回到制卡机用yumdownloader单独补下缺失的包重新做成tar包或者看目标机上是否已经有这个包用rpm直接安装缺失的那个rpm -Uvh python3-jinja2-*.rpm经验之谈与其一次次补不如一开始就用createrepo的本地yum方案让yum自动把依赖关系理顺能从源头上规避这个问题。4.2 pip报错 No matching distribution foundERROR: Could not find a version that satisfies the requirement ansible ERROR: No matching distribution found for ansible这个报错通常是--no-index或--find-links写错了pip找不到安装包。检查路径是否存在、wheel文件名是否正确。如果路径没问题另一个原因可能是Python版本和Ansible版本不兼容比如Python 3.6配Ansible 5.0pip会拒绝安装。用pip3 download下载时建议直接指定版本。4.3 Python版本识别错位这个坑我印象特别深。有些系统里有多个Pythonpython3指向Python 3.6但pip装到Python 3.8上去了。你在终端执行ansible时用的是PATH中先找到的那个Python结果提示-bash: ansible: command not found或者装完执行时报ModuleNotFoundError: No module named ansible解决方法是查看实际安装位置手动建立软链接# 看ansible装到哪了 find / -name ansible -type f 2/dev/null # 把可执行文件软链到/usr/local/bin ln -s /usr/local/bin/ansible /usr/bin/ansible以后安装时留意一下用pip3 install装完用which ansible确认路径一步到位。4.4 源码包编译失败如果你下载时有依赖没有wheel包只能产生tar.gz源码包那么目标机安装时就会尝试编译报错信息通常是error: command gcc failed: No such file or directory或者fatal error: Python.h: No such file or directory解决办法有两个一是回到制卡机用pip download时加--only-binary:all:确保全部是wheel二是如果实在无法避免源码包就在目标机上先安装编译工具链# CentOS系 yum install -y gcc python3-devel # Ubuntu系 apt install -y gcc python3-dev4.5 Windows和macOS上的离线安装虽然生产环境的管控机一般推荐Linux但确实有同事喜欢在Windows上写playbook测试。Windows上离线装Ansible的思路其实是借助WSL在WSL里跑Linux环境然后再按pip方式离线安装。具体操作不展开只提醒一句生产管控机不要用Windows依赖和路径处理会让你怀疑人生。macOS相对简单系统自带Python 3直接pip3离线安装即可步骤和Linux完全一样。4.6 银河麒麟/龙蜥等国产系统的注意事项国产操作系统有个共同点底层虽然是RedHat或Debian系但软件源的包名和目录结构可能会有差异。我遇到过最典型的问题是银河麒麟V10ARM版默认Python是3.7部分Ansible版本对ARM架构的wheel包缺失需要手动确认下载了arm64的包。龙蜥OS 8的dnf源默认没有启用epel导致Ansible搜索不到。解决方案都是同一个思路提前在制卡机上把目标架构、目标系统的所有依赖下载完整不要指望目标机的软件源能做任何事。这个话我说得比较重但确实是离线部署的核心价值观。5. 一套可以直接抄作业的完整脚本前面讲了原理和步骤这里我把之前的操作整合成两个脚本一个给制卡机用一个给目标机用。你直接把IP、版本号替换掉就能跑。5.1 制卡机打包脚本#!/bin/bash # 制卡机打包脚本在一台能上网的Linux机器上执行 # 用法bash build_offline_ansible.sh set -e # 配置区 ANSIBLE_VERSION2.12.5 WORK_DIR/opt/ansible-offline ARCH$(uname -m) echo 开始制作Ansible离线安装包 echo 系统架构: $ARCH echo Python版本: $(python3 --version) # 清空并创建目录 rm -rf ${WORK_DIR} mkdir -p ${WORK_DIR}/wheels ${WORK_DIR}/rpms # 用pip下载wheel包适用于几乎所有Linux推荐 echo 下载pip wheel包 pip3 download ansible${ANSIBLE_VERSION} -d ${WORK_DIR}/wheels --only-binary:all: # 如果是RedHat系同时下载rpm包备用 if [ -f /etc/redhat-release ] || [ -f /etc/centos-release ]; then echo 检测到RedHat系系统下载rpm包 yum install -y yum-utils 2/dev/null || dnf install -y yum-utils 2/dev/null yumdownloader --resolve --destdir ${WORK_DIR}/rpms ansible || \ dnf download --resolve --destdir ${WORK_DIR}/rpms ansible fi # 打包 echo 打包 cd ${WORK_DIR} tar czf ansible-offline-wheels.tar.gz wheels if [ $(ls -A ${WORK_DIR}/rpms) ]; then tar czf ansible-offline-rpms.tar.gz rpms fi echo 完成 echo 文件列表 ls -lh ${WORK_DIR}/*.tar.gz echo 把这些tar包拷贝到U盘或内网传输即可。5.2 目标机安装脚本#!/bin/bash # 目标机安装脚本在隔离网络的Linux机器上执行 # 用法bash install_offline_ansible.sh /path/to/tar.gz set -e ARCHIVE_PATH$1 if [ -z $ARCHIVE_PATH ]; then echo 用法: $0 离线包tar.gz路径 exit 1 fi echo 解压安装包 EXTRACT_DIR/tmp/ansible-offline rm -rf ${EXTRACT_DIR} mkdir -p ${EXTRACT_DIR} tar xzf ${ARCHIVE_PATH} -C ${EXTRACT_DIR} # 检测可用的安装方式 if ls ${EXTRACT_DIR}/wheels/*.whl /dev/null 21; then echo 检测到wheel包使用pip离线安装 # 确保pip存在 python3 -m ensurepip --upgrade 2/dev/null || true pip3 install --no-index --find-links${EXTRACT_DIR}/wheels ansible elif ls ${EXTRACT_DIR}/rpms/*.rpm /dev/null 21; then echo 检测到rpm包使用本地yum仓库安装 # 优先尝试yum本地仓库方式 if command -v createrepo; then createrepo ${EXTRACT_DIR}/rpms echo [ansible-local] /etc/yum.repos.d/ansible-local.repo echo nameAnsible Local Repository /etc/yum.repos.d/ansible-local.repo echo baseurlfile://${EXTRACT_DIR}/rpms /etc/yum.repos.d/ansible-local.repo echo enabled1 /etc/yum.repos.d/ansible-local.repo echo gpgcheck0 /etc/yum.repos.d/ansible-local.repo yum clean all yum makecache yum install -y ansible else echo 警告: 系统没有createrepo改用rpm直接安装 rpm -Uvh ${EXTRACT_DIR}/rpms/*.rpm --nodeps fi else echo 错误: 未找到可用的安装包 exit 1 fi echo 验证安装结果 ansible --version echo 安装完成 注意脚本中rpm直接安装用了--nodeps这是为了应急实际使用时还是尽量用yum仓库方案。5.3 扩展思路把离线仓库变成内网yum源如果你的环境机器很多每次都插U盘显然不现实。我建议把做好的rpm包放到内网一台服务器上用Nginx或HTTPD搭一个内网yum源其他机器直接指向这个源安装效率会高非常多。大致做法# 内网源服务器上 yum install -y nginx createrepo mkdir -p /usr/share/nginx/html/ansible/ cp -r /opt/ansible-offline/rpms/* /usr/share/nginx/html/ansible/ createrepo /usr/share/nginx/html/ansible/然后其他机器上的repo文件改为[ansible-local] nameAnsible Local Repository baseurlhttp://内网IP/ansible/ enabled1 gpgcheck0yum install -y ansible一行就能在任意一台内网机器上装好。CentOS、麒麟、龙蜥这些都适用因为走的是系统自带的yum/dnf只是源换成了内网地址。6. 写在最后的一点体会离线安装Ansible这件事看起来只是个“装软件”的小动作但在内网运维中它往往是自动化运维的第一步也是最容易卡住的一步。我这套方案经过多个项目的检验从CentOS 7、Ubuntu 18.04到银河麒麟V10 ARM版都实际跑通过整体稳定性是可以放心的。我个人实际操作中的一个体会是不要图省事只准备一种安装包。我后来做交付时制卡机上会把wheel包和rpm包都打进去一个tar包才几十MBU盘完全放得下但到了现场就能随机应变——RedHat系用rpm方式Debian系用pip方式哪个都稳不慌。最后一个建议做离线部署前一定先写清楚你目标环境的操作系统、架构、Python版本这三件事再去准备安装包。信息越准确后面的意外越少。祝大家都能顺利在内网里把Ansible跑起来彻底摆脱手工批量操作的苦海。
返回列表