拿到RHEL 9.7的安装介质,很多人第一反应是直接开装。但我在生产环境摸爬滚打这么多年,越来越确信一个观点:真正决定一台Linux服务器后续稳不稳定的,往往不是安装过程本身,而是装之前的方案选型,和装完之后那几天你做了什么。RHEL这类企业发行版,安装只是“地基里的混凝土浇筑”,后续的优化才是“水电管线的排布”,缺了哪一步,后面都要加倍还债。
这篇东西写给两类人看:一类是准备在测试环境熟悉RHEL 9.7、想搞清楚“装完之后到底还要干些啥”的工程师;另一类是已经接到上线任务、正在为生产环境做部署方案的朋友。我会把从镜像选择、分区规划、安装要点、订阅仓库配置、内核参数调优、安全加固,到上线后高频踩坑的完整链路都过一遍,每一处都解释清楚背后的逻辑,而不是只丢给你一串命令。希望能帮你在做方案时少走点弯路。
1. 装机前的版本认知与方案取舍
1.1 RHEL 9.7在9.x家族里的真实位置
先理清一个常见误区:RHEL 9.7不是一套“全新系统”,它是RHEL 9这个主要版本(major release)里的一个更新小版本(minor release)。RHEL 9整个系列都基于Linux 5.14内核,所谓9.7,指的是在5.14内核基础上持续backport(反向移植)安全补丁、硬件驱动、新特性后的第7个更新快照。所以你在9.7上看到的“新”,绝大多数不是内核版本号变了,而是内核里融入了对新CPU、新网卡、新GPU、NVMe硬盘等硬件的更完整支持,以及用户态软件包的整体版本刷新。
那为什么选9.7而不是9.4或者9.5?核心原因是支持生命周期。RHEL每个大版本支持10年(5年全支持+5年维护支持),但小版本就像火车的停靠站,越晚的站点意味着你拥有更长的剩余支持时间。如果你现在部署9.4,那意味着你之后还要经历至少两三次小版本升级才能跟上安全基线;而直接落在9.7上,可以让你的系统在较长时间内保持在一个受支持、且不用频繁跳跃的版本上。对企业环境来说,“能不升级就不升级,要升也要有充分理由”是常态,所以选一个尽量新的小版本作为基线,本身就是一种省事的运维策略。
另外提醒一下:如果你已经有了一台注册了订阅的RHEL 9.4或9.5系统,不需要重装就能升到9.7。小版本之间通过 dnf update 就能平滑滚动上去。大版本间的升级(比如8到9)才需要走Leapp工具,那是另一个故事了。
1.2 镜像变体怎么选:DVD ISO还是Boot ISO
红帽官网提供两种主要安装介质,很多人没细看就随便下了一个,到现场发现不对劲。这两种的选择逻辑其实很直接:
| 镜像类型 | 体积 | 适用场景 | 关键点 |
|---|---|---|---|
| DVD ISO | 10GB以上 | 离线环境、隔离网段、内网机房 | 自带完整软件包仓库,不依赖外网;但每次安装挂载、拷贝都比较费时间 |
| Boot ISO | 几百MB | 有网络仓库可用的环境 | 启动后通过HTTP/NFS等拉取仓库内容,适合批量装机,配合Kickstart效果极佳 |
我做生产环境方案时,如果目标机房能访问公司内部的软件源镜像,我会优先选Boot ISO;如果是完全隔离的涉密网段或者客户现场没有现成仓库,那就直接用DVD ISO离线装。这里有个小技巧:不管用哪种ISO,装完系统后我都建议在本地或内网服务器上再搭建一个RHEL 9.7的仓库镜像,把DVD里的Packages目录同步过去。原因很简单,后续肯定还要装各种软件、打各种补丁,每次都用光驱/挂载ISO非常痛苦,有一个内网源比什么都强。
镜像变体之外,还有一个很现实的问题:选Minimal(最小化)还是Server with GUI(带图形界面)。生产服务器我强烈建议Minimal。你可能会觉得“装个图形界面万一以后要用呢”,但你要为这个“万一”付出的代价是:多几百个安装包、更大的攻击面、更多的内核模块和守护进程,以及偶尔出现的桌面组件安全漏洞。生产服务器不是工作站,用不到的东西不装,就是最好的安全策略。
1.3 手工安装还是Kickstart自动化
单台实验机,手动装没问题;一旦你要部署三五台以上,或者需要反复重建环境,Kickstart的价值就体现出来了。Kickstart本质上是一个安装脚本,把你在图形安装界面里点过的所有选项(分区、软件包、网络、时区、root密码、SSH密钥)全部文本化、参数化。
一个典型的ks.cfg会包含这些核心段落:
code复制# 语言和键盘
lang en_US.UTF-8
keyboard us
# 分区方案
zerombr
clearpart --all --initlabel
part /boot --fstype=xfs --size=1024
part pv.01 --size=1 --grow
volgroup vg_sys pv.01
logvol / --fstype=xfs --name=root --vgname=vg_sys --size=51200
logvol /var --fstype=xfs --name=var --vgname=vg_sys --size=20480
logvol swap --name=swap --vgname=vg_sys --size=8192
# 软件包
%packages
@core
vim-enhanced
%end
# 安装后执行
%post
echo 'tuning...' >> /etc/rc.local
%end
Kickstart最大的优势是“可复现”。你今天手动装出来的系统,和三个月后手动装出来的系统,很可能存在各种细微差异——某个包版本不同、某个配置忘了改。而用Kickstart生成的系统,无论装多少台,结果都是一致的。这也为后续用Ansible等配置管理工具批量交付打了基础。如果你有时间,花半天把Kickstart研究透,后面省下的时间绝对不止半天。
1.4 硬件评估与分区规划:宁大勿小,留足余量
分区规划是安装前最值得花心思的环节。RHEL 9默认使用LVM+XFS的组合,LVM(逻辑卷管理)允许你在物理磁盘上创建逻辑卷,在线扩容非常方便,但有一个硬伤:XFS文件系统不支持缩小。所以分区规划的第一原则是“宁大勿小,留足余量”,尤其是根分区和/var分区。
我给一个可以拿来就用的基准分区方案,适用大多数通用服务器场景:
| 挂载点/卷 | 大小建议 | 说明 |
|---|---|---|
| /boot | 1GB | XFS即可,UEFI启动再加一个/boot/efi(约600MB);内核更新多个版本也不怕满 |
| /(root) | 至少50GB | 系统本身不会占太多,但各种程序、临时文件、容器镜像都会往rootfs里塞 |
| /var | 30~50GB起 | 日志、邮件队列、缓存、容器存储层全在/var里,这是最容易被打爆的目录 |
| /home | 按需 | 如果这台机器只跑业务没用户登录,/home甚至可以只给10GB,或者干脆不独立 |
| swap | 视内存而定 | 如果内存>=16GB且业务对延迟敏感,swap给8GB即可;内存小的话给内存的1~2倍 |
这里特别想强调/var的问题。我见过太多人装系统时只给/和swap,默认把/var也放进root的逻辑卷里。一开始没事,跑了大半年,/var/log或者容器数据把根分区撑满,系统直接进入只读状态,服务全线异常。这种问题在排障时极其头疼,因为df的输出会告诉你根分区100%,但你不一定第一时间想到是/var里的日志在作怪。这个坑,后面详细展开。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 安装过程里最容易翻车的几个环节
2.1 “最小化”不等于“缺东西”,选包时的思路要理清
很多人看到“Minimal”三个字就担心:装完是不是连vim都没有?确实没有。但这不代表你要选那些动不动就几个GB的预定义环境。我的习惯是:安装时选Minimal,然后通过%post脚本或者装完系统后的dnf groupinstall按需补包。
RHEL 9里常用的软件包组包括:
@core:核心基础工具,默认勾选@standard:标准工具集,包含更多运维命令@development:开发工具(gcc、make等),编译软件才需要@headless-management:包含Cockpit等Web管理工具
对于大多数生产服务器,@core+@standard就够起步了。后面需要什么再dnf install什么,干净利落。如果你选了个带GUI的预定义环境,装完系统第一件事多半是dnf remove一堆永远用不到的桌面组件,这不是给自己找事么。
2.2 LVM布局里最常见的失误:给了空间却没留对地方
安装时的“自动分区”功能看起来很省事,但它的默认方案不一定适合你的业务。自动分区通常会把大部分空间都给root逻辑卷,不会单独给/var、/var/log这些容易膨胀的目录规划独立空间。手动分区时需要注意几个细节。
第一,/boot分区要够大。RHEL 9默认的/boot只有1GB左右,看起来够用,但如果你长期不清理旧内核,每次dnf update都会留下一个新内核镜像,反复几次/boot就满了。1GB起步、给到2GB也不过分。
第二,如果你预计这台机器日志量很大(比如跑Web、跑API、跑数据库审计),强烈建议把/var/log或者至少/var单独划一个逻辑卷。这样即使日志打爆了,也只是/var满了,不会拖垮整个系统。
第三,关于swap。很多人沿袭古老的习惯,swap给到内存的两倍。现代服务器内存动辄64GB、128GB甚至更高,给swap划128GB纯属浪费。如果内存足够且业务对延迟敏感,swap给8GB甚至更少都行,关键是设置合理的vm.swappiness(后面调优章节会讲),避免swap被频繁使用。
2.3 root密码的强策略校验与安装后的“第一件事”
Anaconda默认开启了root密码强度校验,你设置一个简单密码(比如123456)时,界面会提示密码过弱。很多人不知道的小技巧是:在密码确认框里连按两次左上角Esc键(或者选择“Done”两次),可以强制跳过弱密码校验,接受你设置的这个弱密码。
但我劝你,除非是几分钟就销毁的临时虚拟机,否则不要用这个“后门”。root密码是系统安全的最后一道防线,弱口令被爆破的代价谁都承担不起。哪怕你用Kickstart部署测试机,也应该在ks.cfg里设置一个符合复杂度要求的密码,或者干脆用SSH公钥认证替代密码登录。
安装完成、重启之后,我建议按这个顺序做第一批操作:
dnf update -y:把系统拉到最新的安全基线- 创建普通用户并加入
wheel组,日常所有操作都用这个用户登录 - 配置SSH公钥登录,关闭root密码登录(至少改为prohibit-password)
- 修改主机名,确认
/etc/hosts里的记录和主机名一致 - 配置时间和时区(
timedatectl set-timezone Asia/Shanghai之类)
顺序有讲究:先打补丁再开服务,避免带着已知漏洞暴露在网络上;先有普通用户再关root登录,避免把自己锁在外面。
2.4 网络配置的持久化:改完IP不生效的奇怪现象
安装过程中设置的IP,装完系统后通常是生效的,但很多人会在后期修改IP时踩坑。RHEL 9默认使用NetworkManager管理网络,它有一个“连接(connection)”的概念。你在安装界面配置的是/etc/NetworkManager/system-connections/下某个连接文件,如果你后续直接用编辑器修改了ifcfg文件或者system-connections里的文件,但没有重启NetworkManager或者重新激活连接,系统不会自动重新读取配置。
正确的做法是用nmcli命令来改:
bash复制# 查看当前连接
nmcli connection show
# 修改IP地址(假设连接名为ens160)
nmcli connection modify ens160 ipv4.addresses 192.168.10.50/24
nmcli connection modify ens160 ipv4.gateway 192.168.10.1
nmcli connection modify ens160 ipv4.dns "192.168.10.1 223.5.5.5"
nmcli connection modify ens160 ipv4.method manual
# 重新激活连接
nmcli connection up ens160
另一个常见问题:如果你创建了一个新的连接,但没有设置autoconnect yes,重启后网卡不会自动拉起,机器直接失联。所以修改网络配置后一定要用nmcli connection up验证一次,并且检查nmcli connection show里该连接的AUTOCONNECT是否为yes。网络问题在机房排障时尤其痛苦,这条我吃了很多次亏。
3. 装完系统后的第一批基础配置
3.1 订阅管理:不注册仓库,系统就是个“半成品”
RHEL和CentOS最大的区别就在这里:RHEL的软件仓库默认是空的,你必须先完成订阅注册,才能从红帽的CDN拉取软件包。没有这一步,dnf install会直接报错,提示“There are no enabled repos”。
注册订阅的标准流程:
bash复制# 使用账号密码注册
subscription-manager register --username 你的账号 --password 你的密码
# 自动订阅匹配的订阅
subscription-manager attach --auto
# 确认已启用仓库
dnf repolist
如果你是个人学习和测试环境,红帽提供免费的开发者订阅(Red Hat Developer Subscription for Individuals),官方支持最多16个节点,对个人使用完全够。注册成开发者订阅后,仓库同样会正常启用,可以正常获取所有软件包更新。
这里有一个很多人容易忽视的操作:注册之后一定要跑一次dnf update,因为9.7仓库里随时可能推送最新的安全补丁。同时确认一下哪些仓库被启用了,比如rhel-9-for-x86_64-baseos-rpms和rhel-9-for-x86_64-appstream-rpms这两个是必须有的。BaseOS提供核心OS组件(内核、系统库),AppStream提供用户态应用(数据库、Web服务器、语言运行时等)。
3.2 EPEL仓库:要不要装,怎么装才安全
EPEL(Extra Packages for Enterprise Linux)是Fedora社区为RHEL系列维护的扩展软件仓库,里面有很多RHEL官方仓库没有的软件包。做运维的几乎都会用到它。
安装方式就是:
bash复制dnf install -y epel-release
但我每次装了EPEL之后都会做一件事:把EPEL仓库设置为默认不启用,需要时手动指定。原因很简单,EPEL里的包有时会和RHEL官方包产生依赖冲突,如果你让它默认启用,哪天一个dnf update把某个包的版本升级到了EPEL侧,可能导致系统里出现一些不兼容。我的做法是:
bash复制# 安装后默认不启用
dnf config-manager --set-disabled epel
# 需要安装某个EPEL包时,临时启用
dnf install --enablerepo=epel 包名
这样既享受了EPEL的软件丰富度,又避免了它干扰官方仓库的依赖解析。
另外,RHEL 9里有一个CRB仓库(CodeReady Builder,对应之前CentOS里的PowerTools),很多编译类软件需要它。同样建议显式启用:
bash复制dnf config-manager --set-enabled crb
不过和EPEL一样,我也倾向于默认不启用,按需指定启用,避免把依赖关系搅乱。
3.3 DNF配置优化:下载提速与内核保留策略
/etc/dnf/dnf.conf值得花两分钟微调一下。我这里给出一个适合大多数场景的配置段,以及每个参数的意义:
ini复制[main]
gpgcheck=1
installonly_limit=3
clean_requirements_on_remove=True
max_parallel_downloads=10
keepcache=1
max_parallel_downloads=10:下载软件包时最多并行拉取10个文件。默认值只有3,内网源或带宽充足时提速明显。keepcache=1:缓存已下载的软件包。好处是出问题时可以离线重装,坏处是占磁盘空间(/var/cache/dnf会越来越大)。我建议测试环境开启,生产环境保持默认的0。installonly_limit=3:系统保留旧内核的数量。内核属于“只安装不升级”的特殊包,每次更新都会新装一个内核镜像,旧的保留在/boot里。这个值控制保留几份,默认3通常够用,频繁升级内核的环境可以调到5。
还有一个容易被忽略的点:RHEL默认使用metalink机制选择最快的CDN节点,所以fastestmirror参数在RHEL上意义不大,不需要像CentOS 7时代那样开启。知道这一点能避免你在网上抄到过时的优化建议。
3.4 时间同步与基础工具链:小事不小
时间同步是被低估的运维基础。RHEL 9默认使用chrony而非ntpd,配置文件是/etc/chrony.conf。装完系统后我会确认一下timedatectl的输出里NTP是active(yes)状态,并检查chronyc sources是否有响应。如果内网有NTP服务器,把pool 2.centos.pool.ntp.org iburst之类的默认池改成内网源,时间同步的精度和稳定性都会更好。
基础工具方面,我个人每次装完必装清单:
bash复制dnf install -y vim-enhanced git lsof tcpdump net-tools sysstat htop wget curl
sysstat提供iostat、sar、pidstat这些性能排查命令,生产环境必备;net-tools提供ifconfig、netstat这些老命令,虽然被ip命令取代了,但很多脚本和排查习惯还是依赖它。这些都装不亏。
4. 内核参数与性能侧的系统调优
4.1 tuned:别自己瞎改,先用现成的“调优套餐”
RHEL自带了一套非常实用的调优工具——tuned。它把常见的性能调优场景抽象成了“profile(配置档)”,每个profile针对一类工作负载,自动调整内核参数、存储IO调度、CPU调度策略等。使用它最大的好处是你不需要记住几十个内核参数的具体含义,就能快速完成80%的基准调优。
bash复制# 查看当前生效的profile
tuned-adm active
# 查看所有可用的profile
tuned-adm list
# 切换profile
tuned-adm profile virtual-guest
我给你一个简单的选型参考:
| 场景 | 推荐profile | 说明 |
|---|---|---|
| 通用虚拟机(VMware/KVM/云主机) | virtual-guest | 针对虚拟化环境优化,这是我最常用的 |
| 物理服务器,追求吞吐 | throughput-performance | 偏重网络和磁盘吞吐 |
| 低延迟金融/交易类应用 | latency-performance | 偏重降低响应延迟 |
| 笔记本/桌面 | balanced | 均衡模式,服务器不常用 |
切换profile后,可以用tuned-adm active确认生效。tuned的设计哲学是“把常见调优选项封装成可切换的配置”,所以在你还没有深刻理解每个内核参数之前,用tuned是比手改/etc/sysctl.conf更安全的选择。
4.2 内核引导参数:哪些值得改,哪些别碰
有些调优项在tuned覆盖不到,需要直接改内核引导参数。这是调优里风险最高的一类操作,因为改错可能导致系统起不来,或者带来安全风险。我给出几个经过实践检验、相对安全的场景化调整思路。
先看怎么查看和修改内核引导参数:
bash复制# 查看当前所有引导参数
grubby --info=ALL
# 为所有内核入口添加参数
grubby --update-kernel=ALL --args="transparent_hugepage=never"
# 移除参数
grubby --update-kernel=ALL --remove-args="transparent_hugepage=never"
常见的值得改的参数:
transparent_hugepage=never:关闭透明大页(THP)。这个在数据库类应用(尤其是Oracle、MySQL)里基本是必改项。THP是为减少TLB开销而设计的,但它会导致内存分配出现性能抖动,数据库场景下弊大于利。像Redis这类对延迟敏感的应用也建议关闭。nowatchdog:关闭软狗(soft lockup watchdog)相关中断。在高并发、CPU密集型的业务中,soft lockup watchdog会周期性打断CPU,关闭它可以在极端压力下减少性能波动。但代价是内核死锁时可能不会及时报警,生产环境要谨慎权衡。- IO调度器的选择。NVMe固态硬盘默认使用
none(即noop),这是正确的,别再改成其他的;机械硬盘(HDD)默认使用mq-deadline,通常也不需要改。除非你有非常特殊的存储场景,否则别动它。
需要特别强调一个参数:mitigations=off,它用来关闭CPU安全漏洞缓解措施,可以明显提升CPU性能(尤其是老CPU),但代价是关闭了Spectre/Meltdown等漏洞的防护。生产环境我坚决反对盲目加这个参数。你的服务器一旦被入侵,别人优先扫描的就是这类系统。性能和安全的优先级,在公网可达的生产环境里永远应该是安全优先。
4.3 sysctl与内存参数:为什么建议别照抄网上的“万能调优”
网上流行一堆“万能sysctl调优配置”,比如vm.swappiness=10、vm.dirty_ratio=5之类。这些参数本身不神秘,问题在于它们各自的适用场景完全不同,照抄容易出问题。
我的建议是只调整你能解释清楚为什么调整的参数。举个最常见的例子:
bash复制# 查看当前值
sysctl vm.swappiness
# 临时修改
sysctl -w vm.swappiness=10
# 永久生效
echo 'vm.swappiness=10' > /etc/sysctl.d/99-performance-tuning.conf
sysctl --system
vm.swappiness控制系统倾向于使用swap的程度,默认值一般是30。数值越大越积极使用swap,数值越小越倾向于保留物理内存。对大多数服务器来说,降到10左右可以避免不必要的swap换页,提高响应稳定性。但如果你的内存本来就小(比如4GB),强行调低反而可能导致OOM Killer频繁触发。所以调参之前先搞清楚自己的内存水位,配合free -h和vmstat观察一段时间再改。
还有一个值得关注的是vm.dirty_ratio和vm.dirty_background_ratio,它们控制脏页写回磁盘的触发时机。默认值在绝大多数场景都够用,不建议为了“调优”而调优。写回策略改得太激进,可能造成大量数据堆积在内存里,一旦断电,数据丢失风险会成倍增加。
4.4 日志与审计的空间防线:journald与auditd
日志管理不算性能调优,但它直接影响系统稳定性。默认情况下,systemd-journald会无限向/var/log/journal写入日志,直到占满所在文件系统。这个设计在生产环境相当危险。我见过太多次根分区被日志打爆的故障,所以装完系统后一定会做两件事。
第一,限制journald的日志大小:
bash复制mkdir -p /etc/systemd/journald.conf.d
cat > /etc/systemd/journald.conf.d/50-size-limit.conf <<'EOF'
[Journal]
SystemMaxUse=500M
MaxRetentionSec=14d
EOF
systemctl restart systemd-journald
这个配置把日志总量限制在500MB,保留14天。既保证了有足够的日志可供排障,又防止它占满磁盘。
第二,确认auditd的日志轮转。/etc/audit/auditd.conf里的max_log_file和num_logs参数控制审计日志的大小和保留份数。如果系统启用了大量SELinux审计、登录审计,日志增长速度会远超预期。建议设置为:
code复制max_log_file = 100
num_logs = 5
也就是单份100MB,最多保留5份轮转。同样的逻辑:审计日志是安全追踪的重要证据,不能无限膨胀也不能直接关闭,合理的轮转策略才是正解。
5. 安全加固里“默认但必须改”的部分
5.1 SELinux:别急着关闭,它是你的免费安全网
RHEL的SELinux默认就是Enforcing(强制)模式。很多Linux老兵从CentOS 6时代就对SELinux“深恶痛绝”,遇到权限问题第一反应是setenforce 0,然后改配置文件永久关闭。这是一个非常危险的习惯。SELinux确实会在你配置Nginx、Redis、自研程序时带来额外的权限限制,你会遇到“明明文件权限都对,服务就是起不来”的怪现象。但绝大多数情况下,这不是SELinux的错误,而是你没有为服务配置正确的SELinux上下文或布尔值。
正确处理SELinux拦截问题,思路是三步走:
- 确认是否真的是SELinux拦截了:
bash复制# 查看最近的AVC拒绝记录
ausearch -m avc -ts recent
- 根据拒绝类型,选择正确的解决方案:
- 端口被拦截:
semanage port -a -t http_port_t -p tcp 8080(允许Nginx监听8080端口) - 文件上下文错误:
restorecon -Rv /data/www(恢复目录的SELinux上下文) - 需要网络访问权限:
setsebool -P httpd_can_network_connect on(允许Apache/Nginx主动发起外连)
- 改完之后再验证服务是否正常。
这套流程走下来,你几乎不用关闭SELinux就能解决99%的问题。SELinux的价值在于:即使攻击者拿到了Web服务的执行权限,SELinux策略依然会限制它读取SSH私钥、连接数据库、执行系统命令。这个纵深防御的层次,是普通文件权限给不了的。
5.2 firewalld:默认拒绝范围之外的流量一律不放行
RHEL 9默认启用firewalld,默认zone是public,行为是“只放行与SSH相关的服务(如果有)”。这是一套比较安全的策略,但很多人在上面叠加业务服务时,习惯性地firewall-cmd --permanent --add-port=8080/tcp,然后reload就完事了。这里我建议你用最小权限原则再审视一遍:
bash复制# 查看当前zone的完整规则
firewall-cmd --list-all
# 只放行特定来源的端口
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="10.0.0.0/8" port port="8080" protocol="tcp" accept'
# 重新加载
firewall-cmd --reload
把端口暴露给全世界和暴露给内网网段,完全是两码事。如果你的服务只给内部系统调用,--add-rich-rule配合source address是更安全的选择。顺带提醒,每次改完防火墙规则,都用firewall-cmd --list-all复查一遍再走。
5.3 SSH加固:最简单也最有效的安全投入
SSH是每台Linux服务器对外的第一道门,也是最容易被暴力破解的目标。加固SSH,我通常做这几件事:
编辑/etc/ssh/sshd_config:
code复制# 禁止root直接用密码登录
PermitRootLogin prohibit-password
# 禁止密码认证,只允许公钥
PasswordAuthentication no
PubkeyAuthentication yes
# 限制登录用户
AllowUsers ops admin
# 限制认证尝试次数,防爆破
MaxAuthTries 3
# 登录超时,空闲自动断开
ClientAliveInterval 300
ClientAliveCountMax 2
改完配置后,一定要先做语法检查再重载:
bash复制sshd -t
systemctl reload sshd
sshd -t是最关键的救命步骤。有一次我在客户现场改完sshd_config,顺手systemctl restart sshd,然后当前连接瞬间断开,新连接又拒绝——原来是我把PermitRootLogin那行写错了导致sshd启动失败。后来养成习惯:所有sshd改动用-t检查,再用reload,reload不会中断现有连接,风险小很多。
如果你担心公网暴力破解,除了MaxAuthTries限制,还可以装fail2ban。但说实话,配合严格防火墙规则+公钥认证后,fail2ban在多数场景下已经不是必需品了。先做好基础的SSH加固,比加多少层额外防护都重要。
5.4 关掉你不会用到的服务,缩小暴露面
装完系统后花十分钟看看有哪些服务在运行:
bash复制systemctl list-units --type=service --state=running
RHEL 9 Minimal装完之后,运行的服务已经很少了,但还会有一些你用不到的:
avahi-daemon:零配置网络发现,服务器环境几乎用不到,可以直接禁用。cups:打印服务,Minimal通常不会有,但如果你误装了带GUI的环境,记得禁用。abrtd:自动错误报告守护进程,如果不想把错误报告发给红帽或本地收集,可以禁用。rpcbind、nfs-client:如果你不跑NFS,这些也没必要常驻。
禁用方式:
bash复制systemctl disable --now avahi-daemon
systemctl mask avahi-daemon
mask比disable更彻底,它会把服务完全锁死,即使别的服务依赖它也无法启动。对于明确不会用的服务,我一般直接用mask。当然,禁用服务前先确认业务没有间接依赖,否则会影响功能。我在生产环境禁用某个服务前,习惯先systemctl status看它是否有依赖关系,再决定是disable还是mask。
6. 上线后运维里最常踩的坑及排查思路
6.1 仓库与订阅过期的连锁故障
现象:某一天dnf makecache突然卡住,或者报错“subscription-manager is not able to connect”。如果你登录上去观察,会看到dnf repolist返回0个仓库,subscription-manager status显示订阅过期。
这一类问题在内网、长期不动的机器上特别容易发生。根因通常是订阅过期或机器失联导致红帽CDN无法验证订阅状态,而RHEL的仓库在订阅过期后会拒绝提供服务。
排查链路:
bash复制# 1. 查看订阅状态
subscription-manager status
# 2. 查看已消耗的订阅
subscription-manager list --consumed
# 3. 重新注册附订阅
subscription-manager register --username ... --password ...
subscription-manager attach --auto
# 4. 确认仓库恢复
dnf repolist
我在一个客户现场排查这个问题时,发现机器已经过了订阅期三个月,期间它一直“工作正常”,因为所有软件包都在本地缓存里,只有执行更新时才暴露问题。这提醒我:生产环境一定要把订阅到期日纳入监控和提醒机制,别等到出故障才想起来。
6.2 journald日志把/var/log塞满的连锁反应
现象:系统开始报“No space left on device”,服务能起但响应异常,df -h显示根分区或者/var分区100%。
最容易忽略的元凶是/var/log/journal。我之前遇到过一次,某个业务模块因为一个代码bug疯狂打日志,journal目录一夜之间涨了30GB,直接把根分区打满。排查方法:
bash复制# 1. 看哪个目录占了很多空间
du -sh /var/log/* | sort -hr | head
# 2. 如果是journal目录,看具体占用
du -sh /var/log/journal/*
# 3. 清理到指定大小
journalctl --vacuum-size=500M
# 4. 或者清理到指定时间
journalctl --vacuum-time=7d
每次遇到类似问题,我都要强调两件事:第一,紧急处理时可以清日志,但清理之后必须找到日志暴涨的根因,否则它还会再涨回来;第二,装系统时就要按前面说的限制journald大小、给/var独立分区,从源头上降低这类故障的发生概率。
6.3 SELinux拦截导致服务启动失败的排查范例
现象:Nginx配置文件无误、监听端口没被占用、firewalld也放行了,但服务就是起不来,或者起来了外部访问不了,而本地curl却正常。
这是一个非常典型的SELinux拦截场景。排查路径:
bash复制# 1. 查看服务状态
systemctl status nginx
# 2. 查看SELinux拦截记录
ausearch -m avc -ts recent
# 3. 看到类似“port 8080”相关的拒绝记录
# 说明SELinux拦截了Nginx监听非标准端口
semanage port -a -t http_port_t -p tcp 8080
# 4. 如果涉及文件目录,恢复上下文
restorecon -Rv /data/www
有一次客户在阿里云上部署一套系统,Nginx无论如何都访问不了,安全组、firewalld都查遍了,最后在audit日志里看到SELinux拒绝nginx监听8080端口。semanage port -a加完,问题立刻解决,全程不到一分钟。所以你遇到服务异常时,别急着关SELinux,先查audit日志,它通常会非常明确地告诉你哪个进程访问什么资源被拒了。
6.4 内核更新后/boot空间不足
现象:执行dnf update时,提示/boot空间不足,内核安装失败,错误信息类似“installing package kernel-core fails”。
原因是/boot分区太小,而每次更新内核都会保留旧版本内核,installonly_limit=3只清理到保留3份旧内核,如果你的/boot只有500MB,装第四个内核时可能就会爆掉。
排查和解决:
bash复制# 1. 查看当前/boot下的所有内核文件
ls -lh /boot/
# 2. 查看当前正在使用的内核版本
uname -r
# 3. 删除所有旧内核(保留当前使用的版本)
dnf remove --oldinstallonly
# 4. 确认/boot空间释放
df -h /boot
dnf remove --oldinstallonly是一个非常方便的命令,它只删除“旧的且不是当前正在使用”的内核。如果/boot不止一次出现这种问题,建议考虑把/boot分区扩到1GB以上,或者定期清理旧内核。
写在最后的一点经验
把整套部署优化流程走下来后,我最想分享的个人心得是:RHEL这类企业发行版,稳定压倒一切。所有调优动作都应该有明确的目标和监控数据支撑,而不是把网上的“优化命令”一次性堆上去。每改一个参数,给系统一段观察期,确认指标确实变好了再持久化;每加一个仓库,先确认它不会破坏现有依赖关系。前期花点时间把Kickstart、订阅注册、基础配置沉淀成脚本化流程,后面每次部署都是一条命令的事情——这才是运维最值得投入的方向。
如果你手头正好要部署RHEL 9.7,建议从第3章的仓库配置和第4章的基础优化开始动手,先把地基打牢,再谈更细的调优。这套流程跑通之后,你会发现所谓“系统优化”不是玄学,而是一套可以逐步积累、不断复用的工程方法论。
