02 Ubuntu 24.04 手把手部署 K8s 集群(K3s 选型 + 真实踩坑记录)
摘要:1 台 5Mbit 小带宽的华为云 ECS 环境里,kubeadm 因镜像源问题屡屡受挫,果断换用 K3s------一条命令装 Server、两条命令加 Agent,10 分钟内 3 节点全部 Ready,本文含镜像加速配置与 3 个真实踩坑。
一、背景与目标
Kubernetes(简称 K8s,容器编排平台的事实标准)部署方式主要分两派:kubeadm (官方推荐,组件全、可定制)和 K3s (Rancher 出品的轻量发行版,单二进制打包,专为资源受限/边缘场景设计)。本文要在 4 台 8C16G、5Mbit 带宽的华为云 ECS 上,搭出 1 Master + 2 Worker 的 3 节点集群,并把踩坑过程完整记录下来。
二、环境说明
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 24.04.4 LTS,内核 6.8.0 |
| 资源 | 8 vCPU / 16 GiB / 40G,带宽 5Mbit |
| 运行时 | 前置已装 Docker 29.1.3 + Containerd 2.2.1(见系列第 01 篇) |
| K3s 版本 | v1.36.4+k3s1(内置 containerd 2.3.4-k3s1.36) |
| 集群拓扑 | 0001=Server(control-plane),0002/0003=Agent(Worker) |
三、架构设计:为什么选 K3s
选型理由(按网络实际情况):
- 镜像可达性 :kubeadm 需要从 registry.k8s.io 拉 kube-apiserver 等 8+ 个系统镜像,国内直连极慢甚至超时;K3s 是单二进制(约 150MB),官方提供国内镜像站(
rancher-mirror.rancher.cn),下载稳定。 - 依赖少:kubeadm 要额外装 CNI(Flannel/Calico)、CoreDNS、Metrics Server,每个都要拉镜像;K3s 把 flannel、CoreDNS、ServiceLB、Traefik 全内置。
- 5Mbit 带宽约束:K3s 整体下载量远小于 kubeadm 全家桶,符合小带宽环境。
- 运维简单 :
k3s kubectl即集群入口,升级回滚都方便,适合教学与中小业务。
四、实操步骤
4.1 关键前置:containerd 镜像加速(K3s 格式!)
K3s 使用自己格式的 registries.yaml(注意:与 containerd 原生格式不同,见踩坑 1):
yaml
# /etc/rancher/k3s/registries.yaml (每台节点)
mirrors:
docker.io:
endpoint:
- "https://docker.m.daocloud.io"
- "https://mirror.ccs.tencentyun.com"
- "https://hub-mirror.c.163.com"
gcr.io:
endpoint:
- "https://gcr.m.daocloud.io"
配置后重启对应服务:Server 节点 systemctl restart k3s,Agent 节点 systemctl restart k3s-agent。
4.2 安装 Server(master)
bash
# 使用国内镜像安装
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn K3S_NODE_NAME=ecs-67e6-753f-0001 \
sh -s - server --node-ip=192.168.0.112 --write-kubeconfig-mode 644 \
--disable traefik --disable metrics-server
参数说明:
--write-kubeconfig-mode 644便于读取 kubeconfig;--disable traefik先关掉内置 Ingress 控制器(后续单独做 Ingress 篇);--disable metrics-server暂不需要。
验证:
text
$ kubectl --kubeconfig=/etc/rancher/k3s/k3s.yaml get nodes
NAME STATUS ROLES AGE VERSION
ecs-67e6-753f-0001 Ready control-plane 66s v1.36.4+k3s1
4.3 加入 Agent(worker × 2)
bash
# 先取 token(内部敏感信息, 只传内存不落日志)
TOKEN=$(cat /var/lib/rancher/k3s/server/node-token)
# worker 节点执行
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
INSTALL_K3S_MIRROR=cn K3S_NODE_NAME=ecs-67e6-753f-0002 \
K3S_URL=https://192.168.0.112:6443 K3S_TOKEN=$TOKEN \
sh -s - agent --node-ip=192.168.0.111
两个 Agent 并发安装,最终集群状态:
text
$ kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP OS-IMAGE CONTAINER-RUNTIME
ecs-67e6-753f-0001 Ready control-plane 19m v1.36.4+k3s1 192.168.0.112 Ubuntu 24.04.4 LTS containerd://2.3.4-k3s1.36
ecs-67e6-753f-0002 Ready <none> 18m v1.36.4+k3s1 192.168.0.111 Ubuntu 24.04.4 LTS containerd://2.3.4-k3s1.36
ecs-67e6-753f-0003 Ready <none> 17m v1.36.4+k3s1 192.168.0.118 Ubuntu 24.04.4 LTS containerd://2.3.4-k3s1.36
3 节点全部 Ready ✅(自动化脚本 scripts/k3s_deploy.py,全程留证于 logs/P0-2-k3s.log)。
五、效果验证
- ✅
kubectl get nodes:3 节点 Ready,版本 v1.36.4+k3s1 - ✅ 节点角色正确:0001 为 control-plane,0002/0003 为 Worker
- ✅ 运行时 containerd 2.3.4-k3s1.36 就绪
- ✅ 无 CrashLoopBackOff / Pending(后续部署验证见第 03 篇)
六、踩坑与解决方案
坑 1:K3s 的 registries.yaml 格式和 containerd 原生不一样(最坑!)
现象 :按 containerd 原生格式写 mirrors.docker.io 下面直接挂 URL 列表,重启后 k3s 一直 activating,日志反复报:
text
yaml: unmarshal errors: line 3: cannot unmarshal !!seq into registries.Mirror
原因 :K3s 的镜像配置要求每个镜像仓库名下是 endpoint: 列表,而不是裸的 URL 数组。 解决:
yaml
mirrors:
docker.io:
endpoint: # ← 必须显式写 endpoint 字段
- "https://docker.m.daocloud.io"
坑 2:Agent 节点没有 /etc/rancher/k3s 目录
现象 :sftp 上传 registries.yaml 报 [Errno 2] No such file。 原因 :Agent 节点的配置目录是 /etc/rancher/node,/etc/rancher/k3s 只有在初始化后才有。 解决 :上传前先 mkdir -p /etc/rancher/k3s。
坑 3:重启 K3s 后长时间 activating
现象 :systemctl restart k3s 后服务一直 activating,5 分钟起不来。 原因 :正是坑 1 的配置错误导致 server 反复解析失败、无法完成自身初始化。 解决 :修正 registries.yaml 格式后重启即恢复(教训:配置文件的语法错误会让守护进程卡死在启动循环里,先查日志再动手)。
坑 4(提醒):镜像加速别只配 docker.io
现象 :cAdvisor 这类 gcr.io 镜像拉取 404/超时(详见第 04 篇)。 解决 :提前把 gcr.io、quay.io 的镜像加速一并配好,避免二次重启集群。
七、总结与延伸
- 选型要贴近现实网络:在国内 5Mbit 环境,K3s 的"单二进制 + 官方国内镜像"优势是压倒性的。
- 配置格式永远以官方文档为准 :K3s registries.yaml 的
endpoint结构是高频翻车点。 - 自动化脚本保证可复现 :
k3s_deploy.py幂等执行,重建集群只需一条命令。
延伸方向:Server 高可用(embedded etcd 模式,3 个 Server 组 HA);Ingress + HTTPS(K3s 内置 Traefik,见后续篇目);Metrics Server + HPA 自动伸缩。
配套源码:gitcode.com/cpyaxjq/k8s... (scripts/k3s_deploy.py、deploy/yaml/registries.yaml、logs/P0-2-k3s.log)