从 Docker 到 K3s:轻量 K8s 集群落地实战,更适合中小业务的云原生升级之路
前言
这周继续咱们的云原生实战系列。前面四周,我们把 Docker 单机环境、多服务编排、自动化运维、故障排查都跑通了,线上业务跑起来基本稳定。但随着服务越来越多,单纯靠 Compose 手动管理,慢慢就有点吃力了:节点多了扩缩容麻烦、服务自愈全靠脚本、监控大盘散在各处。
所以这周我直接把内部在用的 K3s 轻量 K8s 集群 完整落地过程整理出来,不搞花里胡哨的理论,全是能直接复制上线的步骤,也顺便说说为什么中小场景我们更推荐 K3s,而不是直接上完整版 K8s。
一、为什么从 Docker Compose 升级到 K3s,而不是完整版 K8s?
很多人一提到 K8s 就头大:组件多、配置复杂、机器要求高、学习成本吓人。但实际中小业务、内网环境、演示集群这类场景,根本用不到那么重的架构。
我们选择 K3s 的几个很现实的理由:
- 二进制一键安装,不依赖复杂镜像源,内网环境友好
- 内存占用极低,低配机器也能跑,资源利用率比完整版高很多
- 自带 Ingress、LoadBalance、LocalPath 存储,不用额外装一大堆组件
- 兼容原生 K8s 命令,学会 K3s 等于会了大半 K8s
- 适合从 Docker 平滑过渡,不用推翻现有服务重构
简单说:Docker 管单机,Compose 管多服务,K3s 管多节点 + 自愈 + 弹性,又轻又稳。
二、前期准备与环境规划
这次依旧是内网政企环境标准配置,不搞外网花式操作:
- 服务器 2 台(后期可随意扩容):1 台 Master、1 台 Node
- 系统:CentOS 7+ /openEuler 均可
- 关闭 Swap、防火墙放行端口(6443、80、443 等)
- 已有的 Docker 镜像直接复用,不用重新构建
- 内部 Harbor 仓库打通,方便拉取私有业务镜像
整体架构思路很清晰:
- K3s Master:负责调度、认证、API 入口
- K3s Node:运行实际业务 Pod
- 内部 Harbor:统一镜像来源
- Loki + Prometheus:日志 + 监控(后面会专门更)
- Ingress:统一域名入口,替代原来的端口映射
三、K3s 集群安装:一步到位,无坑版
安装过程比想象简单很多,我直接放线上在用的稳定安装方式。
1. Master 节点初始化
curl -sfL http://rancher-mirror.rancher.cn/k3s/v1.30.2+k3s1/install.sh | sh -s - \
--system-default-registry "harbor内网地址" \
--write-kubeconfig-mode 644 \
--tls-san "Master节点IP" \
--disable traefik \
--disable metrics-server
关闭 Traefik 是因为我们后续用更轻量的 Nginx Ingress,更符合内部使用习惯。
安装完查看节点状态:
kubectl get nodes
出现 Ready 就算正常。
2. Node 节点加入集群
先在 Master 上拿 Token:
cat /var/lib/rancher/k3s/server/node-token
在 Node 机器执行:
curl -sfL http://rancher-mirror.rancher.cn/k3s/v1.30.2+k3s1/install.sh | sh -s - \
--system-default-registry "harbor内网地址" \
--kubelet-arg="--node-ip=本机IP" \
K3S_URL=https://MasterIP:6443 \
K3S_TOKEN=上面拿到的Token
再回 Master 查看:
kubectl get nodes
两台都 Ready,集群就算搭建完成。整个过程不超过 5 分钟。
四、把原有 Docker 服务迁移到 K3s:实战步骤
重点来了:之前用 Docker Comppose 跑的服务,怎么平滑挪到 K3s 里?
我以一个典型微服务为例:
- 前端 Web
- 后端 API
- MySQL
- Redis
迁移思路:
- 原有镜像不动,直接从 Harbor 拉取
- Compose yaml 结构 → 翻译成 K8s Deployment + Service + Ingress
- 配置环境变量、挂载目录保持一致,业务无感切换
- 先在测试环境跑通,再上演示 / 生产
1. 编写 Deployment(以业务 API 为例)
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo-api
spec:
replicas: 2
selector:
matchLabels:
app: demo-api
template:
metadata:
labels:
app: demo-api
spec:
containers:
- name: demo-api
image: harbor内网地址/demo/api:v1.3.7
ports:
- containerPort: 8080
env:
- name: SPRING_PROFILES_ACTIVE
value: "test"
- name: MYSQL_HOST
value: "demo-mysql"
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
这里加了资源限制,就是为了避免之前 Docker 下某个服务占满整机资源的问题。
2. Service 暴露服务
apiVersion: v1
kind: Service
metadata:
name: demo-api
spec:
selector:
app: demo-api
ports:
- port: 8080
targetPort: 8080
type: ClusterIP
3. Ingress 统一入口
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: demo-ingress
spec:
rules:
- host: api.demo.local
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: demo-api
port:
number: 8080
应用:
kubectl apply -f .
查看 Pod 状态:
kubectl get pods
全部 Running,服务就启动完成了。
五、迁移中最容易踩的几个坑,我帮你踩完了
这部分是真实踩坑总结,不是 AI 随便凑的,遇到基本都能对上:
1. 挂载目录权限问题
K3s 用容器用户运行,经常出现 MySQL、Redis 挂载后无权限。解决:
- 在宿主机提前 chown 775 对应目录
- 或者在 Deployment 里指定 runAsUser: 1000(和镜像内用户一致)
2. 服务之间 DNS 解析不通
Compose 里直接用服务名互访,K3s 里也是一样,但很多人忘了用 Service 名。解决:
- 用
服务名.命名空间.svc.cluster.local - 测试用 nslookup 服务名 验证 DNS 是否正常
3. 镜像拉取失败
因为是内网环境,不能走公网。解决:
- 安装 K3s 时必须指定
--system-default-registry - 私有镜像仓库在 K3s 中配置
imagePullSecret
4. Ingress 访问不通
- 检查 80/443 是否放开
- 检查 IngressClassName 是否正确
- 本地 hosts 绑定域名,再测试
这些坑踩一遍之后,后面迁移其他服务基本就是复制 yaml 改改名字。
六、K3s 对比原来的 Docker Compose:实际提升在哪?
落地之后最直观的几个变化:
-
服务自动自愈以前容器挂了要靠脚本重启,现在 Pod 挂了 K3s 自动拉起,不用人盯着。
-
一键扩缩容
kubectl scale deployment demo-api --replicas=3
高峰期直接加副本,不用手动起多个容器。
-
统一配置管理ConfigMap、Secret 统一管理,不用每个容器改.env。
-
多节点统一管理以后再加机器,直接加入节点,服务自动调度,不用一台台部署。
-
资源更可控每个服务限制 CPU / 内存,不会出现一个服务打满整个机器的情况。
对中小业务、演示环境、内网项目来说,K3s 真的是性价比极高的选择。
七、下周预告
这周把 K3s 集群搭起来、服务跑起来,只是第一步。下周我会继续更:
- K3s 下的监控体系:Prometheus + Grafana 面板搭建
- 日志统一收集:Loki + Filebeat 完整落地
- 日常常用 kubectl 命令总结,运维必备小抄
- 简单的 CI/CD 思路:提交代码自动更新集群服务
依旧是内网实战、可直接复制、不搞虚的风格。
如果你也在从 Docker 往 K3s/K8s 过渡,或者正在搭轻量集群,欢迎一起交流踩坑经验~
更多推荐


所有评论(0)