从 Docker Compose 到 Kubernetes:物联网管理系统迁移实战
本文记录一次真实的迁移实验过程,包含踩过的坑、解决的思路、以及复盘思考。适合正在学习 K8S 并希望理解"为什么"的读者。
一、背景与目标
为什么做这次迁移?
物联网管理系统原采用 Docker Compose 部署,结构简单:前端 Nginx + 后端 Spring Boot + MySQL。但单机部署存在单点故障、无法扩缩容、发布需停服等问题。
Kubernetes 正是为了解决这些问题而生。本次实验目标:将这套系统迁移到 K8S 集群,体验从"单机编排"到"集群调度"的转变。
二、环境准备
2.1 资源规划
| 角色 | 主机名 | IP 地址 |
|---|---|---|
| Master | master | 192.168.116.168 |
| Node1 | node1 | 192.168.116.169 |
| Node2 | node2 | 192.168.116.170 |
2.2 软件版本
-
操作系统:CentOS 7.9
-
Docker:20.10.24
-
Kubernetes:v1.20.15(kubeadm + kubelet + kubectl)
-
网络插件:Flannel
2.3 系统配置(所有节点)
关闭 SELinux、防火墙、Swap,配置主机名和 hosts 文件。
为什么不展开写? 这些是标准操作,网上一搜一大把,本文重点放在"卡住的地方"。有需要我后面可发出来
三、目录结构
/root/k8s-experiment/
├── iot-1.0.0.jar # 后端 JAR
├── iot.sql # 数据库 SQL
├── iot-manage-front/ # 前端静态文件
├── iot-project/ # 镜像构建目录
│ ├── backend/Dockerfile
│ ├── frontend/Dockerfile
│ ├── frontend/nginx.conf
│ └── database/Dockerfile
└── k8s/ # K8S 部署文件
├── iot-backend-deploy.yaml
├── iot-database-deploy.yaml
└── iot-frontend-deploy.yaml
四、核心挑战与解决方案
🔥 挑战 1:虚拟机无法拉取基础镜像
现象 :docker pull 始终超时,即使配置了国内镜像加速器。
原因:实验环境虚拟机完全无法访问外网(公司网络 + 网关双重限制)。
解决方案:离线导入
- 在 Windows 上拉取镜像 →
docker save导出.tar→ 上传到 master →docker load导入

复盘:网络隔离环境下,跳板机拉取 + 离线包传输是标准方案。
🔥 挑战 2:openjdk:11-jre-slim 镜像已废弃
现象 :not found
原因:OpenJDK 官方镜像已迁移到 Eclipse Temurin。
解决方案 :改用 eclipse-temurin:11-jre
🔥 挑战 3:kubeadm init 失败,kubelet 无法启动
现象:
执行 kubeadm init 后卡住,最终报错:
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed
kubelet isn't running or healthy
timed out waiting for the condition
查看 kubelet 状态:
systemctl status kubelet
查看详细日志:
journalctl -xeu kubelet -n 50
关键错误信息:
no such file or directory: /var/run/dockershim.sock
transport: Error while dialing dial unix /var/run/dockershim.sock
检查 Docker socket 是否存在:
ls -la /var/run/*.sock
输出显示只有 /var/run/docker.sock,没有 dockershim.sock
确认版本:
kubelet --version # Kubernetes v1.22.4
docker --version # Docker version 20.10.24
原因:
Kubernetes v1.22 正式移除了内置的 dockershim 组件。实验手册的配置方式(通过 /var/run/dockershim.sock 连接 Docker)在该版本中已失效。
解决方案:
降级到最后一个原生支持 dockershim 的版本 v1.20.15:
# 清理失败状态
kubeadm reset -f
# 卸载 1.22
yum remove -y kubelet-1.22.4 kubeadm-1.22.4 kubectl-1.22.4
# 安装 1.20.15
yum install -y kubelet-1.20.15 kubeadm-1.20.15 kubectl-1.20.15
# 锁定版本
yum versionlock kubelet kubeadm kubectl
# 重启服务
systemctl restart docker kubelet
#重新初始化
kubeadm init --image-repository=registry.aliyuncs.com/google_containers --pod-network-cidr=10.244.0.0/16
验证:
复盘:
K8S v1.22 已移除 dockershim,实验手册的版本要求与实际配置存在偏差。降级到 v1.20.15 可保持与手册一致。遇到类似问题,建议先确认 Kubernetes 与容器运行时的版本兼容性矩阵。
🔥 挑战 4:Pod 镜像拉取失败与存储卷问题
现象:
原因:
-
ImagePullBackOff / ErrImagePull:镜像只存在于 master 节点,Pod 被调度到 node2,K8S 无法跨节点拉取
-
Pending:数据库 Pod 使用了 PVC,但集群中没有匹配的 PV
解决过程:
# 步骤1:将镜像分发到 node2
docker save iot-backend:1.0 -o iot-backend.tar
docker save iot-database:1.0 -o iot-database.tar
docker save iot-frontend:1.0 -o iot-frontend.tar
scp *.tar root@192.168.116.170:/root/
ssh root@192.168.116.170 "docker load -i /root/iot-backend.tar && docker load -i /root/iot-database.tar && docker load -i /root/iot-frontend.tar"
# 步骤2:创建 PV 解决数据库存储问题
ssh root@192.168.116.170 "mkdir -p /data/mysql"
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: PersistentVolume
metadata:
name: mysql-pv
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /data/mysql
EOF
# 步骤3:删除旧 Pod 触发重建
kubectl delete pod --all
结果:成功访问前端页面
复盘:
-
K8S 集群中每个 worker 节点都需要有镜像,离线环境需手动分发
-
Deployment 使用 PVC 前必须确保 PV 存在,否则 Pod 无法调度
-
三个问题相互独立但同时出现,解决顺序:先分发镜像 → 再创建 PV → 重建 Pod
今日进度:集群搭建完成,后端和前端服务已成功运行,数据库存储问题正在排查中。
本实验从零开始,所有操作均为本人手搓。由于环境(CentOS 7.9 + 内网隔离)和手册版本偏差,踩了不少坑。文中记录的每一个错误、每一行命令,都是真实复现而非预演。
如果觉得内容对你有帮助,欢迎 点赞 + 关注,你的支持是我持续输出的动力。有任何问题或更好的思路,也请在评论区指正交流











