juicedata / docker-volume-juicefs

Docker volume plugin for juicefs
28 stars 7 forks source link

系统重启后挂载失败,要强制停止插件再升级插件才能使用 #37

Closed zzerding closed 6 months ago

zzerding commented 8 months ago

使用的mate为https://juicefs.com/static/juicefs 配合腾讯云oos.正常客户端使用没问题,使用docker plugin 系统重启后就挂载失败。volumes里没有数据。请问应该怎么排查?

docker info

Client: Docker Engine - Community
 Version:    24.0.7
 Context:    default
 Debug Mode: false
 Plugins:
  buildx: Docker Buildx (Docker Inc.)
    Version:  v0.11.2
    Path:     /usr/libexec/docker/cli-plugins/docker-buildx
  compose: Docker Compose (Docker Inc.)
    Version:  v2.21.0
    Path:     /usr/libexec/docker/cli-plugins/docker-compose
    Kernel Version: 5.10.0-26-amd64
 Operating System: Debian GNU/Linux 11 (bullseye)
 OSType: linux
 Architecture: x86_64
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Experimental: false
 Live Restore Enabled: false

按照https://juicefs.com/docs/zh/community/juicefs_on_docker#troubleshooting 排查,输出如下:

sudo. ls /run/docker/plugins/runtime-root/plugins.moby 输出为空 sudo runc --root /run/docker/plugins/runtime-root/plugins.moby list 没有输出

sudo journalctl -f -u docker | grep "plugin=" 输出如下

" level=error msg="2024/01/04 10:29:50 Entering go-plugins-helpers getPath" plugin=2894f5d961070ef3a4cfd1c79f46ec8f66a7a9dd4ea2e7c5507e5fcbb286135e
" level=error msg="2024/01/04 10:29:50 Entering go-plugins-helpers capabilitiesPath" plugin=2894f5d961070ef3a4cfd1c79f46ec8f66a7a9dd4ea2e7c5507e5fc

已知可用的解决方案为: docker plugin disable --force juicedata/juicefs && docker plugin upgrade juicedata/juicefs 然后重新启动容器

TechQuery commented 6 months ago

文档说 Docker compose 停机时要执行:

docker-compose down --volumes

但始终报错:

Error response from daemon: remove my_juice: VolumeDriver.Remove: exit status 1

手动删卷也一样:

sudo docker volume rm -f my_juice
TechQuery commented 6 months ago

已知可用的解决方案为: docker plugin disable --force juicedata/juicefs && docker plugin upgrade juicedata/juicefs 然后重新启动容器

@zzerding 用了这条命令倒是删了旧卷,但 enable 后再 docker-compose up 就又报错:

ERROR: create api-service_polyfill-buffer: VolumeDriver.Create: exit status 1

插件删了重装都一样……

sudo journalctl -f -u docker | grep "plugin=" 执行输出如下:

Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="2024/03/03 09:29:07 Entering go-plugins-helpers getPath" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="time=\"2024-03-03T09:29:07Z\" level=error msg=\"volume api-service_polyfill-buffer not found\"" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="2024/03/03 09:29:07 Entering go-plugins-helpers capabilitiesPath" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="2024/03/03 09:29:07 Entering go-plugins-helpers getPath" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="time=\"2024-03-03T09:29:07Z\" level=error msg=\"volume api-service_polyfill-buffer not found\"" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="2024/03/03 09:29:07 Entering go-plugins-helpers createPath" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="time=\"2024-03-03T09:29:07Z\" level=error msg=\"juicefs format error: 2024/03/03 09:29:07.803202 juicefs[12] <INFO>: Meta address: sqlite3://polyfill-buffer.db [interface.go:497]\\n2024/03/03 09:29:07.804171 juicefs[12] <INFO>: Data use wasb://polyfill4web/polyfill-buffer/ [format.go:471]\\n2024/03/03 09:29:07.895115 juicefs[12] <FATAL>: Storage wasb://polyfill4web/polyfill-buffer/ is not empty; please clean it up or pick another volume name [format.go:485]\\n\"" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="time=\"2024-03-03T09:29:07Z\" level=error msg=\"exit status 1\"" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea
Mar 03 09:29:07 Docker-Caddy dockerd[722]: time="2024-03-03T09:29:07Z" level=error msg="2024/03/03 09:29:07 Entering go-plugins-helpers capabilitiesPath" plugin=783eed41f62d3e4835b027916494989d08e3cbc515bbd715a30159efb65480ea

其中最有用的是:

juicefs[12] <FATAL>: Storage wasb://polyfill4web/polyfill-buffer/ is not empty; please clean it up or pick another volume name [format.go:485]

意思是元数据存储非空,让我清空或换个名字……(换名字一直是我之前的解决方案,但不能每次重启都改 docker-compose.yml 吧)

我又尝试手动删除插件存储,也是一样的报错:

rm -f $(find / -name "my_juice*.db")
timfeirg commented 6 months ago

format 命令允许重复多次执行的,如果文件系统已经存在,会跳过。因此能否:

然后将日志中的 format 命令脱敏发一下 @zzerding

luojiyin1987 commented 6 months ago

https://github.com/juicedata/juicefs/blob/59659db8d67af0934836076a98e205f08fdf924d/cmd/format.go#L482-L505

是不是触发报错的逻辑代码? @timfeirg

juicefs[12] <FATAL>: Storage wasb://polyfill4web/polyfill-buffer/ is not empty; please clean it up or pick another volume name [format.go:485]
timfeirg commented 6 months ago

是这个代码没错,但 format 命令本身是可以反复执行的,如果走到了 create = true 的条件分支,说明元数据引擎是一片空白、需要 format 的状态,但又因为对象存储的对应路径不为空,所以进入冲突。

