跳转到内容

仓库变更控制

在生产环境中,不加控制地直接从公共仓库更新软件包会带来不可预测的风险。仓库变更控制通过冻结仓库快照、搭建本地镜像和建立分阶段测试流程来保证更新的可靠性。

列出所有启用的仓库
dnf repolist
列出全部仓库
dnf repolist all
查看指定仓库的详情
dnf repoinfo baseos
禁用指定仓库
dnf config-manager --disable epel
启用指定仓库
dnf config-manager --enable epel
  • mirrorlist — 从镜像列表服务获取最近的镜像地址,每次可能指向不同的服务器和版本
  • baseurl — 固定指向一个特定的仓库 URL,可确保一致性
查看当前仓库配置
cat /etc/yum.repos.d/almalinux-baseos.repo
固定 BaseOS 仓库到特定镜像
# 备份原始配置
cp /etc/yum.repos.d/almalinux-baseos.repo /etc/yum.repos.d/almalinux-baseos.repo.bak
# 注释掉 mirrorlist,启用 baseurl
sed -i 's/^mirrorlist=/#mirrorlist=/' /etc/yum.repos.d/almalinux-baseos.repo
sed -i 's/^# *baseurl=/baseurl=/' /etc/yum.repos.d/almalinux-baseos.repo

固定到特定版本的仓库(版本快照)

Section titled “固定到特定版本的仓库(版本快照)”

AlmaLinux 和 Rocky Linux 的 vault 仓库保留了历史版本快照。

固定 AlmaLinux BaseOS 到 9.3 版本
cat > /etc/yum.repos.d/almalinux-baseos-frozen.repo << 'EOF'
[baseos-frozen]
name=AlmaLinux 9.3 - BaseOS (Frozen)
baseurl=https://repo.almalinux.org/vault/9.3/BaseOS/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
EOF
固定 Rocky Linux BaseOS 到 9.3 版本
cat > /etc/yum.repos.d/rocky-baseos-frozen.repo << 'EOF'
[baseos-frozen]
name=Rocky Linux 9.3 - BaseOS (Frozen)
baseurl=https://dl.rockylinux.org/vault/rocky/9.3/BaseOS/$basearch/os/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-Rocky-9
EOF

记得禁用原始仓库:

禁用默认仓库,使用冻结版本
dnf config-manager --disable baseos
dnf config-manager --enable baseos-frozen

本地镜像是生产环境仓库控制的最佳实践。

安装仓库同步和创建工具
dnf install -y createrepo_c dnf-plugins-core httpd
创建本地镜像目录
mkdir -p /var/www/html/repos/{baseos,appstream,epel}
同步 BaseOS 仓库
dnf reposync \
--repoid=baseos \
--download-metadata \
--destdir=/var/www/html/repos/baseos \
--newest-only
同步 AppStream 仓库
dnf reposync \
--repoid=appstream \
--download-metadata \
--destdir=/var/www/html/repos/appstream \
--newest-only
创建仓库元数据索引
createrepo_c /var/www/html/repos/baseos/
createrepo_c /var/www/html/repos/appstream/
配置 Apache 提供仓库服务
cat > /etc/httpd/conf.d/repos.conf << 'EOF'
<Directory /var/www/html/repos>
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
EOF
systemctl enable --now httpd
firewall-cmd --permanent --add-service=http
firewall-cmd --reload
在客户端配置使用本地镜像
cat > /etc/yum.repos.d/local-mirror.repo << 'EOF'
[local-baseos]
name=Local Mirror - BaseOS
baseurl=http://repo-server.internal/repos/baseos/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
[local-appstream]
name=Local Mirror - AppStream
baseurl=http://repo-server.internal/repos/appstream/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
EOF
禁用公共仓库,仅使用本地镜像
dnf config-manager --disable baseos appstream
创建仓库同步脚本
cat > /usr/local/bin/sync-repos.sh << 'SCRIPT'
#!/bin/bash
set -e
LOG="/var/log/repo-sync.log"
REPO_BASE="/var/www/html/repos"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] 开始仓库同步" >> "$LOG"
for repo in baseos appstream; do
echo "[$DATE] 同步 $repo ..." >> "$LOG"
dnf reposync \
--repoid="$repo" \
--download-metadata \
--destdir="$REPO_BASE/$repo" \
--newest-only \
--delete >> "$LOG" 2>&1
createrepo_c --update "$REPO_BASE/$repo/" >> "$LOG" 2>&1
done
echo "[$DATE] 仓库同步完成" >> "$LOG"
SCRIPT
chmod +x /usr/local/bin/sync-repos.sh
设置每周日凌晨同步
cat > /etc/cron.d/repo-sync << 'EOF'
0 3 * * 0 root /usr/local/bin/sync-repos.sh
EOF

