《博客崩溃源记》

embedded/2024/10/11 13:29:00/

原文链接:https://www.hezebin.com/publish/66a393d03ad6ee047813fe57

背景

百年未有之大变局年夏初,最近在负责前端同学招聘的一面工作,对于一些常见的八股文基础问题做了一下记录…

忽有一日,面试在即,打开博客见文章列表无了!!!ERROR!!😱

排查

从上述现象看,所有 api 接口超时报错,但是页面能打开,说明至少服务器机器和 Nginx 服务没问题,由于所有服务都部署在 K8S 环境中,此时大致猜想是博客服务 Clash 崩溃了… 于是查看了一下 Pod 状态:

从上图看是 mongo-sts-1 挂了,Pod 的异常状态是 ImagePullBackOf,由于该 Pod 在副本集中还是主节点,且我没有设置 MongoDB 读取偏好的原因,默认使用了 Primary 只从主节点读取数据,所以读取连接超时了。


到这时,主要在比较纳闷为什么会拉取镜像失败呢?所以尝试性的将这个 Pod 删了,让其自动重启一下,仍然没解决,然后又呆滞的将 StatefulSet 重启了一下,OK 现在 3 个 Pod 都挂了,都是拉取不到镜像 😭!


于是,我开始怀疑是不是网络问题了,便尝试直接拉取了一下 Docker 镜像(容器用的 Containerd):

ctr images pull docker.io/library/mongo:latest

失败!网络超时!到这里也算是能确认排查方向就是网络问题了,于是先查看了一下配置的镜像仓库:

cat /etc/rancher/k3s/registries.yaml

结果竟然是空的,我竟然没配,但是之前竟然正常拉取到了镜像!二话不说,先把国内 Docker 镜像源配置上,重启 K3s 后重新尝试直接命令拉取镜像,但是还是超时失败…


这个时候,和网络相关的,我就只能怀疑是我配置的代理问题了,当初部署搭建 K3s 环境时,为了下载国外各种安装包和镜像源方便,在云服务机器上安装了 V2ray,并配置了代理,但是代理的环境变量是临时的:

export http_proxy=http://127.0.0.1:1087
export https_proxy=http://127.0.0.1:1087
export ALL_PROXY=socks5://127.0.0.1:1080

所以我理解我关闭了终端后,这个代理的环境变量就失效了,且我在当前终端打印查看了环境变量,确实是空的,说明宿主机上的网络请求确实没走代理 ( ping 了 google.com 也确实不通啊 ),即使 V2ray 的代理服务一直运行着,但是没走代理就不应该有影响。但是,抱着尝试验证一下的想法,决定把这个代理服务给停掉,确认一下是否真的是由这个代理服务导致的网络问题。


于是关闭代理后我继续命令拉取镜像,仍然失败!此时潜意识的 k get pod了一下想看最新的服务状态,侥幸万一镜像拉到了呢? 突然!很快啊!这一操作竟然也失败了?


错误信息明确提示由于代理网关失败!这个信息就很关键了,说明虽然宿主机网络没走代理,但是 K8S 内的网络通信走了代理,虽然暂时不知道为什么,但是想尽快解决问题就只能先把 V2ray 再启动起来了!


!!! note
忽然!该死的记忆疯狂涌入了大脑🧠,让我想起了点什么事,我昨天在代理服务商那边重置了我的订阅地址,因为当时在用 GPT 时有点卡,所有节点普遍延迟有点高,想通过刷新订阅地址更新一下服务器节点列表,但这会使原先的订阅地址和对应的配置、认证等失效 …
!!!

然后将新的 V2ray 配置更新并重启 V2ray 后,此时普天同庆!终于通过命令直接拉取到镜像了!!!


但事实是我高兴的还是太早了,重新查看 Pod 状态,发现仍然没有启动成功,虽然不是镜像拉取失败了,但是此时的状态变更为了:CrashLoopBackOff,“突闻噩耗,这让本就不健康的状态雪❄️上加霜🩸”…


查看 Pod 日志,有大量的警告和错误日志,关键信息大致是在描述版本不兼容:

{"t":{"$date":"2024-07-19T09:03:16.660+00:00"},"s":"F",  "c":"-",        "id":23093,   "ctx":"initandlisten","msg":"Fatal assertion","attr":{"msgid":28579,"error":"UnsupportedFormat: Application metadata for table:index-37-7408967326262778357 has unsupported format version: 14. Index: {name: user_1_db_1, ns: admin.system.users} - version either too old or too new for this mongod.","file":"src/mongo/db/storage/wiredtiger/wiredtiger_index.cpp","line":514}}

