因我们的前后端项目都部署在k8s集群中,前端项目采用npm和node管理
事故背景: 某天前端同事在测试环境更新完一个前端服务后,访问正常,然后按照正常流程上线到生产环境,但是,在生产环境更新完成后,测试同事反馈访问报502错误,我就去服务器排查刚才发布的服务,检查pod状态是RUNNING状态,更新时间也是几分钟前,从表面看没有问题,由此,赶紧回滚镜像,停止上线,拉开问题排查与解决之路~
与前端同事沟通,该前端服务启动后会有一个3001端口
使用命令进入到刚才更新的pod中
kubectl exec -it k8s-xxx-xxx-1960-0 -- /bin/bash
netstat -lntp |grep 3001
ps -ef
由上图所示,测试环境的服务启动后,有对应的端口及进程服务,因此我猜测生产环境该服务并未完全启动导致更新后报502问题
kubectl exec -it k8s-xxx-xxx-2360-0 -- /bin/bash
netstat -lntp |grep 3001
ps -ef
发现服务并未启动,也没有相关进程
FROM node:12.19.0
WORKDIR /output
COPY ./output /output
EXPOSE 3001
ENV NODE_ENV=production
CMD nohup npm run start >out.log 2>&1 && tail -f out.log
根据dockerfile找到对应的启动命令,手动启动
npm run start
再次检查,发现服务能正常启动,且访问正常
至此,已确认问题: 生产环境502问题是因为服务启动造成的,那么具体未启动的原因是什么?请看下面描述
env |grep wc -l
命令,如下图所示,总共396个环境变量,比较少env |grep wc -l
命令,如下图所示,共有2594个环境变量和研发确认不相干的环境变量,然后修改启动脚本,添加要取消掉的相关变量 A_BJ01|B_BJ01|EXPO_|10,如下所示 在pm2启动前清除系统中的环境变量
#!/bin/sh
cd "$(dirname $0)"/.. || exit 1
echo "$(dirname $0)"
PROC_NAME='xxx'
help(){
echo "${0} <start|stop|restart|status>"
exit 1
}
status(){
wcx=`ps -eo "command" | grep PM2 | wc -l`
if [ $wcx == 1 ]; then
status="offline"
else
status="online"
fi
echo $status
if [ X"$status" == X"online" ]; then
return 0
else
return 1
fi
}
start(){
#修改A_BJ01|B_BJ01|EXPO_|10此处变量即可
for i in `env | grep -E -i 'A_BJ01|B_BJ01|EXPO_|10' | sed 's/=.*//'` ; do
unset $i
done
NODE_ENV=production
pm2 start
sleep 3
status
}
请根据自己环境中的变量进行修改,不可直接粘贴使用
让研发同事将该脚本上传到对应的代码仓库,重新进行CICD操作,然后检查对应的服务端口和进程以及环境变量,发现启动成功,完美解决问题。
在报错服务的deployment.spec.template.spec模块下添加如下内容,其中enableServiceLinks 表示是否将 Service 的相关信息注入到 Pod 的环境变量中,默认是 true:
enableServiceLinks: false
以上就是今天要分享的内容,也是第一次遇到这个问题,主要是不熟悉前端node和pm2,解决方法也是网上找方案及问同事,不过最终还是有用。在解决完上线问题后,前端同事本地调试pm2
,打印打console.log
,也发现是环境变量参数的长度异常,最终定位是process.env
会获取操作系统的所有变量,造成process.env多达70000以上字节长度。占了99%的process.env长度,并且皆为无用变量。因此,为了避免生产和测试环境再次出现该问题,对每个服务都进行了环境变量的筛选,通过脚本的方式在pm2启动前进行没用的环境变量清理,确保后续服务发版顺利!!!