Nginx 生产环境平滑升级实战:从 1.24.0 到 1.28.0 的零宕机操作全记录

在生产环境中升级 Nginx 一直是运维人们最谨慎的操作之一,因为它通常直接暴露在公网,承载着大量的流量,任何一点宕机或配置错误都可能造成业务影响。本文记录了一次真实的线上 Nginx 升级过程:从 1.24.0 升级到 1.28.0 ,全程实现零宕机,并且采用最安全的"二进制文件替换"方式,避免在生产机器上编译。

一、背景与环境

  • 机器信息:CentOS 7(内核 3.10),源码编译安装的 Nginx

  • binary 路径 :/usr/local/nginx/sbin/nginx

  • 配置路径 :/etc/nginx/(配置文件为 /etc/nginx/nginx.conf)

  • 当前版本:nginx/1.24.0

  • 目标版本:nginx/1.28.0

  • 运行方式 :手动启动(非 systemd 管理),但进程手动启动也长期正常运行

  • 特点:无第三方动态模块,编译参数相对简单

二、为什么选择"只替换 binary"的方式?

常见的 Nginx 升级方式有三种:

  1. 直接在生产机源码编译 + make install

    风险:需要安装开发工具、下载源码、长时间编译,万一依赖缺失或编译失败,可能影响运行中的服务。

  2. 使用 yum/apt 等包管理升级

    不适用:本机为源码安装,无 RPM 包。

  3. 在测试机编译新 binary,只拷贝可执行文件替换 (本次采用)

    优点:

    • 生产机几乎不执行高风险操作
    • 只传输一个几 MB 的二进制文件
    • 支持 Nginx 官方推荐的热二进制替换,实现真正零宕机
    • 保持原有配置、日志、权限完全不变nginx文档

三、升级全过程详解

步骤 1:备份(永远的第一步)

在生产机上备份旧 binary:

bash 复制代码
cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx-v1.24.0

步骤 2:获取当前编译参数(最关键!)

javascript 复制代码
# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.24.0
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --user=nginx --group=nginx --prefix=/usr/local/nginx --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --with-pcre-jit --with-http_ssl_module --with-http_v2_module --with-http_sub_module --with-stream --with-stream_ssl_module

输出中重点复制 configure arguments 那一长串(包括 --prefix=/usr/local/nginx),确保新版本用完全相同的参数编译,否则可能缺少模块或路径不一致。

步骤 3:在测试机编译新版本(环境需一致)

选择一台系统、gcc 版本、库版本相近的测试机。

bash 复制代码
cd /tmp
wget https://nginx.org/download/nginx-1.28.0.tar.gz
tar zxvf nginx-1.28.0.tar.gz
cd nginx-1.28.0

./configure [粘贴上面完整的 configure arguments]

make -j$(nproc)    # 快速并行编译(后面的nproc是指最多用多少个核心去编译,如果不写似乎默认是1)

关键提醒 :不要执行 make install!

编译完成后,新 binary 位于:

bash 复制代码
./objs/nginx

验证版本:

bash 复制代码
./objs/nginx -v
# 输出:nginx version: nginx/1.28.0

步骤 4:传输并替换生产机 binary

bash 复制代码
# 从测试机拷贝到生产机的 /tmp
scp objs/nginx root@生产机IP:/tmp/nginx

# 生产机上替换
cd /usr/local/nginx/sbin
mv /tmp/nginx ./
# 直接覆盖或先备份旧的后再 mv
chmod 755 nginx

步骤 5:验证配置与版本

bash 复制代码
/usr/local/nginx/sbin/nginx -t
# 输出 syntax is ok 和 test is successful

/usr/local/nginx/sbin/nginx -V
# 确认显示 nginx/1.28.0,且 configure arguments 与之前一致

步骤 6:平滑重载(零宕机升级)

bash 复制代码
/usr/local/nginx/sbin/nginx -s reload

原理:Nginx master 进程收到 reload 信号后,会启动新的 worker 进程(使用新 binary),旧 worker 处理完当前连接后自动退出,整个过程无连接中断。

在这一步其实只是用了新的worker,而nginx的架构是master+worker的,但是master的话只是负责读取和校验配置文件、绑定 80/443 等特权端口、创建、管理、监控 worker 进程等,实际上几乎不占资源,如果要重载master的话,可以进行重启操作:

shell 复制代码
$/usr/local/nginx/sbin/nginx -s quit

# 等待一段时间,等到nginx相关进程全部停下来,除了 grep 本身,什么都不应该有
$ps -ef | grep nginx

# 重启nginx
$/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf

四、背后的核心原理

  1. Nginx 的 master-worker 架构

    master 进程负责读取配置、管理 worker;worker 负责实际处理请求。reload 时 master 启动新 worker,旧 worker 优雅退出。

  2. 二进制热替换支持

    Nginx 在启动时会将自身可执行文件路径记录下来。即使你替换了磁盘上的 binary 文件,正在运行的 master 进程仍使用旧的内存镜像。但 reload 后,新 worker 会加载新的 binary,从而实现版本升级。

  3. 为什么只换 binary 就行?

    Nginx 的模块大部分是静态编译进 binary 的(本次无动态模块)。只要编译参数一致,新 binary 就能完美适配原有配置和路径。

五、收尾与建议

  • 观察 /var/log/nginx/error.log 一段时间,确保无异常
  • 可选:切换为 systemd 管理,便于开机自启和统一操作
  • 保留旧 binary 至少一周,以备回滚

六、总结

这次升级全程不到 20 分钟,服务无任何感知,真正实现了生产环境的平滑升级。核心经验就是:

  • 备份永远第一位
  • 编译参数必须一模一样(尤其是 --prefix)
  • 优先选择"只替换 binary"的最小侵入方式
  • 利用 Nginx 自身平滑重载机制实现零宕机

这种方法特别适合老旧生产环境、源码安装、无包管理的场景咯

相关推荐
姜鱼问生5 小时前
每次开机手动检查 6 样东西?我写了个 2 秒自检脚本
运维·网络·nginx·docker·容器
xixingzhe21 天前
Nginx 看懂请求耗时瓶颈
服务器·前端·nginx
北风toto1 天前
Windows 下用 OpenSSL 生成 SSL 密钥并配置 Nginx 教程
windows·nginx·ssl
卜锦元1 天前
Docker Compose 部署 Nginx 1.30.6 完整指南
nginx·docker·容器
小小龙学IT2 天前
Nginx 开源 Web 服务器与反向代理深度解
前端·nginx·开源
Coisinier2 天前
docker命令管理镜像及容器
linux·运维·nginx·docker·容器·操作系统
2301_32241428042 天前
基于web的校园失物招领管理系统59695-计算机毕设 原创(免费领源码+部署教程+开发环境)
mysql·nginx·php·apache·thinkphp·phpstudy·wampserver
flytalei2 天前
从YAML到Nginx服务访问:动手理解 Kubernetes Pod、Deployment 与 Service
运维·nginx·kubernetes
健康活着就好3 天前
# Nginx负载均衡四种策略,从原理到配置
nginx