我还没有遇到过完美的软件。错误、故障和缺陷是软件开发者的现实。它们通常有积极的一面,无论是学习大型应用程序中新代码区域,还是想出防止问题的想法。
我们最近遇到一个有趣的问题,Podman 数据库已损坏。数据库的主要作用是跟踪容器、其状态及其配置。在这种情况下,报告者正在测试 Podman,模拟特殊设备上的电源故障。虽然 Podman 团队以及我们的用户或多或少地进行了一些电源故障测试,无论是故意还是意外,我们很少看到数据库损坏,因为数据库要损坏,它必须在写入(至少在理论上)。而写入我们的数据库通常是一个非常快的操作,因此窗口非常小。
虽然我们无法立即确定根本原因,但我们被问到如何从这种故障中恢复。如果你的数据库已损坏,大多数 Podman 命令将无法正常工作。在这种情况下,他们的容器通常在每次启动时都会重新创建,并且是通过 RESTFul API 以编程方式完成的。
Podman DB 损坏
如果你的 Podman 数据库已损坏,在几乎所有情况下,你都 **无法恢复** 任何现有的容器。
在这种情况下,容器由特权用户运行:root。因此,我将展示特权用户的恢复,并为无根用户添加一些说明。过程大致相同。首先,错误
$ sudo podman ps panic: invalid freelist page: 66, page type is leaf goroutine 1 [running]: go.etcd.io/bbolt.(*freelist).read(0x50c95d?, 0x7f96a7e42000) /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/freelist.go:266 +0x22e go.etcd.io/bbolt.(*DB).loadFreelist.func1() /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/db.go:323 +0xb8 sync.(*Once).doSlow(0xc00011e1c8?, 0x10?) /usr/lib/golang/src/sync/once.go:74 +0xc2 sync.(*Once).Do(...) /usr/lib/golang/src/sync/once.go:65 go.etcd.io/bbolt.(*DB).loadFreelist(0xc00011e000?) /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/db.go:316 +0x47 go.etcd.io/bbolt.Open({0x7ffd1855f26a, 0x23}, 0x1b6?, 0x0) /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/db.go:293 +0x48b main.(*CheckCommand).Run(0xc00005fe58, {0xc0000141a0, 0x1, 0x1}) /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/cmd/bbolt/main.go:202 +0x1a5 main.(*Main).Run(0xc000104f40, {0xc000014190, 0x2, 0x2}) /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/cmd/bbolt/main.go:112 +0x979 main.main() /home/baude/go/pkg/mod/go.etcd.io/bbolt@v1.3.6/cmd/bbolt/main.go:70 +0xae
恢复的第一步是删除现有数据库。
$ sudo rm /var/lib/containers/storage/libpod/bolt_state.db
无根数据库路径
特权用户的数据库默认存储在 /var/lib/containers/storage/libpod/bolt_state.db 中。无根用户的数据库默认存储在 ~/.local/share/containers/storage/libpod/bolt_state.db 中。
当 Podman 无法找到其数据库时,它将创建一个新的空数据库。
$ sudo podman ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
现在我们可以重新创建我们的容器,这些容器被称为 container1、container2 和 container3。
$ sudo podman create --name container1 alpine top Error: creating container storage: the container name "container1" is already in use by e77786c096e083b258bad2e196255f7dc1a2859cfb9dd35436648e1541bdce23. You have to remove that container to be able to reuse that name: that name is already in use
容器如何已经存在,但不在所有容器列表中?错误信息 可能更有帮助。有一个鲜为人知的选项称为 `–external`,用于 `podman ps`,用于查看此外部存储状态下的容器。
$ sudo podman ps -a --external CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 69f78dfaa0a6 docker.io/library/alpine:latest storage About a minute ago Storage container1 e5db3ad9125e docker.io/library/alpine:latest storage About a minute ago Storage container2 52591b8b7676 docker.io/library/alpine:latest storage About a minute ago Storage container3
注意,STATUS
列为所有三个容器列出了 STORAGE
。同样,这是因为这些容器仍然存在于文件系统中,这解释了之前的错误。与其尝试删除它们并重新创建容器(这也很有效),我们可以简单地使用 `--replace` 选项,该选项适用于 podman `run` 和 `create`。
$ sudo podman create --replace --name container1 alpine top container1 128876a5b3828350c7bfbc268dee99f69fb2374b5c8ce94cff879b4f83e78c6d
--replace
选项将从文件系统中删除之前的容器,并使用该名称运行或创建新容器。此选项也适用于数据库和常规存储中的容器。
发表评论