问题排查案例
这里收录常见问题的具体排查步骤,你可以直接在本文搜索报错关键字以检索问题。同时,我们也推荐你先掌握「基础问题排查思路」。
CSI 驱动安装异常
如果 JuiceFS CSI 驱动压根没安装,或者配置错误导致安装失败,那么试图使用 JuiceFS CSI 驱动时,便会有下方报错:
kubernetes.io/csi: attacher.MountDevice failed to create newCsiDriverClient: driver name csi.juicefs.com not found in the list of registered CSI drivers
上方的报错信息表示,名为 csi.juicefs.com 的驱动没有找到,请先确认使用的是 Mount Pod 模式还是 Sidecar 模式。
Mount Pod 模式
若使用的是 Mount Pod 模式,遵循以下步骤进行排查:
-
运行
kubectl get csidrivers.storage.k8s.io,如果输出中没有csi.juicefs.com字样,说明 CSI 驱动并未安装,仔细回顾「安装 JuiceFS CSI 驱动」。 -
检查 kubelet 的根目录与 CSI Node 的配置是否一致,如果不一致,会导致 CSI Node 无法正常注册,请修复 CSI Node 的配置,或者重新安装。
# 检查 kubelet 根目录
ps -ef | grep kubelet | grep root-dir
# 检查 CSI Node 配置中的 kubelet 根目录
kubectl -n kube-system get ds juicefs-csi-node -oyaml | grep csi.juicefs.com -
如果上方的
csidrivers列表中存在csi.juicefs.com,那么说明 CSI 驱动已经安装,问题出在 CSI Node,检查 CSI Node 是否正常运作:-
排查开始前,可以简单阅读「检查 CSI Node」,代码示范里有一些快捷命令可供参考。
-
关注应用 Pod 所在节点,检查节点是否正常运行着 CSI Node,如果为 CSI Node 这个 DaemonSet 组件配置了调度策略,或者节点本身存在污点,都有可能造成 CSI Node 容器缺失,造成该错误。
-
如果问题节点的 CSI Node 正常运行(处于 Running 状态),核实它的各个容器均没有明显错误日志,比方说:
# juicefs-plugin 容器负责运行 CSI 驱动的实际工作,如果他访问 Kubernetes API 失败,则会导致 Mount Pod 无法创建
kubectl logs -n kube-system juicefs-csi-node-xxx juicefs-plugin --tail 100
# node-driver-registrar 容器负责注册 csidriver,如果注册过程异常,该容器会报错
kubectl logs -n kube-system juicefs-csi-node-xxx node-driver-registrar --tail 100
-
-
如果以上排查均无结论,则认为 Kubernetes 本身出现了问题,可以尝试重启 kubelet 或者节点。如果问题仍得不到解决,需要向 Kubernetes 的管理员或服务提供商寻求帮助。
Sidecar 模式
若使用的是 sidecar 模式,请确认对应的 namespace 有没有打上 JuiceFS sidecar 所需的标签(juicefs.com/enable-injection=true):
# 换成应用 pod 所在 namespace
kubectl get ns <namespace> --show-labels
CSI Node Pod 异常
如果 CSI Node Pod 异常,与 kubelet 通信的 socket 文件不复存在,应用 Pod 事件中会看到如下错误日志:
/var/lib/kubelet/csi-plugins/csi.juicefs.com/csi.sock: connect: no such file or directory
此时需要检查 CSI Node,确认其异常原因,并排查修复。常见的问题比如 kubelet 没有启用 Authentication webhook,导致获取 Pod 列表时报错:
kubelet_client.go:99] GetNodeRunningPods err: Unauthorized
reconciler.go:70] doReconcile GetNodeRunningPods: invalid character 'U' looking for beginning of value
面对这种情况,阅读启用 Kubelet 认证鉴权了解如何修复该问题。
Node driver registrar sidecar 无法连接 CSI Socket(SELinux 环境)
在启用 SELinux 模式的系统,node-driver-registrar sidecar 容器会因无法访问 CSI socket 文件而启动失败,DaemonSet 状态异常。
node-driver-registrar 容器日志持续报错:
Still connecting to unix:///csi/csi.sock error connecting to CSI driver: context deadline exceeded
通常伴随 CSI Node Pod 无法正常 Ready。
主要原因:
juicefs-plugin容器以privileged: true运行,负责在 hostPath 挂载的/csi目录下创建 socket 文件;node-driver-registrar默认未开启特权模式(privileged: false),但需要访问相同的 hostPath socket;- 在 SELinux enforcing 模式下,privileged 容器创建的 socket SELinux label 与非特权容器不一致,后者无法访问该 socket 文件,导致连接失败。
解决办法:
-
关闭 SELinux enforcing 模式。
-
在
node-driver-registrar容器中开启特权模式(privileged: true)。需要 helm chart 大于 0.28.1 版本,或者手动修改 DaemonSet 配置:
node:
sidecarPrivileged: true手动修改 DaemonSet 配置:
- name: node-driver-registrar
securityContext:
privileged: true # Set to true
Mount Pod 异常
Mount Pod 内运行着 JuiceFS 客户端,出错的可能性多种多样,在这里罗列常见错误,指导排查。
Mount Pod 一直卡在 Pending 状态,导致应用容器也一并卡死在 ContainerCreating 状态
此时需要 查看 Mount Pod 事件,确定症结所在。不过对于 Pending 状态,大概率是资源吃紧,导致容器无法创建。
另外,当节点 kubelet 开启抢占功能,Mount Pod 启动后可能抢占应用资源,导致 Mount Pod 和应用 Pod 均反复创建、销 毁,在 Pod 事件中能看到以下信息:
Preempted in order to admit critical Pod
Mount Pod 默认的资源声明是 1 CPU、1GiB 内存,节点资源不足时,便无法启动,或者启动后抢占应用资源。此时需要根据实际情况 调整 Mount Pod 资源声明,或者扩容宿主机。
集群 IP 不足也可能导致 Mount Pod 一直处于 Pending 状态。Mount Pod 默认以 hostNetwork: false 的形式启动,可能会占用大量的集群 IP 资源,如果集群资源 IP 不足可能会导致 Mount Pod 启动不成功。请联系云服务提供商对 Kubernetes 集群的 IP 数量进行扩容,或者使用 hostNetwork: true 形式启动,参阅:定制 Mount Pod 和 Sidecar 容器。
Mount Pod 重启或者重新创建后,应用容器无法访问 JuiceFS
如果 Mount Pod 发生异常重启,或者经历了手动删除,那么应用 Pod 内访问挂载点(比如 df)会产生如下报错,提示挂载点已经不存在:
Transport endpoint is not connected
df: /jfs: Socket not connected
你需要启用 「挂载点自动恢复」,这样一来,只要 Mount Pod 能自行重建,恢复挂载点,应用容器就能继续访问 JuiceFS。
Mount Pod 正常退出(exit code 为 0),应用容器卡在 ContainerCreateError 状态
Mount Pod 是一个常驻进程,如果它退出了(变为 Completed 状态),即便退出状态码为 0,也明显属于异常状态。此时应用容器由于挂载点不复存在,会伴随着以下错误事件:
$ kubectl describe pod juicefs-app
...
Normal Pulled 8m59s kubelet Successfully pulled image "centos" in 2.8771491s
Warning Failed 8m59s kubelet Error: failed to generate container "d51d4373740596659be95e1ca02375bf41cf01d3549dc7944e0bfeaea22cc8de" spec: failed to generate spec: failed to stat "/var/lib/kubelet/pods/dc0e8b63-549b-43e5-8be1-f84b25143fcd/volumes/kubernetes.io~csi/pvc-bc9b54c9-9efb-4cb5-9e1d-7166797d6d6f/mount": stat /var/lib/kubelet/pods/dc0e8b63-549b-43e5-8be1-f84b25143fcd/volumes/kubernetes.io~csi/pvc-bc9b54c9-9efb-4cb5-9e1d-7166797d6d6f/mount: transport endpoint is not connected
错误日志里的 transport endpoint is not connected,其含义就是创建容器所需的 JuiceFS 挂载点不存在,因此应用容器无法创建。这时需要检查 Mount Pod 的启动命令(以下命令来自 「检查 Mount Pod」 文档):
APP_NS=default # 应用所在的 Kubernetes 命名空间
APP_POD_NAME=example-app-xxx-xxx
# 获取 Mount Pod 的名称
MOUNT_POD_NAME=$(kubectl -n kube-system get po --field-selector spec.nodeName=$(kubectl -n $APP_NS get po $APP_POD_NAME -o jsonpath='{.spec.nodeName}') -l app.kubernetes.io/name=juicefs-mount -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}' | grep $(kubectl get pv $(kubectl -n $APP_NS get pvc $(kubectl -n $APP_NS get po $APP_POD_NAME -o jsonpath='{..persistentVolumeClaim.claimName}' | awk '{print $1}') -o jsonpath='{.spec.volumeName}') -o jsonpath='{.spec.csi.volumeHandle}'))
# 获取 Mount Pod 启动命令
# 形如:["sh","-c","/sbin/mount.juicefs myjfs /jfs/pvc-48a083ec-eec9-45fb-a4fe-0f43e946f4aa -o foreground"]
kubectl get pod -o jsonpath='{..containers[0].command}' $MOUNT_POD_NAME
仔细检查 Mount Pod 启动命令,以上示例中 -o 后面所跟的选项即为 JuiceFS 文件系统的挂载参数,如果有多个挂载参数会通过 , 连接(如 -o aaa,bbb)。如果发现类似 -o debug foreground 这样的错误格式(正确格式应该是 -o debug,foreground),便会造成 Mount Pod 无法正常启动。此类错误往往是 mountOptions 填写错误造成的,请详读 「调整挂载参数」,确保格式正确。
Mount Pod 没有创建
使用 kubectl describe <app-pod-name> 查看当前应用 Pod 的事件,确认已经进入挂载流程,而不是调度失败或者其它与挂载 JuiceFS 无关的错误。
如果应用 Pod 的事件为:
-
driver name csi.juicefs.com not found或者csi.sock no such file检查对应节点上的 CSI Node Pod 是否运行正常,详见文档。
-
Unable to attach or mount volumes: xxx查看对应节点上 CSI Node Pod 的日志,过滤出对应 PV 的相关日志。如果没有找到类似于
NodePublishVolume: volume_id is <pv-name>的日志,并且 Kubernetes 版本低于 1.26.0、1.25.1、1.24.5、1.23.11,可能是因为 kubelet 的一个 bug 导致没有触发 volume publish 请求,详见 #109047。此时可以尝试:
- 重启 kubelet
- 升级 Kubernetes
如果你的 Kubernetes 版本高于这些版本,但仍然遇到这个问题,检查是否是同一个 Pod 挂载了多个相同 volumeHandle 的 PV,这也会导致挂 CSI 无法正常收到请求。详见 #91556。
建议你开启 validation webhook,确保在创建 PV 时就能检查到这个问题。
总之 JuiceFS CSI 驱动需要收到请求才能开始挂载流程。
PVC 异常
静态配置中,PV 错误填写了 storageClassName,导致初始化异常,PVC 卡在 Pending 状态
StorageClass 的存在是为了给 「动态配置」 创建 PV 时提供初始化参数。对于 「静态配置」,storageClassName 必须填写为空字符串,否则将遭遇类似下方报错:
$ kubectl describe pvc juicefs-pv
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Provisioning 9s (x5 over 22s) csi.juicefs.com_juicefs-csi-controller-0_872ea36b-0fc7-4b66-bec5-96c7470dc82a External provisioner is provisioning volume for claim "default/juicefs-pvc"
Warning ProvisioningFailed 9s (x5 over 22s) csi.juicefs.com_juicefs-csi-controller-0_872ea36b-0fc7-4b66-bec5-96c7470dc82a failed to provision volume with StorageClass "juicefs": claim Selector is not supported
Normal ExternalProvisioning 8s (x2 over 23s) persistentvolume-controller waiting for a volume to be created, either by external provisioner "csi.juicefs.com" or manually created by system administrator
volumeHandle 冲突,导致 PVC 创建失败
一个 Pod 使用多个 PVC,但引用的 PV 有着相同的 volumeHandle,此时 PVC 将伴随着以下错误事件:
$ kubectl describe pvc jfs-static
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedBinding 4s (x2 over 16s) persistentvolume-controller volume "jfs-static" already bound to a different claim.
另外,应用 Pod 也会伴随着以下错误事件,应用 Pod 中有分别有名为 data1 和 data2 的 volume(spec.volumes),event 中会报错其中一个 volume 没有 mount:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedMount 12s kubelet Unable to attach or mount volumes: unmounted volumes=[data1], unattached volumes=[data2 kube-api-access-5sqd8 data1]: timed out waiting for the condition
请检查每个 PVC 对应的 PV,每个 PV 的 volumeHandle 必须保证唯一。可以通过以下命令检查 volumeHandle