Nginx 平滑升級的實戰指南!(含備份+業務0中斷+回滾)
今天分享一下Nginx如何平滑升級,做到零中斷。
在實際生產環境,安全部門一般都會定期去掃描程序漏洞,基本都需要升級版本。
部分運維人員的做法是:停服務--> 刪除舊版本nginx-->安裝新版本nginx-->啟動服務。
這種方式需要停服務,非常影響用戶體驗感,所以我下面介紹一下如何進行不停機且安全可控得進行平滑升級Nginx。
1. 實驗環境說明
- 操作系統:Rockylinux9.4
- 當前nginx是編譯安裝
- 部署路徑:/data/nginx
- 從nginx1.26.2升級到1.29.0
2. 升級前先備份!非常關鍵!
線上升級,沒備份 = 自殺式升級。
全量備份:
tar -zcvf /data/nginx-backup-$(date +%F).tar.gz /data/nginx/
回滾時你只需 tar -zxvf + reload,1 分鐘恢復原狀。
3. 確認原版本和編譯參數
[root@webserver data]# nginx -V
nginx version: nginx/1.26.2
built by gcc 11.5.0 20240719 (Red Hat 11.5.0-5) (GCC)
built with OpenSSL 3.2.2 4 Jun 2024
TLS SNI support enabled
configure arguments: --prefix=/data/nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre --with-stream --with-stream_ssl_module
非常重要!新版本必須用相同參數編譯才能平滑替換,不過可以新增參數!
4. 安裝依賴
dnf install -y gcc make zlib-devel pcre-devel openssl-devel wget
這一步可以省略,一般編譯舊版本時已經安裝了依賴。
5. 下載并編譯 Nginx 新版本
(1) 下載源碼
版本可以具體根據漏掃要求,一般是建議最新版本,我這邊選1.29.0版本:
wget https://nginx.org/download/nginx-1.29.0.tar.gz
tar -zxvf nginx-1.29.0.tar.gz
cd nginx-1.29.0
(2) 使用原配置參數重新編譯
這里也可以添加一些新的參數,但是盡量不要刪除以前的參數,建議在已有基礎添加新參數。
./configure --prefix=/data/nginx \
--with-http_stub_status_module \
--with-http_ssl_module \
--with-pcre \
--with-stream \
--with-stream_ssl_module
make
注意注意:千萬不要 make install,避免直接覆蓋現有 Nginx!
6. 平滑升級核心流程
(1) 替換 Nginx 可執行文件
# 移動舊版本可執行文件
mv /data/nginx/sbin/nginx /data/nginx/nginx/sbin/nginx.old
# 將新版本的執行文件放置在安裝目錄下
cp ./objs/nginx /data/nginx/sbin/nginx
# 檢測Nginx進程,可見舊的版本進程還在運行
ps -ef |grep nginx
(2)啟動新主進程(平滑切換)
# 殺掉舊版nginx主進程,讓新進程重新生成
kill -USR2 `cat /data/nginx/logs/nginx.pid`
# 上面引用部分主要是找出nginx的PID,你也可以根據ps來找。
此時存在4個進程. 2個舊版nginx進程 2個新版nginx進程。
新的 master 進程加載新版本。
老版本PID文件變為 .pid.oldbin,仍然工作中:
(3) 優雅關閉舊 worker進程
kill -WINCH `cat /data/nginx/logs/nginx.pid.oldbin`
舊worker 會逐步停止服務,連接自動轉移到新版本,舊master進程還在。
7. 驗證是否升級成功
查看版本:
nginx -v
檢查日志無報錯:
tail /data/nginx/logs/error.log
確認監聽端口仍在線:
netstat -lntup |grep nginx
多核 CPU 下也可觀察進程切換:
ps -ef | grep nginx
8. 結束舊主進程
等業務確認OK后,沒問題,就可以殺掉舊的master進程了。
kill -QUIT `cat /data/nginx/logs/nginx.pid.oldbin`
# 再次檢查
ps -ef |grep nginx
此時舊版進程徹底退出,升級完成!
9. 快速回滾操作
如果升級后出問題,只需執行:
cp /data/nginx/sbin/nginx.bak /data/nginx/sbin/nginx
nginx -s reload
也可以恢復整個 Nginx 安裝目錄:根據之前那個備份目錄直接解壓后重載nginx:
tar -zxvf /data/nginx-backup-YYYY-MM-DD.tar.gz -C /
nginx -s reload
謹記:先備份后操作!如果可以測試環境先行!