推荐的更新推进路径:

开发环境 (Dev) → 测试环境 (Staging) → 预生产 (Pre-prod) → 生产 (Production)

每一层使用不同时间点的仓库快照。

创建仓库的时间点快照
SNAPSHOT_DATE=$(date +%Y%m%d)
SNAPSHOT_DIR="/var/www/html/repos/snapshots/$SNAPSHOT_DATE"
mkdir -p "$SNAPSHOT_DIR"
# 使用硬链接创建快照(节省空间)
cp -al /var/www/html/repos/baseos/ "$SNAPSHOT_DIR/baseos"
cp -al /var/www/html/repos/appstream/ "$SNAPSHOT_DIR/appstream"
echo "快照已创建: $SNAPSHOT_DIR"
开发环境使用最新仓库
# Dev: baseurl=http://repo-server.internal/repos/baseos/
生产环境使用经过验证的快照
cat > /etc/yum.repos.d/production.repo << 'EOF'
[prod-baseos]
name=Production BaseOS (Snapshot 20260315)
baseurl=http://repo-server.internal/repos/snapshots/20260315/baseos/
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux-9
EOF
  1. 发现 — 监控上游安全公告和更新
  2. 评估 — 分析更新的影响范围和风险
  3. 测试 — 在开发/测试环境验证
  4. 审批 — 经过变更审批流程
  5. 执行 — 在维护窗口内推送到生产环境
  6. 验证 — 检查服务和功能正常
  7. 记录 — 记录变更内容和结果
生成待更新包的报告
#!/bin/bash
echo "========================================="
echo " 系统更新评估报告"
echo " 主机: $(hostname)"
echo " 日期: $(date)"
echo "========================================="
echo ""
echo "--- 当前系统 ---"
cat /etc/redhat-release
echo "内核: $(uname -r)"
echo ""
echo "--- 可用更新 ---"
dnf check-update 2>/dev/null || true
echo ""
echo "--- 安全更新统计 ---"
dnf updateinfo summary 2>/dev/null
echo ""
echo "--- 安全公告详情 ---"
dnf updateinfo list security 2>/dev/null
记录更新操作到日志
#!/bin/bash
CHANGE_LOG="/var/log/change-management.log"
TICKET_ID="${1:-UNTRACKED}"
echo "==============================" >> "$CHANGE_LOG"
echo "变更工单: $TICKET_ID" >> "$CHANGE_LOG"
echo "操作人员: $(whoami)" >> "$CHANGE_LOG"
echo "操作时间: $(date)" >> "$CHANGE_LOG"
echo "更新前包状态:" >> "$CHANGE_LOG"
rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort >> "$CHANGE_LOG"
echo "==============================" >> "$CHANGE_LOG"
# 执行更新
dnf update -y 2>&1 | tee -a "$CHANGE_LOG"
echo "更新后包状态:" >> "$CHANGE_LOG"
rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}.%{ARCH}\n' | sort >> "$CHANGE_LOG"
查看最近的变更记录
dnf history list
导出某次变更的详细信息
dnf history info <事务ID> > /var/log/change-$(date +%Y%m%d)-txn<事务ID>.log
列出系统中导入的 RPM GPG 密钥
rpm -qa gpg-pubkey* --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n'
导入第三方仓库的 GPG 密钥
rpm --import https://example.com/RPM-GPG-KEY-example
验证 RPM 包签名
rpm -K <包文件名>.rpm
检查已安装包的签名
rpm -qa --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SIGPGP:pgpsig}\n' | head -20