这就又让我很疑惑了,我使用的镜像地址固定是 mongo:latest,即最新镜像版本,为什么在重新拉取后就直接不兼容了?而且我查看了 Mongo 官方的更新日志并没有大版本的更新。。。 此情此景,已经是有点脑袋晕晕没有办法了,此刻觉着重要的是先把我的文章数据给搞出来,别让数据丢了,但是看了下导出挂载在本地服务器的数据文件竟然有 2 个 G 左右,但实际我的所有文章 JSON 数据大小 1M 都不到,这导出来成本太大了,且去恢复官方的原始数据文件也是一个极为繁琐的过程,劝退 ing…

很庆幸的是,一开始挂掉的 MongoDB Pod 只有主节点那一个容器,修复代理网络问题重启后仲裁节点也因为兼容问题报错挂掉了,但是副本节点还在,所以赶紧在本地机器上通过 kt-connect 打通K8S集群网络,使用Mongo 官方的可视化管理工具 Compass 连上该副本集,然后将数据导出成 JSON 文件,至此,在此次危机中,至少文章数据得以留存…

最后将 Mongo 副本集完全 Flush 后重新安装,然后将数据重新导入后博客暂时恢复正常~

根因

服务器安装了代理服务软件,在重置了代理服务商的订阅地址后,导致服务器代理失效!🌚

分析

上述的各种问题和过程中疑点重重,下面来逐一分析原因~

为什么 Pod 会重启?

Mongo 的 StatefulSet 重启并尝试重新拉取镜像,可能原因包括:

  • 镜像策略设置:imagePullPolicy 设为 Always,导致每次启动都尝试拉取最新镜像。
  • Probe 配置敏感:Readiness 或 Liveness Probe 配置过于严格,导致频繁重启。
  • 特定应用依赖:MongoDB 可能有网络依赖,导致在网络波动时触发重启。
  • 资源限制:临时网络问题导致资源(如内存或 CPU)不足,引发重启。

为什么重启时没使用之前的本地镜像缓存?

在 Kubernetes 中,如果没有配置 imagePullPolicy,默认值取决于镜像标签:

  • latest 标签:默认为 Always。
  • 其他标签或具体版本:默认为 IfNotPresent。

因此,如果使用 mongo:latest,会每次启动都尝试拉取镜像。建议将 imagePullPolicy 设置为 IfNotPresent 来避免这种情况。

为什么 K3s 配置了代理?

K3s 在部署时自动创建了一个环境变量的配置文件:/etc/systemd/system/k3s.service.env,该配置文件下刚好存在网络代理的环境变量:

目前没去深究 K3s 在部署时的具体操作行为,只能是猜测它尤其关注网络配置相关的环境变量,若存在则延用到 K3s 中。当时的环境变量虽然是临时的,结果被应用到K3s 的配置文件中成K3s 永久的网络代理配置了。

为什么重新拉取镜像后出现了版本不兼容情况?

通过查看本地的镜像缓存列表,然后进一步查看镜像详细信息,在镜像信息中发现了一个叫MONGO_VERSION 的变量:

最新的 latest 指向的镜像其版本为 5.0.x,而之前的均为 7.0.x,这跨了 2 个大版本,难怪会版本不兼容。

为什么 latest 出现了拉取到的最新版本是老版本?

上述提到都是 mongo:latest,之前是 7.x,但现在竟然变成了 5.x ,版本还更旧了,真很夸张!

复盘了一下经过,大概想到原因是一开始由于配置了代理,可以访问外网,所以我没有配置 K3s 的镜像仓库,于是所有的镜像都是直接从 Docker 官方镜像源拉取的。但是在排查问题的过程中,我发现了没配国内镜像源就给配上了,结果导致后面拉取的镜像都是从国内镜像源拉取的,国内的镜像仓库可能没有同步最新的版本,导致 latest 拉到的还是老版本,就酱紫了…

为什么副本节点能够正常,其他节点挂掉了?

目前还没找到具体原因,只能猜测是 MongoDB 自身在不同节点角色上的兼容差异导致副本节点幸免于难版本的冲突

解决方案

如何避免出现本次的这些问题,和以后如何更好的处理此类问题呢?

固定版本

不要使用 latest,选择固定的稳定版本,每次升级前仔细阅读和确认官方的变更情况,然后再做升级。

数据备份

