1. 为什么树莓派跑 K8s 总翻车,K3s 才是正解
如果你手里有三块树莓派、一堆 SD 卡和一根网线,大概率动过「搭个 K8s 集群」的念头。我最早也是这么干的,照着网上教程把标准 Kubernetes 装上去,结果 master 节点内存直接吃满,kube-apiserver 和 etcd 抢资源,跑个kubectl get nodes都要等十几秒,升级更是想都别想。树莓派的 ARM 架构和有限内存,天生不适合跑完整版 K8s 那一整套控制平面。
K3s 就是为这种资源受限场景设计的轻量级 Kubernetes 发行版,由 Rancher 团队维护,二进制体积小、默认集成了 Traefik 反向代理和本地存储,还专门针对 ARM 做了优化。它把 etcd 换成了 SQLite(单节点场景),控制平面内存占用能压到几百 MB,三块树莓派 4B 跑起来完全够用。
但集群搭起来只是第一步。真正让人头疼的是:多节点环境下,每个节点上的组件(比如监控 Agent、CI Runner、AI 辅助编码工具)都要单独配 API Key,改一次配置就得 SSH 到每台机器上重复操作,密钥散落在各个节点上,轮换起来简直是灾难。这篇教程除了带你把三节点 K3s 集群跑通,还会用 TaoToken 的统一 Key 和 API 通道,把集群组件的接入配置收敛到一处,节点初始化、Token 分发、配置验证一条龙走完。
适合谁看:有树莓派、想学 K8s 但被资源问题劝退的开发者;已经在跑多节点集群、被密钥管理搞烦的运维同学;以及想用统一 API 通道接入 AI 编码能力的团队。
2. 前置准备:TaoToken 统一 Key 与集群规划
2.1 硬件与网络规划
我用的配置是 3 块树莓派 4B(4GB 内存版),每块配 32GB SD 卡和独立电源,通过交换机接到同一路由器下。IP 规划如下,你按自己网段替换即可:
| 主机名 | 角色 | 静态 IP | 内存 |
|---|---|---|---|
| kmaster | server(控制平面) | 192.168.0.50 | 4GB |
| knode1 | agent(工作节点) | 192.168.0.51 | 4GB |
| knode2 | agent(工作节点) | 192.168.0.52 | 4GB |
先在你的 PC 上把主机名写进 hosts 文件,后面 SSH 和 kubectl 都靠它:
echo -e "192.168.0.50\tkmaster" | sudo tee -a /etc/hosts echo -e "192.168.0.51\tknode1" | sudo tee -a /etc/hosts echo -e "192.168.0.52\tknode2" | sudo tee -a /etc/hosts2.2 为什么要在集群里引入 TaoToken
集群跑起来之后,你迟早要在节点上跑一些需要调用大模型 API 的组件——比如 AI 辅助的代码审查 Runner、日志异常检测 Agent、或者团队内部的编码助手。传统做法是给每个节点单独申请 Key、单独写配置文件,节点一多就乱。
TaoToken 提供的是统一 Key 和统一 API 通道:你只需要在控制台生成一个 Key,所有节点上的组件都通过同一个 API 地址接入,配置分发变成「改一处、同步全部」。它的 API 地址是https://taotoken.net/api,兼容主流模型调用格式,接入成本很低。
注意:TaoToken 是合法的 API 聚合服务,本文只把它当作集群组件的统一接入通道来用,不涉及任何网络代理配置。
2.3 获取统一 Key
登录 TaoToken 控制台,在 API Keys 页面创建一个新 Key,建议按集群维度命名,比如k3s-cluster-prod,方便后续轮换时定位。创建后把 Key 复制到安全的地方,后面配置分发会用到。
控制台入口:https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=k3s_cluster_console
API Keys 管理页:https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=k3s_cluster_apikeys
3. 可复制配置:节点初始化与统一 Key 分发
3.1 安装 master 节点
在 kmaster 上刷好 Raspberry Pi OS(64 位),启用 SSH,设置主机名和静态 IP。然后 SSH 进去装 K3s:
ssh pi@kmaster curl -sfL https://get.k3s.io | sh -装完后验证单节点集群:
sudo kubectl get nodes正常输出类似:
NAME STATUS ROLES AGE VERSION kmaster Ready control-plane,master 2m v1.28.2+k3s13.2 提取 join token 并安装 worker 节点
从 master 上取出节点注册用的 token:
sudo cat /var/lib/rancher/k3s/server/node-token复制这串 token,然后分别 SSH 到 knode1 和 knode2,用下面的命令加入集群(把JOIN_TOKEN替换成刚复制的值):
curl -sfL https://get.k3s.io | \ K3S_URL=https://192.168.0.50:6443 \ K3S_TOKEN=JOIN_TOKEN \ sh -两个 worker 都执行完后,回到 master 验证:
sudo kubectl get nodes你应该看到三个节点全部 Ready:
NAME STATUS ROLES AGE VERSION kmaster Ready control-plane,master 10m v1.28.2+k3s1 knode1 Ready <none> 2m v1.28.2+k3s1 knode2 Ready <none> 1m v1.28.2+k3s13.3 统一 Key 的配置骨架
接下来是重点:把 TaoToken 的统一 Key 做成集群级别的配置,让所有节点上的组件都能读到同一份。我用的是 Kubernetes Secret + ConfigMap 的组合,Secret 存 Key,ConfigMap 存 API 地址和模型参数。
先创建命名空间:
sudo kubectl create namespace ai-tools然后写一个taotoken-secret.yaml:
apiVersion: v1 kind: Secret metadata: name: taotoken-credentials namespace: ai-tools type: Opaque stringData: api-key: "sk-你的TaoToken统一Key"再写taotoken-config.yaml,把 API 地址和默认模型固化下来:
apiVersion: v1 kind: ConfigMap metadata: name: taotoken-config namespace: ai-tools data: base-url: "https://taotoken.net/api" default-model: "claude-sonnet-4-5" timeout-seconds: "60"应用这两个配置:
sudo kubectl apply -f taotoken-secret.yaml sudo kubectl apply -f taotoken-config.yaml3.4 节点侧 config.toml 与 settings.json 骨架
如果你的节点上跑的是需要读本地配置文件的组件(比如某些 CLI 工具或 Agent),可以用 DaemonSet 把配置挂载到每个节点的固定路径。下面是一个config.toml骨架,放在/etc/ai-tools/config.toml:
[api] base_url = "https://taotoken.net/api" api_key_env = "TAOTOKEN_API_KEY" timeout = 60 [model] default = "claude-sonnet-4-5" fallback = "gpt-4o-mini" [cluster] node_role = "agent" report_interval = 30对应的settings.json骨架,放在/etc/ai-tools/settings.json:
{ "api": { "baseUrl": "https://taotoken.net/api", "apiKeyEnv": "TAOTOKEN_API_KEY", "timeoutSeconds": 60 }, "model": { "default": "claude-sonnet-4-5", "fallback": "gpt-4o-mini" }, "cluster": { "nodeRole": "agent", "reportIntervalSeconds": 30 } }这两个文件的关键点是:不把 Key 写死在文件里,而是通过环境变量TAOTOKEN_API_KEY注入。这样 Secret 轮换时只需要更新 Secret,不用改节点上的文件。
4. 验证请求:从集群内确认统一通道可用
4.1 用临时 Pod 验证 API 连通性
配置应用后,最直接的验证方式是起一个临时 Pod,从集群内部发起一次模型调用请求:
sudo kubectl run taotoken-test \ --rm -it \ --namespace ai-tools \ --image=curlimages/curl:latest \ --restart=Never \ --env="TAOTOKEN_API_KEY=$(sudo kubectl get secret taotoken-credentials -n ai-tools -o jsonpath='{.data.api-key}' | base64 -d)" \ -- sh -c 'curl -s -o /dev/null -w "%{http_code}" \ -X POST https://taotoken.net/api/v1/messages \ -H "x-api-key: $TAOTOKEN_API_KEY" \ -H "content-type: application/json" \ -d "{\"model\":\"claude-sonnet-4-5\",\"max_tokens\":16,\"messages\":[{\"role\":\"user\",\"content\":\"ping\"}]}"'如果返回200,说明集群内部到 TaoToken 的统一通道是通的。返回401就是 Key 没注入对,返回404检查 base URL 有没有多写或少写路径。
4.2 验证节点注册状态
确认三个节点都正常注册,并且 K3s 的 agent 进程在跑:
sudo kubectl get nodes -o wide sudo systemctl status k3s-agent # 在 worker 节点上执行 sudo systemctl status k3s # 在 master 节点上执行4.3 验证配置分发是否生效
在任意一个 worker 节点上,确认 ConfigMap 和 Secret 已经挂载到预期路径:
sudo kubectl exec -n ai-tools <pod-name> -- cat /etc/ai-tools/config.toml如果你用的是 DaemonSet 分发,可以在每个节点上检查文件是否存在、内容是否一致。这一步能帮你提前发现「配置只同步了一半节点」这类问题。
5. 本篇常见错排查
5.1 worker 节点一直 NotReady
最常见的原因是 join token 过期或写错。K3s 的 node-token 在 master 重启后不会变,但如果你重装过 master,旧 token 就失效了。重新从/var/lib/rancher/k3s/server/node-token取一次,在 worker 上先卸载再重装:
/usr/local/bin/k3s-agent-uninstall.sh # 然后重新执行加入命令另一个原因是时间不同步。树莓派没有 RTC,断电后时间会漂移,节点间时间差超过几秒就会导致证书校验失败。在所有节点上装 NTP:
sudo apt update && sudo apt install -y systemd-timesyncd sudo systemctl enable --now systemd-timesyncd timedatectl status5.2 API 请求返回 401 或 403
先确认 Secret 里的 Key 没有多余空格或换行。用这条命令检查解码后的值:
sudo kubectl get secret taotoken-credentials -n ai-tools -o jsonpath='{.data.api-key}' | base64 -d | xxd | head如果末尾有0a(换行符),说明 YAML 里 Key 后面多了空行,删掉重新 apply。另外确认 Pod 的环境变量确实引用了这个 Secret,而不是写死的旧值。
5.3 节点内存不足导致 Pod 被驱逐
树莓派 4B 的 4GB 内存跑 K3s 够用,但如果你在节点上又跑了监控、日志收集等组件,容易触发 OOM。给 K3s 的 kubelet 预留资源:
# 在 /etc/rancher/k3s/config.yaml 中添加 sudo tee /etc/rancher/k3s/config.yaml <<EOF kubelet-arg: - "system-reserved=memory=512Mi" - "eviction-hard=memory.available<256Mi" EOF sudo systemctl restart k3sworker 节点对应改/etc/rancher/k3s/config.yaml后重启k3s-agent。
5.4 kubectl 从 PC 访问报证书错误
从 master 复制/etc/rancher/k3s/k3s.yaml到 PC 的~/.kube/config后,要把server: https://127.0.0.1:6443改成server: https://kmaster:6443,否则证书里的 SAN 对不上。改完记得chmod 600 ~/.kube/config。
6. 后续怎么用:统一通道接入更多集群组件
集群跑通之后,你可以把 TaoToken 的统一 Key 复用到更多场景。比如在集群里部署一个 AI 代码审查 Runner,让它监听 Git 仓库的 webhook,自动对 PR 做 review;或者跑一个日志异常检测 Agent,把 K3s 的容器日志喂给模型做实时分析。这些组件都通过同一个taotoken-configConfigMap 读取 API 地址和模型参数,Key 只在 Secret 里维护一份。
如果你主要用模型对话来调试 prompt 和验证输出格式,可以直接在网页端试:
模型对话入口:https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=k3s_cluster_chat
如果团队要长期在集群里跑编码 Agent、CI 辅助这类高频调用场景,Coding Plan 的额度模型比按次计费更划算:
Coding Plan:https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=k3s_cluster_codingplan
接入文档里有完整的 API 参数说明和错误码对照,排障时对着查很快:
接入文档:https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=k3s_cluster_doc
最后提醒一句:树莓派集群的 SD 卡是消耗品,建议把 K3s 的数据目录挂到 USB SSD 上,能显著降低 SD 卡写坏导致节点掉线的概率。我三块 Pi 里已经写坏过两张卡了,换 SSD 之后稳定跑了半年多。