资讯详情

资讯详情

内网环境自建Yum仓库实战:从原理到多机共享

1. 项目缘起与整体设计思路1.1 为什么内网环境必须自建软件仓库很多刚接触Linux运维的朋友会有一个思维惯性装软件不就是敲一条yum install的事吗在能直连外部镜像源的机器上确实如此但一旦进入企业内网、生产隔离区或者实验室的封闭集群这条路就直接被堵死了。我最早接手的一批服务器全部位于无外网出口的网段几十台机器要统一装监控代理、批量升级基础库、部署内部工具链如果还靠U盘一台台拷rpm包手动rpm -ivh那基本等于把自己埋进依赖地狱里。自建yum仓库解决的正是这个核心痛点把散落的rpm包集中管理让内网所有机器像访问公网源一样用yum或dnf自动解析依赖、自动下载安装。它带来的价值不只是能装软件而是版本可控、依赖可解、批量可复制。你可以把仓库理解成一个内部应用商店管理员负责上架客户端只管下单中间不需要每台机器都去理解依赖树。这个项目适合三类人参考一是刚入行的Linux运维需要一套能直接落地的内网源方案二是负责实验室或小集群的技术人员想摆脱手动装包的重复劳动三是有一定基础、想搞清楚yum底层工作机制的开发者。整套方案我会从原理讲到实操从单机仓库讲到多机共享参数和命令都给全照着做就能跑通。1.2 方案选型httpd、nginx还是file协议搭建yum仓库的本质是让客户端能通过某种协议读取到仓库的元数据repodata和rpm包。常见的承载方式有三种我先把选型逻辑讲清楚避免你上来就选错方向。承载方式适用场景优点局限file://本地路径单机自用、临时测试零配置不需要服务无法被其他机器访问http协议httpd/nginx内网多机共享通用性强客户端配置简单需要额外起一个Web服务ftp协议老旧环境兼容部分老系统默认支持配置繁琐逐渐被淘汰我的建议很直接只要涉及两台以上机器一律上http方式。file协议虽然省事但它把仓库锁死在本机失去了共享这个最核心的意义。ftp在早期RHEL5/6时代常见现在新环境基本不用考虑。http服务里httpdApache和nginx都能胜任纯静态文件分发场景下两者性能差异可以忽略选你更熟的那个就行。我个人习惯用httpd因为它在RHEL/CentOS系里是亲儿子配置目录结构清晰排错时日志也直观。还有一个容易被忽略的选型点仓库放本地磁盘还是网络存储。如果rpm包总量不大几个GB以内直接放服务器本地盘最稳如果包量巨大、还要多台仓库服务器同步那就要考虑NFS或对象存储挂载。我这次演示用的是本地盘方案简单可靠适合绝大多数中小规模场景。1.3 整体架构与数据流向把架构想清楚后面每一步操作你都知道自己在干什么。整个yum仓库系统由两部分组成仓库服务端和客户端。服务端负责三件事存放rpm包、生成repodata元数据、通过http把目录暴露出去。客户端要做的只有一件在/etc/yum.repos.d/下写一个.repo文件告诉yum仓库地址在哪、叫什么名字、是否校验签名。数据流向是这样的客户端执行yum install xxxyum先读取.repo文件拿到baseurl然后去请求repodata/repomd.xml这个文件是元数据的索引里面记录了primary、filelists、other等各个数据库文件的位置和校验值。yum下载这些元数据到本地缓存在内存里构建出包名-版本-依赖-文件路径的关系图解析出需要安装哪些包最后按baseurl拼出rpm的实际下载地址逐个拉取并安装。理解了这个流程你就能明白为什么改了rpm包必须重新生成repodata——因为元数据是独立于rpm包存在的你往目录里丢新包repomd.xml并不会自动更新客户端看到的还是旧索引。这是新手最容易踩的坑后面我会专门讲。2. 核心细节解析与实操要点2.1 环境准备与基础依赖确认动手之前先把环境摸清楚能省掉后面一大堆莫名其妙的报错。我这次用的是一台内网服务器系统是RHEL/CentOS 7系的衍生版本IP假设为192.168.10.20主机名repo-server。你换成自己的实际地址即可命令里的路径和IP都要对应调整。第一步确认系统版本和架构因为仓库目录通常要按系统版本架构分层存放混放会导致客户端拉到不兼容的包cat /etc/redhat-release uname -m输出会告诉你类似CentOS Linux release 7.9和x86_64。记住这两个信息后面建目录要用。如果你的环境是RHEL 8/9系命令基本一致只是包管理器默认从yum变成了dnf但dnf完全兼容yum的仓库配置.repo文件写法一模一样不用担心。第二步确认httpd是否已安装。很多最小化安装的系统是不带Web服务的rpm -q httpd如果提示package httpd is not installed那就装。这里有个前提你的仓库服务器本身得能访问到软件源否则连httpd都装不上。如果服务器也是纯内网那就需要先用系统安装镜像ISO挂载出一个临时本地源把httpd和createrepo装进去。挂载ISO的方法mkdir -p /mnt/cdrom mount -o loop /path/to/system.iso /mnt/cdrom然后临时写一个指向file:///mnt/cdrom的repo文件就能用yum装包了。这一步是先有鸡还是先有蛋的经典问题很多内网新手卡在这里记住用ISO做跳板就行。2.2 关键工具createrepo的作用与安装整个仓库搭建里createrepo是绝对的核心工具没有它你放的rpm包就只是一堆文件yum根本不认识。它的作用就是扫描指定目录下的所有rpm包读取每个包的头部信息包名、版本、依赖关系、提供的能力、包含的文件列表然后生成一套结构化的XML元数据统一放在repodata/目录下。安装它yum install -y createrepo装完后可以用createrepo --version确认。这里要提醒一点不同系统版本对应的createrepo版本不同生成的元数据格式也有细微差异。RHEL 8/9系推荐用createrepo_cC语言重写版速度更快命令名可能是createrepo_c但用法和createrepo完全一致。如果你在8系上执行createrepo提示找不到命令试试createrepo_c。注意createrepo只负责生成元数据它不会去校验rpm包本身是否完整、依赖是否齐全。也就是说你放进去一个缺依赖的包createrepo照样能生成元数据但客户端安装时会报依赖错误。所以入库前的包质量把关得靠人工或额外脚本。2.3 仓库目录结构的设计原则目录结构设计得好后期维护省一半力气。我的习惯是按用途系统版本架构三层来分比如/var/www/html/repo/ ├── base/ │ └── 7/ │ └── x86_64/ ├── extras/ │ └── 7/ │ └── x86_64/ └── custom/ └── 7/ └── x86_64/base放系统基础包extras放额外工具custom放自己打的内部包。这样分的好处是客户端可以按需只启用某几个仓库不会因为一个仓库出问题影响全部后期扩容或迁移时按目录整体搬走就行。为什么不把所有包堆在一个目录因为createrepo每次生成元数据都要扫描全目录包越多越慢。而且一旦某个包损坏导致元数据生成失败整个仓库都受影响。分目录能把故障域隔离。当然如果你包量很小几十个图省事放一个目录也无可厚非但养成分类习惯没坏处。目录建好后把rpm包拷进去。拷包的方式看你的包来源从ISO提取、从其他机器scp、从内部制品库下载都行。拷完记得ls | wc -l数一下数量心里有个底。3. 实操过程与核心环节实现3.1 服务端从零生成仓库元数据假设rpm包已经放进了/var/www/html/repo/custom/7/x86_64/现在生成元数据createrepo /var/www/html/repo/custom/7/x86_64/执行完你会看到目录下多了一个repodata/文件夹里面有几个.xml.gz和.xml文件。这就是元数据。第一次生成会稍慢包越多越明显。如果后续往目录里加了新包必须重新生成而且要用--update参数它只处理新增和变化的包比全量重建快得多createrepo --update /var/www/html/repo/custom/7/x86_64/实操心得我见过太多人加了包直接yum install然后纳闷为什么找不到包。原因就是忘了--update。养成习惯——只要动了rpm目录就立刻createrepo --update可以写成一个别名或小脚本减少遗忘。生成完检查一下repodata/repomd.xml是否存在且非空ls -lh /var/www/html/repo/custom/7/x86_64/repodata/如果这个文件是0字节或者不存在说明生成失败通常是目录权限问题或磁盘满了看命令输出里的报错信息定位。3.2 服务端配置httpd暴露仓库目录httpd默认的网站根目录就是/var/www/html所以只要把仓库放在这个目录下理论上启动httpd就能访问。但为了规范我建议单独写一个配置文件而不是去改主配置。在/etc/httpd/conf.d/下新建repo.confAlias /repo /var/www/html/repo Directory /var/www/html/repo Options Indexes FollowSymLinks AllowOverride None Require all granted /DirectoryOptions Indexes的作用是允许目录浏览这样你在浏览器里访问仓库地址时能看到文件列表方便排查。Require all granted是放行所有访问内网环境够用如果对安全有更高要求可以限制来源网段。配置写好后启动并设置开机自启systemctl start httpd systemctl enable httpd然后验证。先在服务器本机用curl测curl -I http://192.168.10.20/repo/custom/7/x86_64/repodata/repomd.xml返回HTTP/1.1 200 OK就说明Web服务正常。如果返回403多半是SELinux在拦临时用setenforce 0测试确认是SELinux问题后再去配布尔值或上下文别直接永久关闭SELinux那是运维大忌。3.3 客户端编写repo文件并验证客户端这边进入/etc/yum.repos.d/新建custom.repo[custom] nameInternal Custom Repository baseurlhttp://192.168.10.20/repo/custom/7/x86_64/ enabled1 gpgcheck0逐行解释[custom]是仓库ID必须唯一name是描述随便写但要有意义baseurl指向repodata的上一级目录注意结尾的斜杠不能少少了有时会解析异常enabled1表示启用gpgcheck0表示不校验包签名。关于gpgcheck这里展开说一下。生产环境建议开启签名校验防止包被篡改但需要你导入对应的GPG公钥gpgkey指向公钥地址。内部自制的包如果没签名就只能设gpgcheck0。这是个安全与便利的权衡内网可信环境下关掉可以接受但心里要清楚风险。配好后清理缓存并验证yum clean all yum repolistrepolist会列出所有启用的仓库及其包数量。如果custom仓库显示包数量为0说明元数据没读到回去检查baseurl路径和httpd访问。如果显示正常数量就可以测试安装了yum install -y 你的包名3.4 多仓库与优先级管理实际环境里往往不止一个仓库比如系统基础源、内部工具源、自研包源同时存在。这时候包名冲突就可能出现——同一个包在多个仓库里都有yum该选哪个yum的默认策略是选版本最高的但有时候你希望优先用内部源。这时可以用priority插件需要装yum-plugin-priorities在repo文件里加一行priority1数字越小优先级越高范围1到99。给内部源设1给外部源设99就能保证优先用内部包。这个细节在混合源环境里非常关键我踩过一次坑内部源里有个定制版的工具包结果被外部源里版本号更高的同名包覆盖了排查半天才发现是优先级问题。另一个技巧是用includepkgs和excludepkgs做包级别的过滤比如某个仓库只想提供特定几个包includepkgsnginx,redis这样即使仓库里有几百个包客户端也只认这两个能有效避免意外引入不需要的包。4. 常见问题与排查技巧实录4.1 元数据相关故障速查元数据问题是yum仓库最高频的故障来源我把典型现象和排查路径整理成表遇到问题直接对号入座。现象可能原因排查与解决repolist显示包数为0元数据未生成或路径错检查repodata目录是否存在baseurl是否指向正确层级报错Cannot retrieve repomd.xmlhttp服务不通或路径404curl测试URL检查httpd状态和SELinux报错repomd.xml signature could not be verifiedgpgcheck开启但无有效签名设gpgcheck0或正确导入gpgkey新加的包找不到忘记createrepo --update重新生成元数据后yum clean all报错Metadata file does not match checksum元数据与包不一致或缓存脏yum clean all清缓存重试这张表基本覆盖了八成以上的元数据故障。我的经验是遇到问题先yum clean all再yum repolist很多缓存导致的假故障一清就好。如果还不行再逐层往上查客户端网络→http服务→目录权限→元数据文件。4.2 依赖地狱的预防与处理自建仓库最头疼的不是搭仓库本身而是依赖完整性。你从某台机器上拷了几个rpm包放进仓库客户端一装就报缺少依赖xxx。这是因为rpm包之间有复杂的依赖关系单独拷几个包往往凑不齐依赖链。预防办法有两个。第一尽量从完整的系统ISO或官方源里提取包它们的依赖关系是经过验证的。第二用yumdownloader工具连同依赖一起下载yumdownloader --resolve --destdir/tmp/pkgs 包名--resolve会自动把该包的所有依赖一并下载到指定目录然后你把整个目录的包一起入库依赖就齐了。这个命令在准备离线包时简直是神器强烈建议掌握。如果已经出现依赖缺失用yum deplist 包名可以列出该包的所有依赖再逐个确认仓库里有没有。缺哪个补哪个补完记得createrepo --update。避坑技巧入库前用rpm -qpR 包名.rpm快速查看单个包的依赖列表批量检查可以写个循环脚本遍历目录。提前发现缺依赖比客户端报错后再回头补要高效得多。4.3 权限、SELinux与防火墙三座大山内网服务搭不起来十有八九栽在这三样上。我按排查顺序说。权限httpd进程默认以apache用户运行它需要对仓库目录有读和执行权限。如果目录是root建的且权限是700httpd就读不到。解决chmod -R 755 /var/www/html/repo chown -R root:root /var/www/html/repo755对仓库目录足够不需要给写权限因为写操作是你手动做的不是httpd做的。SELinux这是最隐蔽的坑。即使文件权限对了SELinux也可能因为安全上下文不对而拒绝httpd访问。检查ls -Z /var/www/html/repo如果上下文不是httpd_sys_content_t用chcon或semanage修正semanage fcontext -a -t httpd_sys_content_t /var/www/html/repo(/.*)? restorecon -Rv /var/www/html/reposemanage方式更规范因为它写入策略重启后依然生效chcon是临时的重启可能失效。防火墙确认80端口放行firewall-cmd --permanent --add-servicehttp firewall-cmd --reload三样都确认后客户端访问基本就通了。我的排查口诀是先curl本机再curl远程先关SELinux测试再查防火墙逐层缩小范围比盲目重启服务高效得多。4.4 仓库扩容与日常维护建议仓库不是搭完就一劳永逸的日常维护有几个点要注意。第一定期清理无用包。时间久了仓库里会堆积大量旧版本包既占空间又拖慢createrepo。可以按修改时间清理或者用repomanage工具来自yum-utils自动保留最新N个版本repomanage --keep3 --old /var/www/html/repo/custom/7/x86_64/这条命令会列出除最新3个版本外的旧包确认无误后加| xargs rm -f删除再createrepo --update。第二元数据生成脚本化。手动敲命令容易忘写个脚本把拷包→createrepo→清缓存串起来每次入库跑一遍规范又省心。第三多仓库服务器同步。如果有多台仓库服务器做冗余可以用rsync同步rpm目录和repodata注意同步后客户端要yum clean all刷新缓存。同步时建议先同步rpm包再同步repodata避免客户端读到元数据说有包但包还没到的中间状态。第四监控仓库可用性。写个简单的健康检查定时curl一下repomd.xml返回非200就告警。仓库挂了会导致所有客户端装不了包属于基础设施级别的重要服务值得监控。我个人在实际维护中最大的体会是仓库的规范性比技术难度更重要。目录分层、命名统一、入库流程固定这些看似琐碎的规矩在包数量涨到几百上千之后会决定你是从容维护还是焦头烂额。刚开始多花十分钟设计结构后面能省几十个小时的排查时间。另外每次改动仓库后务必在一台测试客户端上验证一遍再全量推广这个习惯帮我挡掉过好几次元数据没更新就上线的低级事故。
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →