如果使用动态模块,在升级到新版NGINX或NGINX Plus时,可能会看到如下错误:
Setting up nginx-plus (1.11.10-1~xenial) ...
nginx: [emerg] module "/etc/nginx/modules/ngx_http_geoip_module.so" version 1011005 instead of 1011006 in /etc/nginx/nginx.conf:7
nginx: configuration file /etc/nginx/nginx.conf test failed
invoke-rc.d: initscript nginx, action "upgrade" failed.最可能的原因是尚未升级指定的动态模块(.so文件):
- 如果您运行的是NGINX Open Source,则必须针对要升级到的版本编译动态模块。
- 如果运行的是NGINX Plus,则必须针对与要升级到的NGINX Plus版本相对应的NGINX Open Source版本编译动态模块。
为简洁起见,下文将仅提及NGINX Plus。
别慌!
请放心,此错误消息并不表示NGINX Plus服务器已停止运行。NGINX Plus采用无缝升级,因此升级失败时旧版本仍会继续运行。不过,此时升级尚未完成,系统处于不一致状态:
- 内存中的NGINX Plus进程仍在运行旧版本
- 磁盘上与NGINX Plus相关的所有文件均对应新版本
- 错误消息中提到的动态模块是针对旧版本编译的
请勿手动重启nginx或重新启动系统。否则会导致服务中断,因为只要存在与新版NGINX Plus不同步的动态模块,新的NGINX Plus进程就无法启动。
请注意,该错误消息仅与升级过程中发现的第一个不兼容模块有关,因此务必查找配置中的所有“load_module”指令,并确保每个模块均针对相应的NGINX版本进行编译。每个NGINX Plus版本均提供所有“NGINX开发及认证的第三方动态模块”的正确版本,因此只需重新编译未经认证的模块。本文介绍如何安全地完成升级过程。
出了什么问题?
NGINX 1.11.5和NGINX Plus R11新增了针对NGINX Open Source编译动态模块并将其加载到NGINX Plus中的功能。要实现这种二进制兼容性,模块和NGINX Plus必须基于同一开源版本。如果未先安装针对相应NGINX Open Source版本构建的动态模块,升级NGINX Plus将因版本不匹配而失败。
如果动态模块由第三方供应商提供,则需要联系该供应商,获取与您计划升级到的NGINX Plus版本所对应的NGINX版本相匹配的新模块版本。如果动态模块是从源代码编译的(并且您可以访问源代码),请继续阅读。
恢复之路
步骤0:准备构建环境
强烈建议在单独的系统上编译动态模块,本文将该系统称为“构建环境”。这样可以最大限度地降低运行NGINX Plus及动态模块的系统(本文称为“生产环境”)所面临的风险和复杂性。构建环境必须与生产环境使用相同的操作系统及版本;此外,还必须安装以下组件:
- UnZip实用工具
- 编译器和make实用程序
- Perl 兼容正则表达式库(开发文件)
- Zlib压缩库(开发文件)
为确保构建环境已安装这些必备组件,请运行以下命令。
- 对于Ubuntu/Debian:
buildenv$ sudo apt-get install unzip gcc make libpcre3-dev zlib1g-dev- 对于CentOS/RHEL/Oracle Linux:
buildenv$ sudo yum install unzip gcc make pcre-devel zlib-devel第1步:获取NGINX Open Source
- 在生产环境中运行以下命令,确定与当前运行的NGINX Plus版本对应的NGINX Open Source版本。在此输出中,该版本以橙色突出显示:NGINX 1.11.10,对应NGINX Plus R12。
production$ nginx -vnginx version: nginx/1.11.10 (nginx-plus-r12)- 在构建环境中,下载相应NGINX Open Source版本的源代码。
build-env$ wget -qO - http://nginx.org/download/nginx-1.11.10.tar.gz | tar zxfv -第 2 步:获取动态模块源代码
将动态模块的源代码复制到所选的构建目录。此处,我们从该模块的GitHub存储库中复制一个NGINX“hello world”示例模块。
buildenv$ git clone https://github.com/perusio/nginx-hello-world-module.git
Cloning into 'nginx-hello-world-module'...步骤 3:编译动态模块
- 要编译动态模块,请先运行NGINX的
configure脚本并使用--with-compat参数,使动态模块与NGINX Plus保持二进制兼容。然后运行makemodules,仅编译该模块。
buildenv$ cd nginx-1.11.10/buildenv$ ./configure --with-compat --add-dynamic-module=../nginx-hello-world-module
buildenv$ make modules- 确认构建过程已将动态模块创建为 .so文件,并存放在objs子目录中。
buildenv$ ls objs/*.soobjs/ngx_http_hello_world.so- 创建模块文件的副本,并在文件名中包含NGINX Open Source版本号。这样可以更轻松地在生产环境中管理动态模块的多个版本。
buildenv$ cp objs/ngx_http_hello_world.so ./ngx_http_hello_world_1.11.10.so步骤4:将动态模块复制到生产环境
由于我们创建动态模块时在文件名中加入了NGINX Open Source版本信息,因此可以放心地将其复制到生产环境,而不会影响系统运行。
buildenv$ scp ./ngx_http_hello_world_1.11.10.so production:/etc/nginx/modules第5步:切换动态模块
在生产环境中,换入新的 .so文件以替换当前文件。此时执行此操作是安全的,因为只有在nginx重启或重新加载配置时,动态模块才会加载到内存中。
production$ cd /etc/nginx/modulesproduction$ cp ngx_http_hello_world.so ngx_http_hello_world_ROLLBACK.so
production$ ln -fs ngx_http_hello_world_1.11.10.so ngx_http_hello_world.so
production$ ls -gG
-rw-r--r-- 1 243576 Jan 31 16:18 ngx_http_hello_world_1.11.10.so
-rw-r--r-- 1 243576 Oct 20 10:40 ngx_http_hello_world_ROLLBACK.so
lrwxrwxrwx 1 24 Jan 31 16:26 ngx_http_hello_world.so -> ngx_http_hello_world_1.11.10.so步骤 6:完成 NGINX Plus 升级
- 运行以下命令,测试模块版本是否正确,并确认NGINX Plus已准备好完成升级过程。
production$ nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful- 完成升级流程,使NGINX Plus使用新版本和动态模块。
production$ service nginx upgradeStarting new master nginx: [ OK ]
Graceful shutdown of old nginx: [ OK ]防止升级失败
下次升级NGINX Plus时,请在升级前按照这些说明操作,以确保开始升级时已提供更新后的动态模块,从而节省时间并避免错误。
关于作者

相关博客文章
NGINX Plus R26 正式发布
NGINX Plus R26通过缓存JSON Web密钥集加快JWT验证,并强化TLS握手,从而提升安全性。NGINX JavaScript的新功能包括增强对异步函数的支持,以及实现WebCrypto API。
使用NGINX App Protect DoS保护gRPC应用,抵御严重的DoS攻击
gRPC具备开发人员设计和部署现代应用所需的速度与灵活性,但其开放性也使其极易受到第7层DoS攻击。NGINX App Protect DoS可保护gRPC应用免受此类破坏性攻击。
Ingress Controller 选型指南(第 2 部分):风险与面向未来的规划
了解选择错误的Ingress控制器可能带来的风险,以及如何从关键方面着手,让您的选择更好地适应未来需求。
NGINX Plus R19 正式发布
NGINX Plus R19扩展了监控功能,不仅提供更多指标,还新增了指标分析方式;增加试运行模式,用于测试限速效果;增强键值存储,以支持IP地址范围;并使限速更加动态。
NGINX现已正式加入F5
NGINX现已正式成为F5的一部分。Gus Robertson现任F5 NGINX业务部门负责人。他阐述了两家公司在人才、文化和愿景方面融合的价值,以及双方将如何携手增强NGINX的开源产品和商业产品。
