对Nginx进行平滑升级是为了确保服务在升级过程中不中断,保持稳定性和可用性。平滑升级的主要目的是在不影响用户访问的情况下,应用新的配置或版本,以及引入新的功能或修复安全漏洞。以下是一些理由:
在实施平滑升级时,通常采用以下策略:
无论采用哪种策略,平滑升级都是一种最佳实践,可以确保服务的稳定性和可用性。
平滑升级的原理主要涉及到在升级过程中保持服务的连续性和稳定性。以下是平滑升级的一般原理:
- 多实例部署:
- 在平滑升级中,通常会采用多实例部署的方式。新版本的 Nginx 会在一个独立的实例中启动,并与旧版本的 Nginx 并行运行。
- 新旧版本并行:
- 新旧版本的 Nginx 实例会并行处理请求。这样做的目的是确保在升级过程中不中断服务,同时逐步将流量从旧版本切换到新版本。
- 流量切换:
- 管理员可以逐步切换流量,将一部分请求导向新版本的 Nginx 实例。这可以通过负载均衡器、代理服务器或 DNS 修改来实现。流量逐渐过渡,直到完全切换到新版本。
- 配置逐步生效:
- 新版本的 Nginx 会加载新的配置,但并不一定立即生效。管理员可以逐步应用新的配置,确保在升级过程中不会导致配置的突然变更,从而影响服务的稳定性。
- 请求完成:
- 在升级过程中,已经接收的请求会继续由旧版本的 Nginx 处理,而新版本则处理新的请求。这确保了已接受的请求能够顺利完成,而不会丢失。
- 检测和监控:
- 在整个升级过程中,管理员需要进行实时的监控和检测。这包括监控新旧版本的性能、错误率、日志等,以确保升级过程中没有出现异常情况。
- 回滚机制:
- 如果在升级过程中发现了问题,管理员可以快速回滚到旧版本,恢复正常服务。因此,平滑升级需要提供有效的回滚机制,确保在出现意外情况时能够及时处理。
- 灰度发布:
- 平滑升级的一种变体是灰度发布,其中只向部分用户或流量引入新版本。这有助于在小范围内测试新版本,发现潜在问题并及时修复。
其原理简单概括,就是:
(1)在不停掉老进程的情况下,启动新进程。
(2)老进程负责处理仍然没有处理完的请求,但不再接受处理请求。
(3)新进程接受新请求。
(4)老进程处理完所有请求,关闭所有连接后,停止。
这样就很方便地实现了平滑升级。一般有两种情况下需要升级 Nginx,一种是确实要升级 Nginx 的版本,另一种是要为 Nginx 添加新的模块
平滑升级是热升级、热部署,可以不停服务的情况对 Nginx 服务进行升级
将nginx1.16升级成nginx1.18
wget https://nginx.org/download/nginx-1.16.0.tar.gz
yum -y install gcc gcc-c++ pcre pcre-devel gd-devel openssl openssl-devel zlib zlib-devel
useradd nginx && echo "nginx" | passwd --stdin nginx
mkdir /tmp/nginx
tar -xzvf nginx-1.16.0.tar.gz -C /usr/local/
cd /usr/local/nginx*
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--with-http_ssl_module \
make && make install
#将nginx托管到systemd管理(可选步骤)
vim /usr/lib/systemd/system/nginx.service
[Unit]
#描述服务
Description=nginx
#描述服务类别
After=network.target
#服务运行参数的设置,注意【Service】的启动、重启、停止命令都要用绝对路径
[Service]
#后台运行的形式
Type=forking
#服务具体运行的命令
ExecStart=/usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf
#重启命令
ExecReload=/usr/local/nginx/sbin/nginx -s reload
#停止命令
ExecStop=/usr/local/nginx/sbin/nginx -s stop
#表示给服务分配独立的临时空间
PrivateTmp=true
#运行级别下服务安装的相关设置,可设置为多用户,即系统运行级别为3
[Install]
WantedBy=multi-user.target
systemctl daemon-reload
systemctl enable --now nginx
systemctl status nginx
查看现有的 nginx 编译参数
/usr/local/nginx/sbin/nginx -V
按照原来的编译参数安装 nginx 的方法进行安装
只需要到 make
,千万不要 make install
。如果 make install
会将原来的配置文件覆盖
#下载nginx1.18版本
wget https://nginx.org/download/nginx-1.18.0.tar.gz
tar -xzvf nginx-1.18.0.tar.gz -C /usr/local/
cd /usr/local/nginx-1.18.0/
./configure \
--prefix=/usr/local/nginx \
--user=nginx \
--with-http_ssl_module \
make
备份原 nginx 二进制文件
备份二进制文件和 nginx 的配置文件(期间nginx不会停止服务)
mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx_$(date +%F)
复制新的nginx二进制文件,进入新的nginx源码包
cp /usr/local/nginx-1.16.0/objs/nginx /usr/local/nginx/sbin/
测试新版本的nginx是否正常
/usr/local/nginx/sbin/nginx -t
给nginx发送平滑迁移信号(若不清楚pid路径,请查看nginx配置文件)
kill -USR2 `cat /var/run/nginx.pid`
查看nginx pid,会出现一个nginx.pid.oldbin
ll /var/run/nginx.pid*
-rw-r--r-- 1 root root 5 Jul 1 11:29 /var/run/nginx.pid
-rw-r--r-- 1 root root 5 Jul 1 09:54 /var/run/nginx.pid.oldbin
从容/优雅的关闭旧的Nginx进程
kill -WINCH `cat /var/run/nginx.pid.oldbin`
结束工作进程,完成此次升级
kill -QUIT `cat /var/run/nginx.pid.oldbin`
验证Nginx是否升级成功
/usr/local/nginx/sbin/nginx -V
实现的步骤:
1、首先使用nginx -V
查看nginx现有的编译参数
2、然后下载好要更新的源码包,上传到服务器中,然后使用make
命令编译,编译时用--with
添加要使用的模快,--without
去除不需要的模快
3、备份旧的nginx二进制文件,再将新编译好的二进制文件复制到/usr/local/nginx/sbin
下
4、备份完之后,给旧的进程发送一个kill -USR2
的信号,会启动一个新的nginx主进程,实现热升级
5、然后这个时候就能发现/var/run/nginx/pid
下会出现两个进程(nginx.pid
、nginx.pid.oldbin
)
6、再给旧的nginx进程发送一个kill -WINCH
的信号,让旧的nginx work进程从容关闭,不再接受新请求
7、然后发送一个kill -QUIT
的信号,让旧的nginx主进程处理完请求后再退出
8、最后再查看nginx的版本,是否升级成功
安装配置1.6版本的 nginx,重新开启一台机器
[root@localhost ~]# yum install -y gcc gcc-c++ pcre-devel openssl-devel zlib-devel
[root@localhost ~]# tar xzf nginx-1.6.3.tar.gz -C /usr/local/
[root@localhost ~]# cd /usr/local/nginx-1.6.3
[root@localhost nginx-1.6.3]# ./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
[root@localhost nginx-1.6.3]# make && make install
[root@localhost nginx-1.6.3]# useradd -M -s /sbin/nologin nginx
[root@localhost nginx-1.6.3]# /usr/local/nginx/sbin/nginx -t
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful
[root@localhost nginx-1.6.3]# /usr/local/nginx/sbin/nginx
[root@localhost nginx-1.6.3]# netstat -lntp
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 13989/nginx: master
[root@localhost nginx-1.6.3]# /usr/local/nginx/sbin/nginx -V
nginx version: nginx/1.6.3
built by gcc 4.8.5 20150623 (Red Hat 4.8.5-36) (GCC)
configure arguments: --prefix=/usr/local/nginx --user=nginx --group=nginx --with-http_stub_status_module
[root@localhost nginx-1.6.3]# echo "nginx1.6" > /usr/local/nginx/html/index.html
[root@localhost nginx-1.6.3]# yum install -y elinks
[root@localhost nginx-1.6.3]# elinks -dump 192.168.221.138
将 nginx 版本进行升级 并在不影响业务的情况下添加 SSL 和 pcre 模块
[root@localhost ~]# tar xzf nginx-1.12.2.tar.gz -C /usr/local/
[root@localhost ~]# cd /usr/local/nginx-1.12.2/
[root@localhost nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --user=nginx --group=ngiinx --with-http_stub_status_module --with-http_ssl_module --with-pcre
[root@localhost nginx-1.12.2]# make
[root@localhost nginx-1.12.2]# cd
[root@localhost ~]# mv /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx_lod
[root@localhost ~]# cp /usr/local/nginx-1.12.2/objs/nginx /usr/local/nginx/sbin/
[root@localhost ~]# kill -USR2 `cat /usr/local/nginx/logs/nginx.pid`