1.1 仓库架构设计
在企业内网或离线环境中,搭建一个私有的YUM仓库至关重要。它能保障软件包来源统一、加快部署速度并提升网络安全性。
推荐架构:互联网仓库同步服务器 → 本地镜像服务器 → 客户端
同步策略:
- 全量同步: 用于基础系统仓库(如
BaseOS),通常每周执行一次。
- 增量同步: 用于更新仓库(如
updates、epel),建议每日执行。
- 选择性同步: 仅同步特定软件包或包组,适用于定制化需求。
1.2 环境要求
确保您的服务器满足以下基础条件,这是高效、稳定运维服务的起点。
# 系统要求
# - CentOS/RHEL 7/8/9 或 Rocky/AlmaLinux
# - 磁盘空间:至少50GB(建议100GB+)
# - 内存:4GB以上
# - 网络:稳定高速互联网连接
# 安装必要工具
sudo yum install -y yum-utils createrepo createrepo_c rsync wget
2. reposync 方法(推荐)
reposync 是 yum-utils 提供的工具,用于完整同步远程仓库的所有软件包,是构建全量镜像站点的首选。
2.1 配置网络仓库
首先,配置好高速的远程仓库源。这里以阿里云镜像站为例。
# 1. 备份原yum源
sudo mkdir -p /etc/yum.repos.d/backup
sudo mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/backup/
# 2. 添加阿里云base源(以CentOS 7为例)
sudo tee /etc/yum.repos.d/aliyun-base.repo << 'EOF'
[aliyun-base]
name=Aliyun Base
baseurl=https://mirrors.aliyun.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
enabled=1
EOF
# 3. 添加阿里云更新源
sudo tee /etc/yum.repos.d/aliyun-updates.repo << 'EOF'
[aliyun-updates]
name=Aliyun Updates
baseurl=https://mirrors.aliyun.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
enabled=1
EOF
# 4. 添加epel源
sudo tee /etc/yum.repos.d/aliyun-epel.repo << 'EOF'
[aliyun-epel]
name=Aliyun EPEL
baseurl=https://mirrors.aliyun.com/epel/$releasever/$basearch/
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/epel/RPM-GPG-KEY-EPEL-7
enabled=1
EOF
# 5. 清理并重建缓存
sudo yum clean all
sudo yum makecache
2.2 同步仓库到本地
使用 reposync 命令将配置好的远程仓库同步到本地目录。
# 1. 创建本地仓库目录结构
sudo mkdir -p /data/yum-repo/{base,updates,epel,extras}
sudo chmod -R 755 /data/yum-repo
# 2. 同步base仓库
sudo reposync --repo=aliyun-base \
--newest-only \
--downloadcomps \
--download-metadata \
--gpgcheck \
-p /data/yum-repo/base
# 3. 同步updates仓库
sudo reposync --repo=aliyun-updates \
--newest-only \
--download-metadata \
-p /data/yum-repo/updates
# 4. 同步EPEL仓库
sudo reposync --repo=aliyun-epel \
--newest-only \
--download-metadata \
-p /data/yum-repo/epel
2.3 创建仓库元数据
同步的RPM包需要生成元数据后,才能被YUM客户端识别和使用。使用 createrepo 命令完成这一步。
# 1. 为base仓库创建元数据
sudo createrepo --update \
--database \
--groupfile=comps.xml \
/data/yum-repo/base
# 2. 为updates仓库创建元数据
sudo createrepo --update \
--database \
/data/yum-repo/updates
# 3. 为epel仓库创建元数据
sudo createrepo --update \
--database \
/data/yum-repo/epel
# 4. 检查仓库结构
tree /data/yum-repo/base -L 2
3. yumdownloader 方法(选择性下载)
如果只需要部分软件包(如特定应用及其依赖),使用 yumdownloader 更为高效。
3.1 下载特定软件包和依赖
# 1. 创建下载目录
mkdir -p /data/yum-repo/custom-packages
cd /data/yum-repo/custom-packages
# 2. 下载软件包及其所有依赖
sudo yum install -y yum-utils
sudo yumdownloader --resolve \
--destdir=/data/yum-repo/custom-packages \
nginx httpd mariadb-server
# 3. 下载特定版本的软件包
sudo yumdownloader --releasever=7 \
--destdir=/data/yum-repo/custom-packages \
nginx-1.20.1
# 4. 下载整个包组的依赖(如开发工具)
sudo yumdownloader --resolve \
--destdir=/data/yum-repo/custom-packages \
"@Development Tools"
3.2 创建自定义仓库
将下载的软件包创建为一个独立的、可被YUM识别的小型仓库。
# 1. 创建仓库元数据
sudo createrepo /data/yum-repo/custom-packages
# 2. 生成GPG密钥(可选)
sudo gpg --gen-key
sudo gpg --export --armor > /data/yum-repo/custom-packages/RPM-GPG-KEY-CUSTOM
# 3. 更新仓库元数据(添加新包时)
sudo createrepo --update /data/yum-repo/custom-packages
4. 自动化同步脚本
手动同步效率低下且易出错,编写自动化脚本是生产环境中的标准做法,这也是自动化运维的重要一环。
4.1 完整同步脚本
此脚本可定期执行(如通过Cron),完成多个仓库的完整同步、元数据更新和旧包清理。
#!/bin/bash
# 文件名:yum-repo-sync.sh
# 功能:自动同步多个YUM仓库并更新元数据
set -e
# 配置变量
REPO_DIR="/data/yum-repo"
LOG_FILE="/var/log/yum-repo-sync.log"
REPOS=("base" "updates" "extras" "epel")
# 创建目录
mkdir -p $REPO_DIR
mkdir -p $(dirname $LOG_FILE)
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG_FILE
}
# 同步函数
sync_repo() {
local repo_name=$1
local repo_id=$2
log "开始同步仓库: $repo_name"
# 同步仓库
reposync --repo=$repo_id \
--newest-only \
--download-metadata \
--downloadcomps \
-p $REPO_DIR/$repo_name \
2>&1 | tee -a $LOG_FILE
# 创建/更新元数据
if [ -f "$REPO_DIR/$repo_name/comps.xml" ]; then
createrepo --update \
--database \
--groupfile=comps.xml \
$REPO_DIR/$repo_name \
2>&1 | tee -a $LOG_FILE
else
createrepo --update \
--database \
$REPO_DIR/$repo_name \
2>&1 | tee -a $LOG_FILE
fi
log "完成同步仓库: $repo_name"
}
# 主函数
main() {
log "开始YUM仓库同步任务"
# 同步所有仓库
sync_repo "base" "aliyun-base"
sync_repo "updates" "aliyun-updates"
sync_repo "epel" "aliyun-epel"
# 清理旧包(保留最近5个版本)
find $REPO_DIR -name "*.rpm" -type f | \
xargs -I {} rpm -qp --queryformat "%{NAME}\n" {} | \
sort | uniq | while read pkg; do
ls -t $REPO_DIR/*/${pkg}*.rpm 2>/dev/null | tail -n +6 | xargs rm -f
done
log "YUM仓库同步任务完成"
}
# 执行主函数
main
4.2 增量同步脚本
相比全量同步,增量同步能极大节省带宽和时间,适合更新频率高的仓库。
#!/bin/bash
# 文件名:yum-repo-incremental.sh
# 功能:增量同步YUM仓库
REPO_DIR="/data/yum-repo"
TEMP_DIR="/tmp/yum-sync-$(date +%s)"
LOCK_FILE="/var/run/yum-repo-sync.lock"
# 创建锁文件,防止并发执行
if [ -f $LOCK_FILE ]; then
echo "另一个同步进程正在运行"
exit 1
fi
touch $LOCK_FILE
trap "rm -f $LOCK_FILE; rm -rf $TEMP_DIR" EXIT
# 创建临时目录
mkdir -p $TEMP_DIR
# 同步新包
for repo in base updates epel; do
echo "同步 $repo 仓库的更新..."
# 获取当前仓库中所有RPM包的列表
find $REPO_DIR/$repo -name "*.rpm" -exec basename {} \; | sort > $TEMP_DIR/local_$repo.txt
# 同步仓库(只下载新包)
reposync --repo=aliyun-$repo \
--newest-only \
--download-metadata \
-p $TEMP_DIR/$repo
# 找出新下载的包
find $TEMP_DIR/$repo -name "*.rpm" -exec basename {} \; | sort > $TEMP_DIR/new_$repo.txt
# 移动新包到本地仓库
comm -13 $TEMP_DIR/local_$repo.txt $TEMP_DIR/new_$repo.txt | while read pkg; do
mv $TEMP_DIR/$repo/$pkg $REPO_DIR/$repo/
echo "新增: $pkg"
done
# 更新仓库元数据
createrepo --update $REPO_DIR/$repo
done
# 清理
rm -rf $TEMP_DIR
5. 配置本地HTTP服务
本地仓库需要通过HTTP或FTP协议发布。使用Nginx是性能优异且配置简单的选择。
5.1 使用Nginx提供仓库服务
# 1. 安装Nginx
sudo yum install -y nginx
# 2. 配置Nginx
sudo tee /etc/nginx/conf.d/yum-repo.conf << 'EOF'
server {
listen 80;
server_name yum-repo.local;
root /data/yum-repo;
autoindex on;
autoindex_exact_size off;
autoindex_localtime on;
location / {
try_files $uri $uri/ =404;
}
# 防止访问上级目录
location ~ /\. {
deny all;
}
# 设置缓存头
location ~ \.(rpm)$ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
# 多个仓库虚拟主机配置(可选)
server {
listen 8080;
server_name base-repo.local;
root /data/yum-repo/base;
autoindex on;
}
server {
listen 8081;
server_name updates-repo.local;
root /data/yum-repo/updates;
autoindex on;
}
EOF
# 3. 设置SELinux(如启用)
sudo setsebool -P httpd_enable_homedirs 1
sudo chcon -R -t httpd_sys_content_t /data/yum-repo
# 4. 启动Nginx
sudo systemctl enable nginx
sudo systemctl start nginx
# 5. 防火墙规则
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
5.2 使用Apache提供仓库服务
# 1. 安装Apache
sudo yum install -y httpd
# 2. 配置Apache
sudo tee /etc/httpd/conf.d/yum-repo.conf << 'EOF'
Alias /yum-repo /data/yum-repo
<Directory "/data/yum-repo">
Options Indexes FollowSymLinks
IndexOptions FancyIndexing NameWidth=* DescriptionWidth=* HTMLTable
AllowOverride None
Require all granted
# 设置RPM文件的MIME类型
AddType application/x-rpm .rpm
# 设置缓存
<FilesMatch "\.(rpm)$">
Header set Cache-Control "max-age=2592000, public"
</FilesMatch>
</Directory>
EOF
# 3. 启动Apache
sudo systemctl enable httpd
sudo systemctl start httpd
6. 客户端配置
内网中的其他服务器需要配置为使用这个新建的本地仓库。
6.1 配置客户端使用本地仓库
# 1. 创建本地仓库配置文件
sudo tee /etc/yum.repos.d/local.repo << 'EOF'
[local-base]
name=Local Base Repository
baseurl=http://yum-server-ip/base
gpgcheck=1
gpgkey=http://yum-server-ip/base/RPM-GPG-KEY-CentOS-7
enabled=1
priority=1
[local-updates]
name=Local Updates Repository
baseurl=http://yum-server-ip/updates
gpgcheck=1
gpgkey=http://yum-server-ip/updates/RPM-GPG-KEY-CentOS-7
enabled=1
priority=1
[local-epel]
name=Local EPEL Repository
baseurl=http://yum-server-ip/epel
gpgcheck=1
gpgkey=http://yum-server-ip/epel/RPM-GPG-KEY-EPEL-7
enabled=1
priority=1
EOF
# 2. 备份并禁用外部仓库
sudo mkdir -p /etc/yum.repos.d/backup
sudo mv /etc/yum.repos.d/CentOS-*.repo /etc/yum.repos.d/backup/ 2>/dev/null || true
sudo mv /etc/yum.repos.d/epel*.repo /etc/yum.repos.d/backup/ 2>/dev/null || true
# 3. 清理缓存
sudo yum clean all
# 4. 测试本地仓库
sudo yum repolist
sudo yum check-update
6.2 使用NGINX代理多个仓库源
在混合云或复杂网络环境中,可以使用Nginx作为代理,智能分发请求。
# 当需要同时使用本地和外部仓库时
upstream aliyun_base {
server mirrors.aliyun.com:443;
}
upstream local_base {
server 192.168.1.100:80;
}
server {
listen 80;
server_name proxy-repo.local;
location /centos/$releasever/os/$basearch/ {
proxy_pass https://aliyun_base/centos/$releasever/os/$basearch/;
proxy_set_header Host mirrors.aliyun.com;
}
location /local/base/ {
alias /data/yum-repo/base/;
autoindex on;
}
}
7. 高级功能实现
7.1 仓库镜像和缓存(Squid)
对于拥有大量客户端的大型环境,可以部署Squid作为缓存代理,进一步减少外网流量并加速客户端下载。
# 1. 安装Squid
sudo yum install -y squid
# 2. 配置Squid作为YUM缓存代理
sudo tee /etc/squid/squid.conf << 'EOF'
http_port 3128
cache_dir ufs /var/spool/squid 5000 16 256
acl localnet src 192.168.0.0/16
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 443 # https
http_access allow localnet
http_access deny all
# YUM仓库缓存设置
refresh_pattern ^http://mirrors\.aliyun\.com/.*\.rpm$ 129600 100% 129600 override-expire
refresh_pattern ^https://mirrors\.aliyun\.com/.*\.rpm$ 129600 100% 129600 override-expire
cache_mem 256 MB
maximum_object_size 1024 MB
EOF
# 3. 启动Squid
sudo systemctl enable squid
sudo systemctl start squid
# 4. 客户端配置使用代理
sudo tee /etc/yum.conf << 'EOF'
[main]
cachedir=/var/cache/yum/$basearch/$releasever
keepcache=0
debuglevel=2
logfile=/var/log/yum.log
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
installonly_limit=5
proxy=http://squid-server:3128
EOF
7.2 仓库监控和告警
确保本地仓库的健康和可用性是运维核心工作。以下脚本提供了基本的监控点。
#!/bin/bash
# 仓库监控脚本
# 监控仓库状态
check_repo_health() {
local repo_url=$1
local repo_name=$2
# 检查仓库可访问性
if ! curl -s --head $repo_url/repodata/repomd.xml | grep "200 OK" > /dev/null; then
echo "CRITICAL: 仓库 $repo_name 不可访问"
return 1
fi
# 检查仓库完整性
if ! curl -s $repo_url/repodata/repomd.xml | grep -q "primary.xml.gz"; then
echo "WARNING: 仓库 $repo_name 元数据不完整"
return 2
fi
# 检查仓库更新时间
last_update=$(stat -c %Y /data/yum-repo/$repo_name/repodata/repomd.xml)
now=$(date +%s)
diff=$((now - last_update))
if [ $diff -gt 86400 ]; then # 超过24小时未更新
echo "WARNING: 仓库 $repo_name 超过24小时未更新"
return 3
fi
echo "OK: 仓库 $repo_name 状态正常"
return 0
}
# 监控磁盘空间
check_disk_space() {
local threshold=90 # 百分比
local usage=$(df /data | awk 'NR==2 {print $5}' | sed 's/%//')
if [ $usage -gt $threshold ]; then
echo "CRITICAL: 磁盘使用率 ${usage}% 超过阈值 ${threshold}%"
return 1
fi
echo "OK: 磁盘使用率 ${usage}%"
return 0
}
# 发送告警
send_alert() {
local message=$1
local level=$2
# 发送邮件(需要配置邮件服务器)
echo "$message" | mail -s "[$level] YUM仓库告警" admin@example.com
# 发送到监控系统(如Zabbix)
# zabbix_sender -z zabbix-server -k yum.repo.status -o "$message"
}
# 主监控函数
main() {
repos=(
"http://localhost/base Base仓库"
"http://localhost/updates Updates仓库"
"http://localhost/epel EPEL仓库"
)
for repo in "${repos[@]}"; do
url=$(echo $repo | awk '{print $1}')
name=$(echo $repo | awk '{print $2}')
check_repo_health "$url" "$name"
done
check_disk_space
}
# 定期执行
main
7.3 使用Pulp管理仓库
对于超大规模或需要精细权限、生命周期管理的企业环境,可以考虑使用 Pulp 这类专业的仓库管理软件。
# Pulp是专业的仓库管理工具,适合大型环境
# 1. 安装Pulp 3(仅CentOS 8/RHEL 8)
sudo dnf install -y pulpcore python3-pulpcore
# 2. 初始化数据库
sudo -u pulp python3-django-admin migrate --noinput
# 3. 启动服务
sudo systemctl enable pulpcore-api pulpcore-content pulpcore-worker
sudo systemctl start pulpcore-api pulpcore-content pulpcore-worker
# 4. 创建仓库
pulp rpm repository create --name centos-8-base
# 5. 同步远程仓库
pulp rpm remote create \
--name centos-8-base-remote \
--url https://mirrors.aliyun.com/centos/8/BaseOS/x86_64/os/ \
--policy immediate
pulp rpm repository sync \
--name centos-8-base \
--remote centos-8-base-remote
8. 性能和优化
8.1 优化同步性能
# 1. 使用并行下载(需要axel)
sudo yum install -y axel
# 修改reposync脚本使用axel
reposync --repo=aliyun-base \
--downloadcomps \
--download-metadata \
-p /data/yum-repo/base \
--norepopath \
--download_path=/data/yum-repo/base \
--config=/etc/yum.repos.d/aliyun-base.repo
# 2. 配置yum下载加速
sudo tee /etc/yum.conf << 'EOF'
[main]
cachedir=/var/cache/yum/$basearch/$releasever
keepcache=1
debuglevel=2
logfile=/var/log/yum.log
exactarch=1
obsoletes=1
gpgcheck=1
plugins=1
installonly_limit=5
# 下载优化
minrate=1
timeout=300
retries=10
EOF
8.2 磁盘优化
# 1. 使用XFS文件系统(对大文件友好)
sudo mkfs.xfs /dev/sdb
sudo mkdir -p /data/yum-repo
sudo mount -o noatime,nodiratime /dev/sdb /data/yum-repo
# 2. 配置LVM以便扩展
pvcreate /dev/sdb
vgcreate yum_vg /dev/sdb
lvcreate -L 200G -n yum_repo yum_vg
mkfs.xfs /dev/yum_vg/yum_repo
mount /dev/yum_vg/yum_repo /data/yum-repo
# 3. 定期清理旧包
find /data/yum-repo -name "*.rpm" -mtime +180 -delete
9. 故障排查
9.1 常见问题解决
# 问题1:reposync下载失败
# 解决方案:
# 检查网络连接
ping mirrors.aliyun.com
# 检查仓库配置
yum repolist
# 临时禁用GPG检查
reposync --repo=aliyun-base --nogpgcheck -p /data/yum-repo
# 问题2:createrepo失败
# 解决方案:
# 检查磁盘空间
df -h
# 检查文件权限
ls -la /data/yum-repo/base/
# 重新创建元数据
rm -rf /data/yum-repo/base/repodata
createrepo /data/yum-repo/base
# 问题3:客户端无法访问
# 解决方案:
# 测试HTTP访问
curl -I http://yum-server/base/repodata/repomd.xml
# 检查防火墙
sudo firewall-cmd --list-all
# 检查SELinux
sudo getsebool -a | grep httpd
sudo setsebool -P httpd_can_network_connect on
9.2 调试命令
# 查看仓库详细信息
yum repoinfo local-base
# 检查仓库元数据完整性
ls -la /data/yum-repo/base/repodata/
# 查看同步日志
tail -f /var/log/yum-repo-sync.log
# 测试特定软件包
yum --disablerepo="*" --enablerepo="local-base" list available
# 检查仓库统计
repomanage --old /data/yum-repo/base | wc -l
repomanage --new /data/yum-repo/base | wc -l
10. 最佳实践建议
10.1 维护策略
同步策略:
- 定时增量同步: 每日凌晨2-4点执行增量同步。
- 定期全量同步: 每周末执行一次全量同步,确保元数据健康。
- 紧急更新: 对于重大安全更新(如内核漏洞),应立即手动触发同步。
存储策略:
- 版本保留: 保留最近3个月的所有版本,保留最近1年的主要版本。
- 定期清理: 定期清理旧内核包和无用依赖。
备份策略:
- 配置备份: 每日备份仓库服务器上的
/etc/yum.repos.d/ 和同步脚本。
- 元数据备份: 每周备份各仓库的
repodata 目录。
- 全量备份: 每月对
/data/yum-repo 目录进行一次全量备份。
10.2 安全建议
# 1. 使用HTTPS
# 配置Nginx使用SSL
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout /etc/nginx/ssl/yum-repo.key \
-out /etc/nginx/ssl/yum-repo.crt
# 2. 访问控制
# 配置Nginx基础认证
sudo htpasswd -c /etc/nginx/.htpasswd username
# 3. 监控异常访问
# 配置日志分析
sudo tee /etc/logrotate.d/nginx-yum << 'EOF'
/var/log/nginx/yum-access.log {
daily
rotate 30
compress
delaycompress
notifempty
create 644 nginx nginx
}
EOF
10.3 扩展架构
对于跨国或大型企业,可考虑以下扩展架构:
多级缓存架构:
总部中心镜像 → 区域/分公司镜像 → 部门/项目组本地缓存 → 最终客户端
负载均衡方案:
- 部署多个镜像服务器,通过DNS轮询或负载均衡器(如
HAProxy、Nginx)分发客户端请求。
- 对于公网分发,可结合CDN服务。
高可用方案:
- 采用主备模式的镜像服务器,通过
rsync 或 DRBD 实时同步数据。
- 配置虚拟IP(VIP),结合
Keepalived 实现自动故障切换。