这次问题的出现在整个过程中我最担心的就是我的博客文章数据怎么办?只能说鸡蛋🥚还是不能放在一个篮子里,要多做数据备份,万一哪次彻底没法找回数据了,也好用备份的数据做恢复。

目前写了一个简易的专门用于做数据备份的服务,定时将数据备份到 OSS:https://github.com/ihezebin/data-backup

tips:以前遇到过数据库被劫持勒索,被清空的情况,所以唯一解法还是做好数据备份。

补充

这里补充一个在 K8S 中部署中间件分片或副本集集群的坑,如 Redis 分片集群存在一个问题是:即使你在初始化集群注册节点时用的 dns 名称:

redis-cli -a root --cluster create redis-sts-0.redis.default.svc.cluster.local:7000 redis-sts-1.redis.default.svc.cluster.local:7000 redis-sts-2.redis.default.svc.cluster.local:7000 --cluster-replicas 0

在 Redis 维护的节点数据文件里,其节点信息记录的是当时 dns 名称解析出的具体 ip,若 sts 重启,那 Pod 的 ip 必然会发生变化,这就会导致集群状态异常和崩溃:

目前我的解法就是用 Pod 来部署,然后每个 Pod 绑定一个 Service,只要 Service 不删,ip 就不变。

参考文献 🐶

  • 《桃花源记》-【作者】陶渊明 【朝代】东晋
  • K3S 和 Rancher 安装部署&配置
  • React 前端面试基础问题
  • MongoDB 7.0(稳定版本)发布说明

http://www.ppmy.cn/embedded/97792.html

相关文章

算法刷题day35|动态规划:121. 买卖股票的最佳时机、122. 买卖股票的最佳时机 II、123. 买卖股票的最佳时机 III

121. 买卖股票的最佳时机 一维dp class Solution { public:int maxProfit(vector<int>& prices) {if (prices.size() 0) return 0;vector<int> dp(prices.size(), 0);dp[0] 0;int mint INT_MAX;for (int i 1; i < prices.size(); i){//更新最小股票值…

基于vue篮球联盟管理系统pf

TOC springboot476基于vue篮球联盟管理系统pf 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现&#xff0c;改变了几千年以来人们的生活&#xff0c;不仅仅是生活物资的丰富&#xff0c;还有精神层次的丰富。在互联网诞生之前&#xff0c;地域位置往往是人们思想上不可跨域…

C#单例模式

&#xfeff;using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace _3._3._6_单例模式 {public class Singleton{private static Singleton s_instance;private int _state;private Singleton(int …

c_cpp_properties.json、launch.json、 tasks.json

在 Visual Studio Code 中&#xff0c;c_cpp_properties.json、launch.json 和 tasks.json 是三个重要的配置文件&#xff0c;它们的作用如下&#xff1a; c_cpp_properties.json&#xff1a; 这个文件用于配置 C/C 扩展的 IntelliSense、编译器路径和包括路径等。它帮助 VS Co…

智慧安防/一网统管/视频监控EasyCVR视频汇聚平台的视频轻量化特点及应用

在数字化时代&#xff0c;视频监控已成为保障公共安全、提升管理效率的重要手段。随着技术的不断进步&#xff0c;EasyCVR视频汇聚平台应运而生&#xff0c;平台以其独特的视频轻量化特点在安防监控领域展现出强大的应用潜力。本文将详细探讨EasyCVR视频汇聚平台的视频轻量化特…

分布式调度 redis scheduler锁的实现参考

scheduler竞争锁 注意参数类型和返回值 Autowiredprivate StringRedisTemplate redisTemplate;Autowiredprivate XfuzzConfig xfuzzConfig;private volatile boolean scheduler false;Scheduled(fixedDelay 5 * 1000, initialDelay 10 * 1000)public void acquireLock() {S…

【体检】程序人生之健康检查,全身体检与预防疫苗,五大传染病普筛,基因检测等

程序员养生指南之 【体检】程序人生之健康检查&#xff0c;全身体检项目分类&#xff0c;五大传染病普筛&#xff0c;基因检测等 文章目录 一、全身体检与预防疫苗&#xff08;年检&#xff09;1、实验室检测&#xff1a;生化全套检查2、医技检查&#xff1a;辅助诊疗科室3、科…

Linux·权限与工具-make

1. Makefile/makefile工具 首先展示一下&#xff0c;makefile工具如何使用。我们先写一个C语言程序 然后我们建立一个Makefile/makefile文件&#xff0c;m大小写均可。我们在文件中写入这样两行 wq保存退出后&#xff0c;我们使用 make 命令 可以看到生成了可执行程序&#xff…