从 Docker Compose 到 Kubernetes:物联网管理系统迁移实战(3)—— 两个运维坑

一、项目背景

物联网管理系统最初采用 Docker Compose 部署,结构简单:前端 Nginx + 后端 Spring Boot + MySQL。随着业务发展,单机部署的问题逐渐显现:单点故障、无法扩缩容、发布需停服。

本次实验的目标是将这套系统迁移到 Kubernetes 集群,体验从"单机编排"到"集群调度"的转变。

前四篇文章记录了集群搭建、镜像构建、应用部署、健康检查配置的过程。系统终于跑起来了,但在后续运维中又遇到了两个典型问题:

  1. 虚拟机重启后 kubectl 证书失效

  2. 数据库迁移后表不存在导致 500 错误

这两个问题在实际工作中非常常见,记录如下:

问题1:虚拟机重启后 kubectl 证书失效

现象:

每次重启虚拟机后,执行 kubectl 命令都会报错:

复制代码
kubectl get pods
# Unable to connect to the server: x509: certificate signed by unknown authority

原因:

kubectl 需要读取集群证书才能与 API Server 通信。证书配置存储在 $HOME/.kube/config 文件中,但每次重启后环境变量丢失或配置文件路径不正确,导致 kubectl 找不到正确的证书。

export KUBECONFIG=/etc/kubernetes/admin.conf 能临时解决,但重启后环境变量会丢失。

解决方案:

将配置写入 ~/.bashrc,让每次登录时自动设置环境变量。

复制代码
echo 'export KUBECONFIG=/etc/kubernetes/admin.conf' >> ~/.bashrc
source ~/.bashrc

验证:

复制代码
# 重新登录或执行 source ~/.bashrc 后测试
kubectl get nodes

复盘:

kubectl 默认读取 $HOME/.kube/config,如果该文件不存在或内容不正确,就需要通过 KUBECONFIG 环境变量指定配置文件路径。将环境变量写入 ~/.bashrc 可以保证每次登录都自动生效,避免重复配置。

问题二:数据库迁移后表不存在导致 500 错误

背景:

因实验需要,想把数据库从 node2 迁移到 node1(后来改用 node2 的 /root/k8s-zabbix/ 目录)。迁移后,前端页面无法加载设备列表,后端接口返回 500 错误。

现象:

复制代码
curl http://192.168.116.168:30786/device/list
# 返回 500 Internal Server Error

排查过程:

1. 查看后端日志

复制代码
kubectl logs -l app=iot-backend --tail=200 | grep -E "ERROR|Exception" -A5 -B5

发现关键错误:

复制代码
java.sql.SQLSyntaxErrorException: Table 'iot.device' doesn't exist

2. 进入数据库确认表是否存在

复制代码
kubectl exec -it $(kubectl get pod -l app=iot-database -o jsonpath='{.items[0].metadata.name}') -- mysql -uroot -pjjsg_2yj -e "USE iot; SHOW TABLES;"

输出为空,确认 device 表不存在。

原因:

迁移数据库到新节点后,新创建的 MySQL Pod 是全新的,没有执行 iot.sql 初始化脚本,导致 device 表未创建。

解决方案:

手动创建 device 表:

复制代码
kubectl exec -it $(kubectl get pod -l app=iot-database -o jsonpath='{.items[0].metadata.name}') -- mysql -uroot -pjjsg_2yj iot -e "
CREATE TABLE device (
    device_id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '设备主键',
    device_name VARCHAR(100) NOT NULL COMMENT '设备名称',
    device_type VARCHAR(50) NOT NULL COMMENT '设备类型',
    serial_number VARCHAR(64) NOT NULL COMMENT '序列号',
    status ENUM('online','offline','error','maintenance') NOT NULL DEFAULT 'offline',
    last_heartbeat DATETIME DEFAULT NULL,
    location VARCHAR(255) DEFAULT NULL,
    created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (device_id),
    UNIQUE KEY ux_devices_serial (serial_number)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
"

验证:

bash

复制代码
# 确认表已创建
kubectl exec -it $(kubectl get pod -l app=iot-database -o jsonpath='{.items[0].metadata.name}') -- mysql -uroot -pjjsg_2yj -e "USE iot; SHOW TABLES;"

# 测试后端接口
curl http://192.168.116.168:30786/device/list

最终验证:

浏览器访问 http://192.168.116.168:30081,设备管理功能恢复正常。

复盘:

迁移数据库时,新 Pod 不会自动执行初始化 SQL 脚本。需要手动建表或从备份恢复数据。建议在迁移前先导出数据,迁移后再导入,避免数据丢失。


五、总结

两个问题的核心都是"配置丢失":

问题 原因 解决方案
kubectl 证书失效 环境变量丢失 写入 ~/.bashrc
数据库表不存在 初始化脚本未执行 手动建表或导入备份

Kubernetes 提供了强大的自动化能力,但某些细节(如环境变量持久化、数据迁移)仍需人工介入。记录这些"坑",能帮助自己和他人少走弯路。

相关推荐
eleven_4u5 小时前
RocketMQ相关问题
java·运维·中间件
0+1115 小时前
Linux --DNS与ICMP
linux·运维·服务器
钛生智能5 小时前
OA 流程定制全参数详解(三):环节信息——流程中最核心、参数最多的部分
运维·办公自动化·oa·协同办公·oa办公系统
bjxiaxueliang5 小时前
一文自建STUN:在Ubuntu上分步搭建STUN服务
linux·运维·ubuntu
秦jh_5 小时前
【Docker】镜像、卷原理
运维·docker·容器
小马同学-5 小时前
K8s 命名空间与上下文:Namespace 资源隔离与多集群切换实战
云原生·容器·kubernetes
程序员老赵5 小时前
Docker 部署 XWiki:轻松搭建企业知识库与协作 Wiki
前端·docker·开源
物联网软硬件开发-轨物科技6 小时前
【轨物方案】深度解读开关柜智能感知及一键顺控专家系统
大数据·运维·网络·人工智能·算法·机器人
I'mChloe6 小时前
飞牛NAS部署flatnotes实战:Docker、8080端口、Markdown笔记与固定地址访问
笔记·docker·容器
川石课堂软件测试6 小时前
涨薪技术|0到1学会性能测试第9课-HTTP响应统计
数据库·功能测试·网络协议·http·kubernetes·单元测试·测试用例