1. 为什么需要本地DNF仓库与NFS共享
在企业级Linux运维场景中,软件包管理和文件共享是两个高频需求。传统方式直接连接互联网仓库存在三个痛点:一是外网依赖导致安装速度不稳定,二是大量主机重复下载消耗带宽,三是内网隔离环境无法访问外部源。我曾为某金融客户部署测试环境时,50台主机同时拉取OpenJDK导致外网带宽瞬间占满,触发了公司网络告警。
本地DNF仓库的价值在于:
- 依赖解析加速:基于libsolv的依赖分析比传统YUM快3-5倍
- 版本控制:可冻结特定版本软件包(如锁定Python3.6)
- 离线可用:军工、银行等隔离环境的核心需求
而NFS共享则解决了:
- 集群配置同步:如Kubernetes所有节点的/etc/kubernetes配置同步
- 日志集中存储:将/var/log通过NFS挂载到日志服务器
- 开发协作:团队共享代码目录避免重复传输
2. DNF仓库部署实战
2.1 基础环境准备
推荐使用CentOS 8+或openEuler系统,最小化安装后执行:
bash复制# 禁用现有仓库
sudo mv /etc/yum.repos.d/* /tmp/
# 安装必要工具
sudo dnf install -y createrepo_c dnf-plugins-core httpd
sudo systemctl enable --now httpd
2.2 仓库目录结构设计
建议采用分层存储策略:
code复制/srv/repos
├── baseos # 系统基础包
├── epel # 第三方扩展包
├── custom # 自编译包
└── metadata # 仓库元数据
初始化仓库示例:
bash复制sudo mkdir -p /srv/repos/baseos/{Packages,repodata}
sudo createrepo_c /srv/repos/baseos
2.3 仓库配置文件详解
创建/etc/yum.repos.d/local.repo:
ini复制[baseos-local]
name=Local BaseOS
baseurl=file:///srv/repos/baseos
enabled=1
gpgcheck=0
priority=1
# 可选HTTP访问方式
[baseos-http]
name=HTTP BaseOS
baseurl=http://$SERVER_IP/baseos
关键参数解析:
priority=1:优先于网络仓库metadata_expire=3600:元数据缓存时间(秒)skip_if_unavailable=True:仓库不可用时跳过而非报错
2.4 仓库同步策略
推荐使用reposync进行增量同步:
bash复制dnf reposync --repoid=epel --download-metadata \
-p /srv/repos/epel --delete --remote-time
可设置cronjob每日同步:
bash复制0 3 * * * root /usr/bin/dnf reposync --repoid=epel -p /srv/repos/epel -q
3. NFS服务深度配置
3.1 服务端优化配置
安装必要组件:
bash复制sudo dnf install -y nfs-utils libnfsidmap
sudo systemctl enable --now rpcbind nfs-server
配置文件/etc/exports示例:
code复制/srv/shared 192.168.1.0/24(rw,sync,no_root_squash,no_subtree_check)
/data 192.168.1.100(rw,async) 192.168.1.200(ro)
关键参数说明:
sync:写入操作同步到磁盘(数据安全)async:异步写入(性能优先)no_wdelay:禁用写延迟(适用于SSD存储)insecure_locks:兼容旧版NFS客户端
3.2 性能调优技巧
修改/etc/nfs.conf:
ini复制[nfsd]
threads=16
tcp=y
vers4.2=y
[exportfs]
manage-gids=y
内核参数优化:
bash复制echo 65536 > /proc/sys/fs/nfs/nlm_udpport
sysctl -w sunrpc.tcp_slot_table_entries=64
3.3 客户端挂载最佳实践
推荐挂载参数:
bash复制mount -t nfs -o \
rw,nosuid,nodev,noexec,hard,intr,rsize=65536,wsize=65536,timeo=600,retrans=3 \
nfs-server:/srv/shared /mnt/nfs
/etc/fstab示例:
code复制nfs-server:/data /mnt/data nfs defaults,_netdev,noatime 0 0
4. 故障排查手册
4.1 DNF常见问题
问题1:依赖解析失败
bash复制# 查看详细依赖树
dnf repoquery --requires --resolve <package>
# 清理缓存重建
dnf clean all
rm -rf /var/cache/dnf
问题2:仓库签名校验失败
bash复制# 临时禁用校验
dnf install --nogpgcheck <package>
# 永久配置
echo "gpgcheck=0" >> /etc/dnf/dnf.conf
4.2 NFS排错指南
症状:mount卡住无响应
bash复制# 检查服务端端口
rpcinfo -p nfs-server
# 强制卸载
umount -lf /mnt/nfs
# 查看NFS版本支持
nfsstat -m
日志分析:
bash复制journalctl -u nfs-server --since "1 hour ago"
tail -f /var/log/messages | grep nfsd
5. 安全加固方案
5.1 DNF仓库安全
-
GPG签名验证:
bash复制rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS dnf config-manager --setopt=gpgcheck=1 -
访问控制:
apache复制# /etc/httpd/conf.d/repos.conf <Directory "/srv/repos"> Require ip 192.168.1.0/24 Options Indexes </Directory>
5.2 NFS安全实践
-
防火墙规则:
bash复制
firewall-cmd --add-service={nfs,rpc-bind,mountd} firewall-cmd --runtime-to-permanent -
SELinux策略:
bash复制setsebool -P nfs_export_all_rw 1 semanage fcontext -a -t public_content_rw_t "/srv/shared(/.*)?"
6. 生产环境部署建议
6.1 高可用架构
DNF仓库HA方案:
- 使用DRBD+Keepalived实现存储层冗余
- 通过rsync每小时同步仓库数据到备用节点
- 配置DNS轮询实现负载均衡
NFS集群方案:
- 后端采用GlusterFS分布式存储
- 前端通过HAProxy实现NFS网关负载均衡
- 使用CTDB管理IP故障转移
6.2 监控指标
关键监控项包括:
-
DNF仓库:
bash复制# 仓库响应时间 curl -o /dev/null -s -w '%{time_total}\n' http://repo/test # 存储空间预警 df -h /srv/repos -
NFS服务:
bash复制# 连接数监控 nfsstat -c # IO性能分析 iostat -x 1 | grep nfs
7. 进阶应用场景
7.1 与CI/CD集成
在Jenkins中配置自动更新仓库:
groovy复制pipeline {
stages {
stage('Update Repo') {
steps {
sh '''
cp target/*.rpm /srv/repos/custom/Packages
createrepo_c --update /srv/repos/custom
'''
}
}
}
}
7.2 容器化部署
使用Podman运行NFS服务器:
bash复制podman run -d --name nfs-server \
-v /srv/shared:/exports \
-p 2049:2049 \
-e SHARED_DIRECTORY=/exports \
docker.io/itsthenetwork/nfs-server-alpine
在Kubernetes中通过PVC挂载:
yaml复制apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
nfs:
server: nfs-server-ip
path: "/srv/shared"
通过三年在银行系统的部署经验,我总结出两个黄金法则:一是所有仓库变更必须先在测试环境验证,二是NFS挂载必须使用hard+intr参数避免应用卡死。某次升级glibc时因未充分测试导致生产环境批量故障,这个教训让我至今在每个变更窗口都保持高度警惕。
