
1. 部署方案设计与事前规划1.1 部署需求与镜像准备RHEL 9.7这个版本说新不新说旧不旧但对于生产环境来说选它做承载业务的操作系统底座稳定性是有保障的。我这次是在一套物理服务器上做全新部署配置是Intel Xeon 双路CPU、128GB内存、2块1TB NVMe SSD做RAID1网络是双千兆网卡绑定。整体思路很明确装一台干净的最小化系统然后在上面做一轮初始化优化让它达到能直接上生产的标准。准备工作第一步是拿ISO镜像。如果你有Red Hat订阅直接去官方门户下载没有订阅也可以用开发者订阅注册一下就能获得免费授权。拿到镜像之后先校验一下SHA256不要省这一步我曾经遇到过下载损坏的镜像装到一半报错白白浪费了半小时。用命令sha256sum rhel-9.7-x86_64-dvd.iso把输出值和官网的值比对没问题再开始做启动盘。制作启动盘我推荐用Ventoy比dd直接写入更方便能直接在U盘里放多个ISO启动时自己选。物理机如果支持UEFI用Rufus或者Ventoy都行注意分区格式选GPT。1.2 分区方案与安装方式抉择分区是安装阶段最需要想清楚的事。RHEL 9.7默认的自动分区对生产环境不够理想它会把所有空间都分给根分区看起来省事但后面日志暴涨或者容器镜像堆积的时候根分区一旦写满系统直接进入只读状态服务全部被拖死。我见过不止一次这种事故一台跑监控的服务器/var目录被历史告警日志撑爆应用起不来查了半天才发现是分区规划的问题。我的推荐方案是手动分区用LVM管理分区/逻辑卷建议大小挂载点文件系统说明/boot1GB/bootxfs引导分区放内核和grub/50GB/xfs系统本身和/usr等/var100GB/varxfs日志、缓存、邮件队列等都用它/home50GB/homexfs用户数据隔离根分区风险swap16GBswapswap跟内存大小相关见下文剩余全部——/dataxfs业务数据落盘的位置swap分区大小这个事128GB内存的机器到底分多少老规矩说swap是内存的两倍但现在的服务器内存动不动64G起步两倍根本不合理。我个人的习惯是内存小于8GB的机器swap分2倍内存内存16GB到64GBswap分16GB内存超过64GBswap可以控制在16GB以内甚至某些纯计算节点不配swap也行。原因是内存够大的情况下swap大量使用反而拖慢性能系统频繁换页IO负载直接拉高。分一个兜底的16GB是防止某些应用突发内存占用把OOM Killer触发起来误杀关键进程。安装方式上单台机器不需要上Kickstart手工安装就行。如果你是要批量部署二十台以上的同配置机器那强烈建议用Kickstart加PXE网络安装能省掉大量重复劳动。这次是单台部署我直接走的图形安装界面注意在安装时要选的软件包集合选Minimal Install最小化安装等装完再按需装东西。最小化安装的好处是少了很多用不到的系统组件磁盘占用小、暴露的攻击面少、启动也快符合生产环境一贯瘦身的原则。2. 系统初始化与基础环境配置2.1 主机名、网络与时间设置装完系统重启进命令行第一件事是确认基础信息没有配置错位。主机名要跟业务规划对应别用默认的localhost。我自己用hostnamectl设置hostnamectl set-hostname node01.example.local hostnamectl status改完主机名后旧终端里提示符可能还是localhost重新登录一次或者执行exec bash刷新即可。另外/etc/hosts里最好把主机名和IP对应关系加上避免部分服务做地址反查时解析不到白白拖慢连接建立速度。网络配置这块RHEL 9.7默认用NetworkManager管理网络。我见过不少老运维打开/etc/sysconfig/network-scripts/ifcfg-ens192就直接改文件里写IP、掩码、网关然后重启网卡发现完全不生效。这不是你写错了而是RHEL 9系列里NetworkManager接管了所有网络配置的激活权限手动改ifcfg文件后必须通过nmcli重新加载才能生效。正确做法是用nmclinmcli connection modify ens192 ipv4.method manual ipv4.addresses 192.168.10.20/24 ipv4.gateway 192.168.10.1 ipv4.dns 223.5.5.5 8.8.8.8 ipv4.dns-search example.local nmcli connection up ens192如果你要做双网卡绑定用nmcli创建bond类型连接把两块物理网卡作为port加入就行这里不展开生产环境中链路聚合建议用mode4LACP协议需要交换机配合配置。时间同步必须在系统装完就处理否则日志时间和业务时间对不上排障的时候痛苦指数飙升。RHEL 9.7自带chrony我的配置习惯是这样vim /etc/chrony.conf # 添加国内可用的时间服务器 server ntp.aliyun.com iburst server time1.aliyun.com iburst server time.cloud.tencent.com iburst # 允许系统时钟漂移修正 makestep 1 3改完重启chronyd并确认同步状态systemctl restart chronyd chronyc sources -v chronyc tracking能看到System time的偏移量在毫秒级以内说明时间同步正常工作。同步时间这个问题故障隐蔽但影响范围极大比如数据库主从复制是基于时间戳的时间一偏复制直接出乱子日志审计定位安全事件时时间错乱会导致证据链断裂。所以这一步务必做扎实。2.2 dnf源配置与基础工具补齐RHEL 9.7默认的软件源指向Red Hat的CDN如果你的机器能访问外网并且已用subscription-manager注册直接就能用。但很多生产环境处于内网隔离区没有外网访问权限这种情况下有两条路可以选。第一条路在内网搭一套本地仓库镜像把Red Hat源、EPEL源镜像下来客户端配置repo地址指向内网服务器。这个方案灵活但需要一台维护成本。第二条路直接用安装光盘做本地方源简单粗暴mkdir -p /mnt/cdrom mount -o loop /dev/sr0 /mnt/cdrom cat /etc/yum.repos.d/local.repo EOF [local-baseos] nameLocal BaseOS baseurlfile:///mnt/cdrom/BaseOS enabled1 gpgcheck0 [local-appstream] nameLocal AppStream baseurlfile:///mnt/cdrom/AppStream enabled1 gpgcheck0 EOF dnf clean all dnf makecache光盘上的BaseOS和AppStream两个源能覆盖绝大部分系统基础软件包但像nginx、redis这类第三方软件就不够了。如果需要可以再从EPEL源下载相关rpm包传到内网装。EPELExtra Packages for Enterprise Linux是Fedora社区维护的扩展仓库RHEL 9对应epel-9版本配置方式dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm装完基础源之后我习惯把一批通用工具先装上这是从多年运维经验里总结出的标配dnf install -y vim wget curl telnet lsof tree net-tools bind-utils tar unzip gdisk pciutils sysstat iotop htop psmisc lrzsz dnf groupinstall -y Development ToolsDevelopment Tools这个组包里面有gcc、make、git等编译链工具后续如果要在机器上编译安装软件就离不开它们。sysstat提供sar、iostat、mpstat这些性能采集命令生产环境排障必备。3. 系统优化细节从装完变成能用3.1 内核参数调整策略RHEL 9.7装完默认的内核参数是兼容模式很多参数按最保守的方式设置对于业务服务器来说太浪费。我做的内核优化核心思路是不要照抄网上的性能调优大集合而是根据这台机器将来跑什么业务来选参数。举个例子机器将来主要跑Web服务和数据库读写那网络栈和文件系统相关的参数优先调整如果只是做内部监控采集内核参数几乎不需要动。我在/etc/sysctl.conf里添加了这样一组参数# 降低swap使用倾向优先用物理内存 vm.swappiness 10 # 增加单个进程允许的最大文件句柄数 fs.file-max 2097152 # 网络连接队列相关应对短连接高并发 net.core.somaxconn 65535 net.ipv4.tcp_max_syn_backlog 65535 net.ipv4.ip_local_port_range 1024 65535 net.ipv4.tcp_tw_reuse 1 net.ipv4.tcp_fin_timeout 30 # 脏页回写策略减少突发IO保证数据安全 vm.dirty_ratio 30 vm.dirty_background_ratio 5逐个说下为什么这么配。vm.swappiness设成10物理内存128GB的机器平时几乎用不到swap设置太低比如0或1的话有些内存回收机制可能在特殊场景下反而出问题10是个兼顾稳妥和性能的值。net.core.somaxconn和tcp_max_syn_backlog关系到高并发连接的排队能力如果你的服务用Nginx做反向代理这两个值调大后突发流量来临时不会因为半连接队列溢出而丢请求。ip_local_port_range扩大到1024到65535是因为大量短连接场景下源端口不够用系统会报Cannot assign requested address这个经典错误。tcp_tw_reuse这个参数争议比较大内核文档里明确说在NAT环境下慎用因为TIME_WAIT状态的连接如果被复用而TCP序号又恰好冲突可能造成数据错乱。我自己的经验是纯内网、无NAT、服务端和客户端都在可控范围内的场景开启没有问题跨公网的场景就关掉它用调整tcp_fin_timeout代替。调优没有一揽子方案必须结合网络拓扑判断。配置写完后执行sysctl -p重载再用sysctl -a | grep net.core.somaxconn确认生效。另外注意一点容器场景下内核参数不能只改宿主机例如podman容器内部读到的somaxconn值受宿主机netns和容器netns隔离机制影响如果是host网络模式则直接继承宿主机参数bridge模式需要单独调优。这个坑后文会提到。3.2 用户级资源限制与systemd限额文件描述符的限制是另一个高频坑点。默认情况下进程的文件句柄上限是1024生产环境完全不够用。你只要遇到过Java应用报Too many open files或者数据库连接池大一点服务起不来你就知道这个参数有多重要。修改方式有几种传统做法是改/etc/security/limits.confcat /etc/security/limits.conf EOF * soft nofile 65535 * hard nofile 65535 * soft nproc 65535 * hard nproc 65535 EOF但注意这种方式对登录会话有效对systemd托管的服务不一定生效。RHEL 9.7上很多服务是用systemd unit管理的必须单独设置服务文件的LimitNOFILE属性。比如调整sshd服务mkdir -p /etc/systemd/system/sshd.service.d cat /etc/systemd/system/sshd.service.d/limits.conf EOF [Service] LimitNOFILE65535 EOF systemctl daemon-reload systemctl restart sshd确认进程实际生效值cat /proc/$(pgrep -u root sshd | head -1)/limits | grep open files如果输出是65535说明改成了。很多人在limits.conf里改了但发现不生效十有八九就是没查systemd层面的限制这两个层级并不是简单的继承关系各自有独立默认值都得配。3.3 日志管理与journald瘦身RHEL 9.7的日志系统继承了systemd时代的journald同时保留rsyslog。默认配置下journald会无限积累系统日志长期运行下来journal目录能占到几GB甚至几十GB磁盘空间。这不是危言耸听我处理过一次故障一台跑了大半年的机器/var/log/journal占了37GB终端操作都卡顿根因就是journald默认上限是磁盘空间的10%磁盘越大日志攒得越狠。因此我调整了journald配置vim /etc/systemd/journald.conf # 关键参数 SystemMaxUse1G MaxRetentionSec30d RuntimeMaxUse256MSystemMaxUse指持久化日志放在/var/log/journal最多占1GB超过这个量系统会自动清理最老的日志。MaxRetentionSec是保留30天对大多数业务排查场景够了审计要求高的系统可以适当调大但配合SystemMaxUse一起看。改完重启journald生效systemctl restart systemd-journald日志轮转这块如果还用rsyslog处理特定应用日志/etc/logrotate.d下的规则也要检查一遍比如nginx的access.log默认按天轮转但如果你调整了日志格式或者增加输出量轮转频率也要同步调整。我的习惯是把重要业务日志通过rsyslog单独写到独立目录配好logrotate避免全部堆在/var/log/messages里messages这种汇总日志一旦被占满很多应用的写日志操作直接阻塞。4. 安全加固与日常运维底座4.1 SELinux策略选择与排错SELinux是每个RHEL运维都绕不开的话题。社区里有一种声音是装完直接setenforce 0省心我强烈建议不要在生产环境这样做。SELinux的设计初衷是强制访问控制就算进程被攻破也只能在受限域内活动不能越权访问其他资源。关闭它是图一时省事但把系统的纵深防御拆掉了一面。我见过一个最新最典型的场景一台跑Nginx的RHEL 9.7机器管理员给Nginx配置了一个非标准端口8443来对外的业务结果防火墙放行了、selinux状态也是Enforcing可服务就是访问不了。查日志才看到日志里面明确写着类型为httpd_t的进程访问端口被SELinux拦了原因是SELinux针对端口定义了一个类型上下文默认只有80、443等标准端口允许监听非标准的需要手动加白。处理方式很简单semanage port -l | grep http semanage port -a -t http_port_t -p tcp 8443同理如果你的Web服务要连接后端的3306端口但SELinux布尔值没打开httpd_can_network_connect也会被拦截。排查这类问题我的习惯步骤如下先看SELinux日志grep -i selinux /var/log/messages | tail -20 ausearch -m avc -ts recent有AVC拒绝记录时使用audit2why解析ausearch -m avc -ts recent | audit2why输出会直接告诉你哪个布尔值没开哪个端口没放照做即可。对业务上确实需要放宽的项用setsebool -P打持久化标记重启不会丢失。在生产环境里真正需要setenforce 0的情况基本是第三方闭源软件没有适配SELinux上下文、或者新装好的系统在做POC验证时间紧想先跑通功能。这种时候我的建议也是先用permissive模式而不是直接disabled。permissive模式下SELinux策略不会阻止操作但会把违规行为全部记录到日志里你可以根据日志追查问题最后还是要切回enforcing。我记得很清楚有一次把一个数据采集程序从permissive切到enforcing后网络连接直接失败查日志才发现它调用的一个共享库需要访问/var/tmp下的临时文件SELinux上下文件类型不对我把文件放到了允许访问的目录顺手修了这个潜在问题。4.2 SSH安全加固与防火墙配置SSH是Linux服务器的生命线也是最常被暴力扫描的攻击目标。RHEL 9.7默认的sshd配置还算规整但还是有几个点必须强化。第一禁止root远程登录。root账号密码一旦被爆破成功就等于把整个系统的钥匙交出去了。合理做法是用普通用户登录需要提权时用sudo。编辑/etc/ssh/sshd_config找到PermitRootLogin项改成no。如果你确认只有固定运维IP会连这台机器可以配合Match Address限定来源IPMatch Address 10.10.0.0/16 PermitRootLogin no第二优先使用密钥认证替代密码认证。把公钥复制到服务器后在sshd_config里设置PasswordAuthentication no。切换之前千万确认无论普通用户还是root钥匙都能正常登录否则你把自己锁在门外就只能去物理控制台捞人了。第三改SSH默认端口的问题。有人认为改端口是调优刚需我个人的习惯是对内网服务器默认22没问题内网一般有防火墙ACL控制对公网暴露的机器改端口确实能挡住大量批量扫描流量但要注意SELinux和firewalld双保险都要带上。改端口不是安全方案的全部还得配合fail2ban做暴力破解拦截。fail2ban在EPEL源里有装完配置好sshd的jail五分钟内同一IP连续失败三次以上就临时封禁效果立竿见影。防火墙方面RHEL 9.7默认启用firewalld管理命令是firewall-cmd。最小化安装后默认只放行ssh端口我的配置习惯是先把默认区改成dropfirewall-cmd --set-default-zonedrop firewall-cmd --reload systemctl enable firewalld --now默认区改成drop意味着所有未显式放行的流量直接丢弃比默认的public区仅放行少量服务更严格。然后按需放行端口firewall-cmd --permanent --zonepublic --add-port443/tcp firewall-cmd --permanent --zonepublic --add-port3306/tcp firewall-cmd --reload firewall-cmd --list-all注意firewall-cmd加--permanent是写配置不加则是临时规则但如果只做临时放行没有--permanent服务器一重启就丢了。这个细节踩过坑的人才会记得住。4.3 系统软件更新与自动安全补丁策略补丁管理是生产环境的核心问题。很多运维不重视系统装完就放那儿跑三年不更新直到被漏洞打穿才追悔莫及。RHEL 9.7默认支持dnf-automatic可以设置自动下载并安装安全补丁。但我不建议设置成全自动毫无提醒尤其是对企业级数据库、核心业务服务所在节点某个内核补丁自动装上重启之后服务起不来造成的损失比漏洞攻击还大。我的方案是配置dnf-automatic只自动下载不自动安装配合监控检查更新情况dnf install -y dnf-automatic vim /etc/dnf/automatic.conf # 修改如下 downstream_method dnf apply_updates no emit_via motdapply_updates设成no系统会定时下载更新但不会自动装然后通过/run/motd.d系通知你有哪些更新可以装。我每周一看一次更新列表dnf check-update --security评估安全补丁级别测试服务器先装、验证通过后再滚动到生产节点。这样既不冒进也不放任兼顾安全性和稳定性。日常巡检我还习惯用systemctl status排查异常服务、ss -lntp查看端口监听情况配合前文提到的sysstat工具定期抓取CPU、内存、磁盘IO基线数据这些数据可以在问题发生时快速定位异常点。你自己心里要有一条基线线比如这台机器平时CPU使用率一般不超过20%某天突然涨到80%还持续稳定那十有八九有异常进程或者部署了新的定时任务没评估好资源占用。运维里面设备健康检查做得好故障引发的救火次数会大幅减少。5. 常见问题与踩坑记录实际部署过程中有几类问题是反复出现的我按现象-原因-处理整理成表方便你对照排查现象根因处理方法用nmcli配置静态IP后外网不通没设置正确的DNS或者网卡连接没有激活成功nmcli connection modify后必须up再ping测试服务监听非标准端口外网访问不了firewalld没放行该端口firewall-cmd --permanent --add-port8443/tcpreloadNginx/Node服务启动失败日志无异常SELinux阻止绑定非标准端口semanage port -a -t http_port_t -p tcp 8443应用报Too many open fileslimits.conf没生效或systemd LimitNOFILE未配置同时检查/etc/security/limits.conf和unit文件dnf安装报warning: gpg key older than file本地方源GPG校验问题和源包时间戳异常内网本地方源设置gpgcheck0或导入新版GPG key重启后静态IP丢失NetworkManager没启用或连接没有autoconnectnmcli connection modify ens192 connection.autoconnect yes时间漂移导致数据库主从告警chrony服务没启动或防火墙拦了UDP 123端口systemctl enable --now chronyd检查UDP 123放行根分区被/var/log/journal占满journald默认无上限占用磁盘配置SystemMaxUse限制定期journalctl --vacuum-size500M再单独说两个我这次部署中真实踩到的坑很有代表性。第一个坑是网卡的命名问题。RHEL 9.7在部分服务器上网卡的名称不是传统的eth0而是根据BIOS槽位生成的enp3s0、ens192这种命名。老运维写脚本时还按eth0、eth1去匹配结果脚本完全失效。我的建议是所有涉及网卡名的脚本、服务配置用nmcli确认实际名称后统一改成变量别在脚本里硬编码。如果你实在需要传统命名安装时在内核启动参数里加一个biosdevname0或net.ifnames0RHEL 9.7上这个参数依然有效但注意这会影响系统初始化的网络链路顺序尽量在装机阶段定好后面改容易引起混乱。第二个坑是systemd服务的资源上限。用systemd托管一个高并发的Java应用时我按照老经验修改了limits.conf的nofile和nproc结果应用照样报文件句柄不够。排查了很久才发现问题出在Java服务unit的文件里systemd对这个服务有自己独立的限制在service文件里加[Service] LimitNOFILE1048576 LimitNPROC65536然后daemon-reload重启服务才彻底解决。这个问题比较典型RHEL 9系列对systemd的服务隔离做得彻底修改limits.conf已经管不到systemd管理的进程了必须每个unit单独设置。这也是RHEL 9和旧版本一个很大的运维习惯差异。6. 优化效果与后续扩展思路写这篇记录的时候系统已经稳定运行了一段时间。部署完成时我用脚本做了一轮基本检查sshd正常监听、firewalld规则齐备、SELinux处于Enforcing且无风险告警、chrony时钟偏差低于1ms、journald日志占控在1GB以内、原生资源限制全部落实。内网压测的结果Nginx短连接QPS比默认配置下提升大约是30%到40%注意这只是一个参考数据具体提升幅度跟业务场景关系极大——如果你的瓶颈在应用代码本身内核参数调优能带来的提升微乎其微这也是为什么我一直强调先搞清楚瓶颈在哪再动参数别照抄任何调优清单。整个部署流程走下来最有价值的经验其实是RHEL这种企业级系统安装只是起点优化成一套适合你自己业务的底座才是关键。装完系统就丢到机架上不管和花半天时间做初始化配置后续维护成本能差出一大截。建议你在做完一轮配置后顺手做个记录文档把每个参数为什么这么设写清楚。一两个月后再回看你会有新的理解这些理解才是运维经验真正沉淀下来的部分。如果你想在更多机器上复现这套配置下一步值得投入的方向是自动化把分区的kickstart文件、post-install的初始化脚本、sysctl的配置模板都固化下来用Ansible把上面所有步骤写成playbook新机器一键部署效率和一致性都能大幅提升。RHEL 9.7对Red Hat Ansible Automation Platform原生支持很好跑这套方案运维成本会显著下降。