k0s无需systemd因单二进制静态链接核心组件,但离线部署需手动补全iptables、ip、modprobe等系统工具及so依赖,并正确配置service路径、worker join Token和containerd镜像导入。

为什么 k0s 不需要 systemd 也能跑,但离线部署必须手动处理二进制依赖
k0s 本身是单二进制,k0s 文件里已静态链接了大部分运行时(比如容器运行时、etcd),但实际启动时仍会调用系统级工具:比如 iptables、modprobe、sysctl。这些不是 k0s 自带的,离线环境若没预装,节点会卡在 “waiting for node to be ready” 或报 failed to setup iptables rules。
实操建议:
- 离线前,在同构系统(相同 OS 版本 + 架构)上运行
k0s install controller并观察日志,用strace -e trace=execve k0s start捕获所有外部命令调用 - 把缺失的二进制(如
iptables、ip、modprobe、sysctl)连同它们的 so 依赖(用ldd检查)一并打包进离线介质 - 别指望用
--disable-components关掉网络策略就能绕过 iptables——kube-proxy默认启用,且 k0s v1.28+ 强制校验iptables可用性
k0s air-gapped 部署时,如何让 worker 节点跳过 controller 的 TLS 证书校验
离线环境下,controller 的证书通常是自签名的,worker 启动时默认会校验 CA,失败就停在 failed to join cluster: x509: certificate signed by unknown authority。这不是 bug,是设计行为。
实操建议:
- 不要改 worker 的
k0s.yaml去删 CA 字段——k0s 会拒绝加载不完整配置 - 正确做法是在 controller 初始化时,用
--config指定含spec.api.tlsSan和spec.network.podCIDR的配置,并提前生成好 CA;或更简单:用k0s token create --role=worker --expiry=24h生成带嵌入式 CA 的 join token - token 本质是 base64 编码的 json,里面包含
ca.crt内容,worker 用它 join 就自动信任,无需额外传证书文件 - 注意 token 有效期:离线环境无法自动续期,务必用
--expiry设长一点,比如8760h(1年)
离线集群里,k0s 如何加载本地 containerd 镜像而不依赖 registry
k0s 默认用 containerd,但它不支持直接从本地 tar 文件加载镜像(像 docker load 那样)。如果离线环境没搭 registry,又想预置 coredns、kube-proxy 等镜像,容易卡在 ImagePullBackOff。
实操建议:
- 先在有网机器上用
ctr --Namespace=k8s.io images pull拉取所需镜像,再用ctr --namespace=k8s.io images export coredns.tar ghcr.io/coredns/coredns:1.11.3导出为 tar - 离线节点上,用
ctr --namespace=k8s.io images import coredns.tar导入——注意 namespace 必须是k8s.io,否则 k0s 容器运行时不认 - 别用
nerdctl或docker save/load替代:containerd 的镜像存储格式和 layer 解析逻辑与 docker 不完全兼容,导入后可能显示missing blob - 验证是否成功:
ctr --namespace=k8s.io images list | grep coredns,看到 status 是ready才算真正可用
k0s v1.27+ 离线安装时,systemd 服务文件为什么不能直接用 k0s install 生成
k0s install 默认生成的 systemd unit 会写死 ExecStart=/usr/bin/k0s,并依赖 /usr/bin/k0s 存在。但在 air-gapped 场景下,你很可能把 k0s 放在 /opt/k0s/k0s 这类自定义路径,直接运行 install 会导致服务启动失败,报 Failed at step EXEC spawning /usr/bin/k0s: No such file or Directory。
实操建议:
- 不要运行
k0s install,改用手动创建 service 文件:sudo cp k0s /opt/k0s/k0s && sudo chmod +x /opt/k0s/k0s - 用
k0s default-config > k0s.yaml生成基础配置,修改其中spec.dataDir指向离线路径(如/opt/k0s/data) - service 文件里明确写
ExecStart=/opt/k0s/k0s server --config /opt/k0s/k0s.yaml,并加Environment="K0S_DATA_DIR=/opt/k0s/data" - 特别注意:k0s v1.28 开始,
k0s install加了--bin-dir参数,但仅限 controller;worker 仍不支持,必须手写 service
离线部署最麻烦的从来不是 k0s 本身,而是它默许依赖的那些“系统常识”——比如哪个路径该有 iptables,哪个 namespace containerd 认,甚至 systemd 服务里一个硬编码路径。这些细节不记日志、不报明确错误,只让你等在 “node not ready” 里干瞪眼。