02 Ubuntu 24.04 手把手部署 K8s 集群(K3s 选型 + 真实踩坑记录)

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

graph TB subgraph K3s 集群 M[ecs-0001<br>K3s Server<br>192.168.0.112<br>control-plane] W1[ecs-0002<br>K3s Agent<br>192.168.0.111] W2[ecs-0003<br>K3s Agent<br>192.168.0.118] end M --- W1 M --- W2 subgraph 基础设施 R1[containerd 内置<br>CNI: flannel 内置<br>ServiceLB 内置] end M --- R1

选型理由(按网络实际情况)

  1. 镜像可达性 :kubeadm 需要从 registry.k8s.io 拉 kube-apiserver 等 8+ 个系统镜像,国内直连极慢甚至超时;K3s 是单二进制(约 150MB),官方提供国内镜像站(rancher-mirror.rancher.cn),下载稳定。
  2. 依赖少:kubeadm 要额外装 CNI(Flannel/Calico)、CoreDNS、Metrics Server,每个都要拉镜像;K3s 把 flannel、CoreDNS、ServiceLB、Traefik 全内置。
  3. 5Mbit 带宽约束:K3s 整体下载量远小于 kubeadm 全家桶,符合小带宽环境。
  4. 运维简单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.ioquay.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)

相关推荐
袁因1 小时前
多租户隔离该做到哪一层:从连接池到 ORM 的取舍
后端
名字还没想好☜1 小时前
Python 用 tempfile 安全创建临时文件:NamedTemporaryFile、TemporaryDirectory 与别自己拼 /tmp 的坑
开发语言·后端·python·安全·编程语言
lvshuocool1 小时前
golang 多版本管理工具 -- g
开发语言·后端·golang
代码调试师2 小时前
【毕设分享】springboot攀枝花生鲜电商平台58990
java·vue.js·spring boot·后端·架构·eclipse·课程设计
洛阳泰山3 小时前
别卷 Python 了:我用 Java 21 + Spring Boot 3 打造了一个企业级 RAG + 智能体工作流引擎(附架构与源码解析)
java·spring boot·后端
海盗12344 小时前
DSH 接入 OpenCode Go 报 400 MissingSessionID:从 LLM 语义层退到 fetch 传输层的完整排障
开发语言·后端·golang
一木 之林4 小时前
第 3 节 在 AI 行业中,C/C++ 编程中的动态库和静态库
c语言·c++·后端
skywalkerch4 小时前
Spring 循环依赖与三级缓存
后端
萧瑟余晖5 小时前
Hibernate 实体映射与关联关系详解
后端·hibernate