需要梳理你的使用流程,为什么会反复清空引擎,却未清空对象存储数据呢?

TechQuery commented 6 months ago

需要梳理你的使用流程,为什么会反复清空引擎,却未清空对象存储数据呢?

我的上下文代码在此:wessberg/Polyfiller#71

timfeirg commented 6 months ago

每次运行的时候,都现场创建一个sqlite作为元数据引擎。现场销毁以后,对应的对象存储却并未清空。导致下次即便想复用,也会报错。

可以选择:

目前看来,这不是 docker volume plugin 的问题,而是 juicefs 创建和使用流程的问题,先 close 了

TechQuery commented 6 months ago

每次运行的时候,都现场创建一个sqlite作为元数据引擎。现场销毁以后,对应的对象存储却并未清空。导致下次即便想复用,也会报错。

可以选择:

  • 每次运行之前,都清空对象存储,让 juicefs 客户端得以全新 format 文件系统
  • 或者复用一个持久存续的元数据引擎,这样就不需要每次都重新 format 一个了

目前看来,这不是 docker volume plugin 的问题,而是 juicefs 创建和使用流程的问题,先 close 了

@timfeirg Docker compose 配置文件是按照官方文档写的,但上面并没有写如何手动销毁元数据存储,官方卷销毁参数也会报错:https://juicefs.com/docs/zh/community/juicefs_on_docker/#using-docker-compose

所以按理说,应该在 Docker 镜像正常退出的时候,插件自动做好清理工作,这个锅不能甩给用户。

timfeirg commented 6 months ago

可以用 juicefs destroy 来销毁文件系统,但这不是 docker volume plugin 的工作。文件系统必须用户显式操作、销毁。

jfs 和周边系统(docker volume plugin,或者 csi 驱动)都将文件系统视作「重要、决不能乱删」的资源,在你的例子里,应该是 CI 环境销毁的时候直接删了 sqlite 文件,但是并没有流程负责清理对象存储,这才导致下次启动的时候没办法重新跑 format。

在一个正常的业务场景中,绝不会有人去乱删元数据引擎的数据,如果要销毁文件系统,那也应该走正常流程、用 destroy 命令来清空两边的数据。

docker volume plugin 不可能去在 volume 卸载或删除的时候,来清空你的元数据引擎,这会在业务中导致灾难(因为也许其他应用还在使用这个文件系统,并且不一定会通过 volume plugin)

timfeirg commented 6 months ago

举个更简明的例子,你的诉求就像是应用连接 mysql,创建 db,然后指望应用关停以后,mysql 能自动把这个 db 给销毁掉,这不符合正常应用的使用流程,因此 jfs volume plugin 也无法实现你期望的自动清理,不属于“甩锅”。

TechQuery commented 6 months ago

可以用 juicefs destroy 来销毁文件系统,但这不是 docker volume plugin 的工作。文件系统必须用户显式操作、销毁。

jfs 和周边系统(docker volume plugin,或者 csi 驱动)都将文件系统视作「重要、决不能乱删」的资源,在你的例子里,应该是 CI 环境销毁的时候直接删了 sqlite 文件,但是并没有流程负责清理对象存储,这才导致下次启动的时候没办法重新跑 format。

在一个正常的业务场景中,绝不会有人去乱删元数据引擎的数据,如果要销毁文件系统,那也应该走正常流程、用 destroy 命令来清空两边的数据。

docker volume plugin 不可能去在 volume 卸载或删除的时候,来清空你的元数据引擎,这会在业务中导致灾难(因为也许其他应用还在使用这个文件系统,并且不一定会通过 volume plugin)

@timfeirg  我不想清理、不想销毁呀,我就是想能丝滑重启容器,没别的需求。

我最早只执行 docker compose down,再次 docker compose up 的时候,Docker 说已经有同名卷了,让我先销毁。

于是我又按 JuiceFS 文档执行 docker compose down --volumes 来销毁卷,但JuiceFS又报退出码 1

然后我又重启插件试图手动销毁存储,但再次启动容器时又报创建卷退出码是 1,日志里说已经存在数据库文件不让我创建……

TechQuery commented 6 months ago

举个更简明的例子,你的诉求就像是应用连接 mysql,创建 db,然后指望应用关停以后,mysql 能自动把这个 db 给销毁掉,这不符合正常应用的使用流程,因此 jfs volume plugin 也无法实现你期望的自动清理,不属于“甩锅”。

@timfeirg 我作为一个 Docker 用户,我就是想在我的应用代码更新的时候重启相关服务的容器,同时复用现有所有的卷。

我现在根本涉及不到任何销毁数据的需求,因为我是要提供一个长期的对外服务。现在所有的“销毁”都是日志和 issue 当中跟我说:你得先销毁,再怎样…… 都把我绕晕了。

luojiyin1987 commented 6 months ago

可以用 juicefs destroy 来销毁文件系统,但这不是 docker volume plugin 的工作。文件系统必须用户显式操作、销毁。

jfs 和周边系统(docker volume plugin,或者 csi 驱动)都将文件系统视作「重要、决不能乱删」的资源,在你的例子里,应该是 CI 环境销毁的时候直接删了 sqlite 文件,但是并没有流程负责清理对象存储,这才导致下次启动的时候没办法重新跑 format。

在一个正常的业务场景中,绝不会有人去乱删元数据引擎的数据,如果要销毁文件系统,那也应该走正常流程、用 destroy 命令来清空两边的数据。

docker volume plugin 不可能去在 volume 卸载或删除的时候,来清空你的元数据引擎,这会在业务中导致灾难(因为也许其他应用还在使用这个文件系统,并且不一定会通过 volume plugin)

docker 相关插件 是否正常维护了 sqlite ?是指停止运行插件,再度启动插件。 作为普通用户很难这么深入了解 juicefs。