k0s 的 manifests 目录默认在 /var/lib/k0s/manifests,不可通过命令行修改,但可通过配置文件 spec.extensions.manifests 字段或符号链接方式更改;air-gapped 环境需用 ctr -n k8s.io images import 导入镜像,并确保 manifests 中镜像使用 digest 或本地 registry 地址,同时确认 containerd snapshotter(如 overlayfs)正常且 manifest 文件权限为 644。

manifests 目录在哪?能不能改?
k0s 默认把 manifests 目录设在 /var/lib/k0s/manifests,启动时自动加载该目录下所有 *.yaml 文件。它不能通过命令行参数直接改路径,但可以改——靠修改 k0s 配置文件里的 spec.extensions.helm 或 spec.extensions.manifests 字段(取决于你用的是原生 manifests 还是 Helm 扩展)。不过注意:如果只是想换位置,别动配置,直接用符号链接更稳妥,比如:
rm -rf /var/lib/k0s/manifests<br>ln -s /opt/my-manifests /var/lib/k0s/manifests这样既不影响 k0s 启动逻辑,又避开权限和路径硬编码问题。
air-gapped 环境下怎么让 k0s 加载离线镜像
k0s 本身不提供“镜像导入”命令,它依赖底层 containerd。所以真正要操作的是 containerd 的 ctr 工具。常见错误是直接用 docker load ——没用,k0s 不用 dockerd。正确流程是:
- 把镜像导出为 tar 包(在有网机器上):
ctr -n k8s.io images export calico-node.tar docker.io/calico/node:v3.26.1
- 把
calico-node.tar拷进 air-gapped 节点 - 导入到 k0s 使用的 containerd namespace:
ctr -n k8s.io images import calico-node.tar
- 确认导入成功:
ctr -n k8s.io images list | grep calico
注意:namespace 必须是 k8s.io,不是 default;否则 k0s 调度时找不到镜像,Pod 会卡在 ImagePullBackOff。
manifests 里引用的镜像怎么确保离线可用
manifests 文件本身不解决镜像拉取问题,只负责声明资源。如果你的 Deployment 里写的是 image: nginx:alpine,k0s 会在 runtime 尝试从 Docker Hub 拉——这在 air-gapped 环境必然失败。必须提前做两件事:
- 把所有 manifest 中的
image:字段替换成本地 registry 地址或完整 digest,比如image: my-registry.local/nginx:alpine@sha256:abc123... - 确保该镜像已用
ctr images import导入,并且 tag 和 digest 完全匹配(tag 可以省略,但 digest 必须一致) - 避免使用
latest标签——离线环境无法解析,containerd 会报failed to resolve reference
顺带一提:k0s 的 k0s ctr 是个 wrapper,等价于 ctr -n k8s.io,可以用它简化命令,但别指望它自动处理镜像重定向。
为什么改了 manifests 目录、也导入了镜像,Pod 还是起不来
最常被忽略的是 containerd 的 snapshotter 配置。k0s 默认用 overlayfs,但如果节点文件系统不支持(比如某些 ext4 挂载选项不对),或者你手动改过 /etc/containerd/config.toml,就可能触发 failed to prepare overlay mount。此时即使镜像存在、manifest 正确,Pod 也会卡在 ContainerCreating。检查方式:
sudo journalctl -u k0scontroller -n 100 | grep -i "overlay\|snapshot"如果看到 snapshot 相关错误,回退 containerd 配置,或确认 rootfs 类型是否支持 overlay。另外,
manifests 下文件权限要是 644,不能是 755——k0s 会静默跳过可执行文件。










