惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
Google Developers Blog
J
Java Code Geeks
爱范儿
爱范儿
Microsoft Azure Blog
Microsoft Azure Blog
美团技术团队
人人都是产品经理
人人都是产品经理
Martin Fowler
Martin Fowler
IT之家
IT之家
博客园_首页
B
Blog RSS Feed
Google DeepMind News
Google DeepMind News
B
Blog
U
Unit 42
Apple Machine Learning Research
Apple Machine Learning Research
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
罗磊的独立博客
N
Netflix TechBlog - Medium
T
Tailwind CSS Blog
博客园 - 聂微东
腾讯CDC
A
About on SuperTechFans

WANGYE / 王晔

网站平台迁移到ASP.NET 8.0 使用umami自建博客流量统计分析平台 解决PPPoE宽带上网IPv6卡顿问题 网站近期的维护情况 restic使用rclone后端备份数据至WebDAV服务器 Linux LVM分区管理学习备忘 本站使用PGP/GPG加密技术保护联系表单 看门狗(Watchdog)使Linux设备从异常运行中快速恢复 Docker容器使用dumb-init作为进程supervisor和init系统 让过时浏览器支持新技术 JavaScript Polyfill 网站近期的维护情况 Bash Shell脚本得到宽带公网动态IP地址 FreePBX解决动态公网IP环境SIP地址更新问题 从Socket error丢失网络连接的Linux SSH恢复pts会话 Bash Shell使用curl POST向Web API提交JSON nginx njs利用ipset集合实现黑名单(白名单)访问控制 网站平台由ASP.NET 5.0迁移到.NET 6.0 Linux环境.NET Core zh-CN中文语言问题 Docker桥接网络开启IPv6支持
5月29日网站nginx运维故障复盘
Wang Ye · 2022-06-02 · via WANGYE / 王晔

本文章超过一年没有更新,所提供信息可能已经过时,请谨慎参考。

29日下午正好有时间例行网站应用代码升级维护,正好发现nginx HTTP3模块进行了更新,一直关注HTTP3的发展,网站一开始使用的是Cloudflare开发的HTTP3扩展,等nginx官方有了HTTP3支持后也是第一时间升级了,由于本站架构运行在Docker之上,所以这次升级也就改一下nginx代码库commit id,然后重新编译Docker镜像,一直都是这么升级,结果今天翻车了。

由于编译一次Docker镜像需要耗费较长时间,所以我会习惯性把一些该升级的组件进行一次升级:例如更新频率比较高的BoringSSL。这次还发现了ngx_brotli这个很长时间没有更新的扩展也有了更新记录,顺带也升级到最新commit。 完成编译后便直接将这个最新版本的nginx镜像推送至registry,然后服务器同步拉取(pull)完成更新容器更新,由于没有测试直接更新容器,结果炸了。受问题镜像同步的影响,共用nginx镜像的威言威语的网站也进入了不可用状态,好在他服务器上有前一个镜像的备份,遂执行了了回滚,约10分钟后威言威语网站恢复,但我自己的网站在更新的时候清除了镜像备份,所以只能重新上传镜像备份,由于网站服务器在境外,这个过程耗时较长,所以我的网站中断了长达2个多小时,算是较为严重的运维事故。

开始以为是更新的commit存在问题,后来发现不是,经过摸索得到具体的问题出在安全模块ModSecurity上,自构建的Docker镜像没有使用特定commit,导致每次安装的ModSecurity都是最新版本,SpiderLabs/ModSecurity在commit id 00483e4更新上使用线程安全版本取代了单实例:

这导致在启用了此版本及后续版本的ModSecurity的nginx接收请求时进程崩溃,具体表现是出现以下错误:

[alert] 9#9: worker process 111 exited on signal 11

然后客户端接收到的是empty response,如果不启用ModSecurity扩展,则无此类问题。

解决的办法也很简单,直接固定ModSecurity的commit为前一个版本606f572即可,当然对于Docker编译来说通常使用下面的编译指令:

# 以下是代码片段,仅供参考
ENV MODSEC_COMMIT    606f5721c2b52e030f1028ae4e62f359a86443ce
RUN git clone -b v3/master https://github.com/SpiderLabs/ModSecurity \
  && git reset --hard $MODSEC_COMMIT \
  && git submodule init \
  && git submodule update \
  && ./build.sh \
  && ./configure --with-yajl --with-ssdeep --with-lmdb --with-geoip --enable-examples=no\
  && make -j$(getconf _NPROCESSORS_ONLN)\
  && make -j$(getconf _NPROCESSORS_ONLN) install

其中需要注意的是增加了git reset --hard commit_id指令,该指令将强制使用特定commit_id的版本,这样问题可以算是临时解决了,至于为啥ModSecurity改Thread safe导致nginx进程崩溃还需要继续研究,目前先临时这么处理。

总结来说,以后对于这类镜像的编译和部署还是要先行测试,不能偷懒图省事了,因为隐秘的角落总是会有奇奇怪怪的Bug在伺机而动。