当数据卷由 NFS 作为后端时,SonarQube Pod 在启动时卡住
目录
问题描述根因故障排查步骤 1 — 确认 Pod 是否卡在文件系统操作上步骤 2 — 检查节点上的挂载选项步骤 3 — 先排除 export 侧配置错误解决方案使用手动创建的 NFS PV 时使用动态 NFS StorageClass 时应用更改注意事项问题描述
某个数据卷由 NFS export 提供后端存储的 SonarQube 实例无法变为 Ready。表现包括:
- PostgreSQL Pod 处于健康状态,且没有重启。
- SonarQube Pod 处于
Running状态,或卡在启动循环中,但始终不报告 Ready。 - Pod 日志在初始化期间会继续推进,随后在读取或写入
/opt/sonarqube/data下文件的某一步骤卡住。不会抛出异常——进程只是长时间停止输出。 - Pod 内部的文件模式和所有权可能看起来与非 NFS 环境不同,但修改它们并不能解决问题。
NFS export 本身已使用预期选项配置(例如 rw,async,no_root_squash,no_all_squash),并且该 export 可从集群访问。
根因
SonarQube 及其内置的 Elasticsearch 需要进行文件锁定,以协调对磁盘状态的访问。默认情况下,NFSv3 挂载通过 rpc.lockd / rpc.statd 协商锁。如果客户端无法访问这些锁守护进程(通常是因为它们未通过网络策略暴露,或者 NFS 服务器未运行它们),SonarQube 发起的文件锁操作就会无限期阻塞。Pod 仍然存活,但无法继续推进,这就表现为“启动卡住”。
要求客户端在本地处理锁、而不是联系服务器的挂载选项是 nolock。启用 nolock 后,文件锁变为进程本地锁——对于单 Pod 的 SonarQube 已经足够——因此启动可以正常继续。
故障排查
步骤 1 — 确认 Pod 是否卡在文件系统操作上
典型特征是日志在某个步骤中途停止(最常见于 Elasticsearch 初始化期间,或在 /opt/sonarqube/data 下创建初始索引时),并且在数分钟内不再输出任何内容。
步骤 2 — 检查节点上的挂载选项
找到承载 SonarQube Pod 的节点,并检查为该 SonarQube data PVC 提供后端的 NFS export 的挂载选项:
如果挂载选项不包含 nolock,则很可能会出现该问题。存在诸如 local_lock=none 的选项,或者根本没有 lock 条目,都与这种故障模式一致。
步骤 3 — 先排除 export 侧配置错误
如果 export 缺少 rw、no_root_squash 或 no_all_squash,请先修复这些配置——它们属于不同的故障模式,不能通过 nolock 解决。只有在确认 export 选项正确,且 Pod 能够读取和写入文件(只是不能加锁)之后,才继续执行下面的解决方案。
解决方案
将 SonarQube 使用的 NFS PV 的挂载选项中添加 nolock,然后重启 SonarQube Pod,使其使用新选项重新挂载。
使用手动创建的 NFS PV 时
编辑 PersistentVolume,并将 nolock 添加到 spec.mountOptions:
使用动态 NFS StorageClass 时
编辑 StorageClass,并将 nolock 添加到其 mountOptions,然后重新创建 PVC(以及 Pod),以便新选项在新创建的 PV 上生效:
应用更改
更新 PV 或 StorageClass 后,重新创建 SonarQube Pod,使卷重新挂载:
确认节点上已生效新的挂载选项,然后观察 Pod 启动:
注意事项
nolock对单 Pod 的 SonarQube 是安全的。 SonarQube 针对其数据卷以单 Pod 方式运行,因此进程本地锁已经足够。对于真正需要通过 NFS 锁进行跨节点协调的工作负载,不应使用nolock。- NFSv4。 在 NFSv4 上,文件锁定是协议本身的一部分,不需要
rpc.lockd/rpc.statd。如果该 export 可作为 NFSv4(vers=4/vers=4.1)访问,但锁定仍然卡住,请先查找其他无关原因,再考虑应用nolock。 - 参考。 Red Hat 关于 NFS 挂载选项的文档对
nolock及其他选项进行了说明:Mounting NFS shares。