从零搭建 K3s 混合集群:云服务器+NAS+PC 的踩坑实录

2026年04月29日2 次阅读0 人喜欢
踩坑记录技术运维
所属合集

前言

最近想把我的零刻 NAS、PC 和腾讯云服务器组成一个 Kubernetes 集群,实现算力和存储的最优组合。经过一番折腾,终于成功搭起来了。本文记录完整的搭建过程和踩过的坑。

架构设计

设备清单

设备 角色 配置 说明
腾讯云服务器 Control Plane 4GB 内存 / CentOS 7 24h 在线,公网 IP:vpc.nnnnzs.cn
零刻 NAS (linke-me-mini) Worker Node Debian 12 (飞牛OS) 持久化存储,ZeroTier IP:192.168.193.194
PC Worker Node 可用性较低,算力强 临时加入用于重计算任务

角色分配原则

  • 控制平面(Server):选择腾讯云服务器,因为:

    • 24h 在线,稳定性高
    • 有公网 IP,方便跨地域节点接入
    • 资源隔离,不会影响本地服务
  • 工作节点(Agent):NAS 和 PC 作为工作节点

    • NAS 提供持久化存储(NFS/Local Path)
    • PC 提供强劲算力(编译、AI 推理等)

踩坑实录

坑一:版本兼容性问题

现象:

NAS 先安装了 K3s v1.35.4,服务器安装了 v1.28.10,导致 NAS 无法加入集群。

原因:

Kubernetes 要求 master 版本 ≥ worker 版本

解决方案:

bash 复制代码
# 在 NAS 上降级到与服务端匹配的版本
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_VERSION=v1.28.10+k3s1 \
  INSTALL_K3S_MIRROR=cn \
  sh -

坑二:内存不足导致服务频繁重启

现象:

服务器上 K3s 启动后立即崩溃,systemctl status k3s 显示 activating (auto-restart),日志里全是 context canceledClosing database connections

原因:

  1. 内存压力:服务器同时运行了 Java 后端服务(scm-backend,JVM 堆内存 1GB),可用内存仅剩 900MB
  2. 无 Swap:没有交换空间,系统内存不足时直接杀进程
  3. 组件启动开销:K3s 启动时需要约 500MB-1GB 内存初始化 Traefik、Metrics Server 等组件

解决方案:

  1. 开启 Swap(必须有!)

    bash 复制代码
    # 分配 2GB Swap
    sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    # 永久生效
    echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
  2. 暂时停掉内存大户

    bash 复制代码
    docker compose down  # 停止 scm-backend
  3. 精简启动参数(禁用非必要组件)

    bash 复制代码
    curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
      INSTALL_K3S_MIRROR=cn \
      INSTALL_K3S_EXEC="server \
        --disable traefik \
        --disable servicelb \
        --write-kubeconfig-mode 644" \
      sh -

坑三:cgroup v1/v2 冲突

现象:

日志报错:

复制代码
Error: failed to validate kubelet configuration, error: kubelet is configured to not run on a host using cgroup v1. cgroup v1 support is unsupported and will be removed in a future release

原因:

K3s 新版本默认要求 cgroup v2,但 CentOS 7 内核只支持 cgroup v1。

解决方案:

bash 复制代码
# 添加兼容参数
INSTALL_K3S_EXEC="server \
  --disable traefik \
  --disable servicelb \
  --write-kubeconfig-mode 644 \
  --kubelet-arg=config-confusable-cgroup-v1-with-v2=true"

坑四:systemd 配置不生效

现象:

修改了 /etc/systemd/system/k3s.service,但 ps -ef | grep k3s 显示进程完全没有加载任何参数。

原因:

systemd 的 ExecStart 多行书写格式极其敏感,反斜杠 \ 后面如果有空格会导致后续行被忽略。

解决方案:

方法一:使用环境变量(推荐)

创建 /etc/systemd/system/k3s.service.env

复制代码
K3S_EXEC="server --disable=traefik --disable=servicelb --write-kubeconfig-mode=644 --kubelet-arg=config-confusable-cgroup-v1-with-v2=true"

然后在 k3s.service 中:

ini 复制代码
ExecStart=/usr/local/bin/k3s $K3S_EXEC

方法二:一行写法

ini 复制代码
ExecStart=/usr/local/bin/k3s server --disable=traefik --disable=servicelb --write-kubeconfig-mode=644 --kubelet-arg=config-confusable-cgroup-v1-with-v2=true

坑五:节点地址被服务器覆盖

现象:

NAS 配置了 K3S_URL=https://192.168.80.100:6443(服务器 ZeroTier IP),但日志显示一直在尝试连接 10.0.4.2:6443(服务器内网 IP)。

原因:

K3s 的服务发现机制会自动广播服务器的「最佳 IP」。服务器有两个网卡:

  • 公网/ZeroTier:192.168.80.100
  • 腾讯云内网:10.0.4.2

服务器默认会告诉 Agent:「用 10.0.4.2 连我」,而 NAS 根本访问不到这个地址。

解决方案:

在服务器启动时强制指定对外通告地址:

bash 复制代码
# 修改 /etc/systemd/system/k3s.service
INSTALL_K3S_EXEC="server \
  --node-ip=192.168.80.100 \
  --advertise-address=192.168.80.100 \
  --disable traefik \
  --disable servicelb \
  --write-kubeconfig-mode 644"

