加入收藏 | 设为首页 | 会员中心 | 我要投稿 站长网 (https://www.0472zz.com/)- 云渲染、网络安全、终端安全、数据治理、智能机器人!
当前位置: 首页 > 运营中心 > 建站资源 > 建站经验 > 正文

嵌入式工程师建站踩坑实录:裸机到高可用全链路运维

发布时间:2026-10-30 11:07:40 所属栏目:建站经验 来源:DaWei
导读:  我原以为把 STM32F407 的裸机启动代码烧进 Flash 之后,剩下的就是配个 Nginx、开个 TLS、绑个域名——毕竟跑过 FreeRTOS、调过 CAN FD、抓过 JTAG 信号毛刺,谁还怕个 HTTP?结果十一月三号凌晨两点十七分,监控钉钉弹

  我原以为把 STM32F407 的裸机启动代码烧进 Flash 之后,剩下的就是配个 Nginx、开个 TLS、绑个域名——毕竟跑过 FreeRTOS、调过 CAN FD、抓过 JTAG 信号毛刺,谁还怕个 HTTP?结果十一月三号凌晨两点十七分,监控钉钉弹窗第十八次报 “backend offline”,我正蹲在机柜前用热风枪吹一块焊歪的 ESP32-C3 模组,旁边桌上半盒冷掉的酸辣粉浮着层油花,汤里泡着两根没夹起来的豆芽。


  那个晚上机房空调坏了,出风口嗡嗡震得整排 1U 机架共振,像台老式洗衣机脱水甩干。我听见老张在隔壁隔间接电话,声音压得很低:“……不是硬件问题,是它自己 reload 配置的时候把 etcd lease 给续丢了。” 他顿了三秒,“对,就那一秒,没心跳,集群判它死了。” 我手一抖,热风枪偏了半度,C3 的 BOOT0 引脚铜箔冒了青烟。我盯着那点烟看了六秒——不是心疼芯片,是突然想起三天前我们对着 Prometheus 图表吵的那句:“你管这叫‘服务健康’?这叫定时自爆倒计时。”


  高可用?呵。我们当时真拿 K8s 跑过一个裸机部署:三个树莓派 4B+ 2GB 内存,装 k3s,挂 NFS 存 PV。运行三个月,没崩。第四个月第一天,NFS 服务器 reboot 后没自动挂载,k3s-agent 死循环重试 372 次后内存占满,整个 node 丢心跳——但 etcd 成员状态还是 `healthy`,UI 上绿得发亮。运维脚本每分钟 check `/proc/mounts`,但只 grep `nfs` 字样,漏掉了 mount point 是 `192.168.3.11:/data` 而输出实际是 `192.168.3.11:/data on /mnt/data type nfs4 (rw,relatime,vers=4.2,rsize=1048576,wsize=1048576,…)`——就因为少写了个 `-o` 参数,grep 匹配不上,脚本直接 exit 0。这个我敢打包票,日志截屏我还存着,第三行第十四列那个反斜杠就是证据。


  后来我们切回裸机 + systemd + nginx,加了个 `ExecStartPre=/bin/bash -c 'timeout 5 curl -f http://127.0.0.1:8080/health || exit 1'`。听起来靠谱吧?结果上线第二天,某个同事临时改了 health 接口返回 JSON 的结构,字段名从 `status` 改成 `health_state`,而前端 JS 也同步更新了——可后端 nginx 配置里那个 curl 健康检查没动。于是每次重启 service,systemd 先 ping 一次旧接口,失败,就卡死不启;人还得 ssh 进去手动 `systemctl reset-failed`。我在 Slack 里打字手抖,把 “reset-failed” 打成 “reset-faild”,发出去才发现,撤回不了,就补了句:“…faild 是我新起的服务名,已注册商标。” 没人笑。没人回。只有钉钉又响了一声,警报恢复,但根本没恢复——那台机器其实已经断网四十三分钟,只是 ARP 缓存没清,ping 还通着。


  上礼拜我路过前台,看见实习生小杨蹲在地上给一堆 USB-C 线分类:红的插电源,蓝的传数据,黄的带 E-Marker。她手里捏着一根灰线,线身印着模糊的 “USB-IF Certified”,但接口金属片刮花了,第三根针有点歪。她举起来问我:“哥,这根能当 PD 触发线使吗?” 我说“不能”。她说“为啥”。我说“因为 PD 协议握手要 5V/3A 撑住 500ms,你这针歪了 12 微米,电压跌落会触发 Source 自动降档到 9V/2A,再降成 15V/1.5A——等轮到你那台 ARM64 开发板的 Type-C 插座检测到 VBUS,内核早 panic 在 usbcore_probe 里了。” 她点点头,把线塞进“待测”盒。我没告诉她,我们线上那个 HTTPS 证书自动续签失败的真正原因,也是某根被误插进管理网口的、同样刮花的灰线——BMC 网口 PHY 芯片和主板网口 PHY 碰巧用了同一颗 Marvell 88E1512,共用一个内部 LDO,而刮伤导致短时漏电,LDO 波动引发电源复位,刚好发生在 certbot renew 最后一次 POST 时。这事我说不准——没抓到波形,示波器租期上个月到期了。


文章配图,仅供参考

  现在我们的发布流程是这样的:先 git tag v2025.11.x,然后 Jenkins 构建 Docker 镜像,推 registry;接着 Ansible 登录所有边缘节点,pull 新镜像、stop 旧容器、start 新容器——但不删旧镜像。三年下来,一台生产边缘设备磁盘满了,df 显示 100%,docker image ls 列出来七百多镜像。清理脚本是另一套 cron,每天删一个月前的所有 dangling image;结果它真删了,也真删错了:把还在 running 的 v2025.09.3 镜像删了——因为 tag 没打全,只剩 image ID,而那段 ID 恰好跟一个 dangling 的中间层 ID 完全相同。Docker 没报错,只是下次 restart 容器时找不到 base layer,报 `layer does not exist`。我们在日志里翻了整整十一个小时才找到这一行。后来我们给所有构建加了 `--squash`,又发现 Squash 后的镜像层校验和,会跟某些版本的 overlay2 驱动有 hash 冲突……算了,这段不说了。我泡杯茶,茶包掉进杯子里,没捞出来,就让它沉底。


  优胜劣汰?是啊,真他妈是。不是靠技术文档淘汰,是靠你哪天手滑少打了一个 `-f`,或者哪次巡检路过没听见机柜顶那声“咔哒”异响——就那一下,继电器触点粘连,UPS 输出电压漂移 ±0.8V,刚好压过 STM32H7 的 VDDA ADC 参考阈值,导致采集的环境温湿度数据连续三天飘高 3.2℃,报警逻辑始终不触发。直到客户打电话问:“你们后台显示我仓库烧起来了,可我明明在东北。”


  我昨天把所有 ansible-playbook 的 `-C`(check mode)参数全删了。不是因为信得过,是因为上次加 `-C`,它报告“一切正常”,执行时却卡死在 `copy` 模块,原来目标路径权限是 `750`,而 playbook 默认 umask 是 `022`,导致新建文件夹属组丢失写权限,`notify: restart nginx` 就永远等不到。这次我不赌。我把所有关键服务的 systemctl unit 文件里都加了 `RestartSec=3s`,然后把 `Restart=on-failure` 改成了 `Restart=always`。我知道这蠢。可十一月快过去了,我只想让那台 192.168.10.12 的工控网关,在下雪之前,自己把自己拉起来一次。

(编辑:站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!