服务器K8s集群Firecracker排错:从Pod起不来到底层容器启动失败
在Kubernetes集群里用Firecracker跑Pod,遇到起不来时,先看kubelet和容器运行时的日志,再检查/dev/kvm、内核模块和CRI配置。
多数问题集中在三处:宿主机没开虚拟化、运行时没接上Firecracker、Pod的annotation或RuntimeClass没写对。
先确认宿主机能不能跑Firecracker
Firecracker是轻量级虚拟机,依赖KVM。
在目标节点执行:
ls -l /dev/kvm
kvm-ok
如果/dev/kvm不存在,说明CPU虚拟化没开或嵌套虚拟化被禁用。
云服务器上常见情况是厂商默认关闭嵌套虚拟化,需要在控制台开启或换支持嵌套虚拟化的实例规格。
再看内核模块:
lsmod | grep kvm
modprobe kvm_intel
AMD平台对应kvm_amd。
模块加载失败时,dmesg | tail -50通常会给出具体原因,比如BIOS里VT-x没开。
检查容器运行时与Firecracker的对接
Kubernetes本身不直接调用Firecracker,中间要经过CRI运行时,比如containerd配合firecracker-containerd,或者kata-containers的Firecracker模式。
先确认运行时状态:
systemctl status containerd
crictl info
如果crictl info里runtime name和预期不符,说明kubelet连的不是你配置的那个运行时。
检查/etc/containerd/config.toml里是否启用了对应的runtime handler,以及/var/lib/kubelet/kubeadm-flags.env或/etc/default/kubelet里的--container-runtime-endpoint指向是否正确。
改完配置后重启并复查:
systemctl restart containerd kubelet
crictl info | grep -i runtime
Pod起不来时按顺序看三个地方
第一看Pod事件。
kubectl describe pod -n
重点看Events里有没有Failed to create pod sandbox、RuntimeClass not found这类信息。
第二看运行时日志。
journalctl -u containerd -n 200 --no-pager
Firecracker启动失败时,日志里常见failed to start firecracker、KVM is not available、permission denied on /dev/kvm。
权限问题可以检查运行时的用户是否在kvm组,以及/dev/kvm的属主。
第三看内核日志。
dmesg -T | tail -80
这里能看到KVM创建VM失败、内存不足、cgroup限制等底层报错。
容易踩的坑与规避方式
- 节点没有
/dev/kvm就硬上Firecracker,Pod会一直卡在ContainerCreating。先解决虚拟化,再谈运行时。 - RuntimeClass名字写错或没创建,Pod会报
RuntimeClass not found。用kubectl get runtimeclass核对,Pod里runtimeClassName要和它完全一致。 - annotation里CPU和内存给太小。Firecracker虽然轻量,但内核启动也需要内存,建议至少给256MiB以上,否则可能启动后立刻OOM。
- 防火墙或iptables规则把CNI插件的转发链拦了,表现为Pod网络不通。检查
iptables -L FORWARD和CNI插件日志。 - 改完
config.toml只重启了containerd没重启kubelet,导致kubelet还拿着旧连接。两个都重启后再验证。
怎么确认已经恢复
Pod进入Running后,执行:
kubectl get pod -o wide
kubectl exec -it -- uname -a
如果uname -a显示的内核版本和宿主机不同,说明Pod确实跑在Firecracker微虚拟机里,而不是普通runc容器。
最后在节点上确认Firecracker进程存在:
ps aux | grep firecracker
能看到对应VM的进程,且数量与运行中的Pod匹配,基本可以判断链路是通的。
几个常见疑问
Firecracker和Kata Containers是什么关系?
Kata Containers是一套容器运行时框架,可以用Firecracker作为底层VMM。如果你用的是Kata的Firecracker模式,排错时要同时看kata-runtime和firecracker两侧日志。
为什么普通Pod能跑,加了runtimeClassName就失败?
说明默认runc链路正常,问题在Firecracker运行时本身。优先查/dev/kvm权限、运行时二进制路径和RuntimeClass配置。
日志里没有明显报错,但Pod一直Pending。
Pending通常是调度问题,不是Firecracker问题。先看kubectl describe pod里的调度事件,确认节点资源、污点和亲和性是否满足。
整体思路是:先确认宿主机虚拟化可用,再确认运行时接对了Firecracker,最后用Pod事件、运行时日志和内核日志三层定位。
按这个顺序走,绝大多数服务器K8s集群Firecracker排错场景都能找到明确方向。