参数说明:

  • --node-ip:绑定指定网卡
  • --advertise-address:向其他节点通告这个 IP

重启后验证:

bash 复制代码
kubectl get nodes -o wide
# 应该看到 INTERNAL-IP 变成 192.168.80.100

坑六:国内网络环境问题

现象:

  • GitHub 下载极慢,经常超时
  • 容器镜像拉取失败(ErrImagePullImagePullBackOff

解决方案:

  1. 使用国内镜像

    bash 复制代码
    INSTALL_K3S_MIRROR=cn
  2. 配置容器镜像加速器

    创建 /etc/rancher/k3s/registries.yaml

    yaml 复制代码
    mirrors:
      docker.io:
        endpoint:
          - "https://mirror.ccs.tencentyun.com"
          - "https://hub-mirror.c.163.com"

最终成功的安装流程

服务器端(Control Plane)

bash 复制代码
# 1. 清理旧环境
sudo systemctl stop k3s
sudo rm -rf /var/lib/rancher/k3s

# 2. 开启 Swap(如果还没开)
sudo dd if=/dev/zero of=/swapfile bs=1M count=2048
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile

# 3. 安装(带所有优化参数)
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_MIRROR=cn \
  INSTALL_K3S_EXEC="server \
    --node-ip=192.168.80.100 \
    --advertise-address=192.168.80.100 \
    --disable traefik \
    --disable servicelb \
    --write-kubeconfig-mode 644" \
  sh -

# 4. 验证
sudo systemctl status k3s
kubectl get nodes -o wide

NAS 端(Worker Node)

bash 复制代码
# 1. 获取服务器 Token
# 在服务器上执行:
# cat /var/lib/rancher/k3s/server/node-token

# 2. 加入集群
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh | \
  INSTALL_K3S_VERSION=v1.28.10+k3s1 \
  INSTALL_K3S_MIRROR=cn \
  K3S_URL=https://192.168.80.100:6443 \
  K3S_TOKEN=K105fb7352c16cdee39f39043da59ab9dccfa257660ce36b2bd4cf32737de0a7dfc::server:3c659f37c48a02c9a14caaa70f9dbc41 \
  INSTALL_K3S_EXEC="--node-name nas-worker" \
  sh -

# 3. 验证
kubectl get nodes -o wide
# 应该看到两个节点:
# NAME             STATUS   ROLES           AGE   VERSION
# vm-4-2-centos   Ready    control-plane   10m   v1.28.10+k3s1
# nas-worker       Ready    <none>         8m    v1.28.10+k3s1

验证集群

bash 复制代码
# 查看节点状态
kubectl get nodes -o wide

# 查看系统组件
kubectl get pods -A

# 部署测试应用
kubectl create deployment nginx --image=nginx:alpine --replicas=2
kubectl get pods -o wide

常用命令参考

集群管理

bash 复制代码
# 查看节点
kubectl get nodes -o wide

# 查看组件
kubectl get pods -A

# 查看服务
kubectl get svc -A

# 查看事件(排查神器)
kubectl get events -A --sort-by='.lastTimestamp'

故障排查

bash 复制代码
# 查看服务状态
systemctl status k3s       # 服务器端
systemctl status k3s-agent  # 工作节点端

# 查看实时日志(错误和警告)
journalctl -u k3s -p err..warn -f
journalctl -u k3s-agent -p err..warn -f

# 手动启动(前台运行,直接看报错)
/usr/local/bin/k3s server --disable traefik
/usr/local/bin/k3s agent -s https://192.168.80.100:6443 -t $TOKEN

彻底卸载

bash 复制代码
# 服务器端
sudo /usr/local/bin/k3s-uninstall.sh

# 工作节点端
sudo /usr/local/bin/k3s-agent-uninstall.sh

# 手动清理残留(如果卸载脚本找不到)
sudo rm -rf /var/lib/rancher/k3s /etc/rancher/k3s
sudo systemctl daemon-reload

总结

搭建 K3s 集群看似简单,但在国内环境和资源受限的服务器上,踩坑几乎是不可避免的。本文记录的 6 个主要坑点,涵盖了版本兼容性、资源管理、网络配置、内核参数等多个维度。

关键经验:

  1. 版本对齐:master 版本必须 ≥ worker 版本
  2. 内存是第一生产力:小内存服务器务必开启 Swap,精简启动参数
  3. 地址强制:多网卡环境下务必用 --node-ip--advertise-address 固定集群通信地址
  4. systemd 很挑剔:多行配置用环境变量或一行写法,避免反斜杠陷阱
  5. 国内加速:镜像源和容器注册表都要配置国内镜像
  6. 验证 > 猜测:每次改动后用 kubectl get nodes 验证,不要假设配置生效

现在这个混合集群已经稳定运行,接下来可以在上面部署一些有用的服务,比如:

  • 存储类:NFS Provisioner 实现 NAS 存储共享
  • Ingress:安装 Traefik 或 Nginx Ingress Controller
  • 监控:安装 Prometheus + Grafana 监控集群状态
  • CI/CD:部署 GitLab Runner 或 Jenkins 实现 CI/CD

如果你也想搭建类似的集群,希望本文能帮你少走弯路!有问题欢迎交流。

加载评论中...