GCS FUSE挂载GCS存储桶时Java应用出现打开文件过多错误
GCS FUSE挂载目录重命名/移动触发"Too many open files"的解决方案
问题场景
在GCP Kubernetes集群部署Java Spring Boot应用,通过Cloud Storage FUSE CSI驱动将GCS存储桶挂载为文件系统,让应用通过通用文件IO操作访问桶内对象。当尝试重命名或移动包含20个以上文件的非空目录时,应用容器和FUSE边车容器均报错:
应用容器错误
java.nio.file.FileSystemException: /volume/mydirectory -> /volume/mydirectoryTmp : Too many open files at sun.nio.fs.UnixException.translateToIOException(UnixException.java:91) at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102) at sun.nio.fs.UnixCopyFile.move(UnixCopyFile.java:457) at sun.nio.fs.UnixFileSystemProvider.move(UnixFileSystemProvider.java:262) at java.nio.file.Files.move(Files.java:1395)
FUSE边车容器错误
fuseops.RenameOp error: too many open files
试过网上推荐的--rename-dir-limit 1000参数,但问题依旧,最终找到可行的解决方法分享如下:
解决方案
这个问题的核心是GCS FUSE处理目录重命名时,会为目录下每个文件打开一个文件句柄,当文件数量超过容器默认的文件描述符上限时就会触发错误。仅调整GCS FUSE参数不够,必须同时修改容器的文件描述符限制:
- 调整Pod容器的文件描述符上限
在Pod的应用容器和FUSE边车容器的定义中添加ulimit配置,将最大打开文件数(nofile)调高至65535:
securityContext: ulimits: - name: nofile soft: 65535 hard: 65535
- 优化GCS FUSE挂载参数
在CSI驱动的挂载参数中,除了--rename-dir-limit 1000,额外添加以下参数减少并发操作带来的句柄占用:
--max-concurrent-operations=100 --stat-cache-ttl=60s
说明
单独设置--rename-dir-limit无效的原因是:该参数仅控制单次重命名操作中批量处理的文件数量,但如果容器本身的文件描述符上限低于这个值,即使分批次处理,还是会触发句柄不足的错误。必须同时调高容器的nofile限制,才能让GCS FUSE的参数生效。
内容的提问来源于stack exchange,提问作者Salim Hamidi
相关产品推荐
相关产品推荐

