Skip to content

Export zpools on zfs shutdown - #1028

Merged
talos-bot merged 1 commit into
siderolabs:mainfrom
gjabell:zpool-export
Mar 31, 2026
Merged

talos-bot merged 1 commit into
siderolabs:mainfrom
gjabell:zpool-export

Conversation

@gjabell

@gjabell gjabell commented Mar 29, 2026

Copy link
Copy Markdown
Contributor

Fixes cases where later tasks fail because the disks are still in use (e.g. closing encrypted volumes).

I ran into similar issues as siderolabs/talos#9307 and siderolabs/talos#8800 while setting up a new cluster with a ZFS data disk; since the pools are still active, cryptsetup close fails in a loop until it reaches the timeout and this also prevents the normal upgrade process from completing (--stage can still be used to upgrade but it takes much longer than necessary).

@github-project-automation github-project-automation Bot moved this to To Do in Planning Mar 29, 2026
@talos-bot talos-bot moved this from To Do to In Review in Planning Mar 29, 2026
Comment thread storage/zfs/zfs-service/main.go Resolved
Fixes cases where later tasks fail because the disks are still in use
(e.g. closing encrypted volumes).

Signed-off-by: Galen Abell <[email protected]>
Signed-off-by: Noel Georgi <[email protected]>
@github-project-automation github-project-automation Bot moved this from In Review to Approved in Planning Mar 31, 2026
@frezbo

frezbo commented Mar 31, 2026

Copy link
Copy Markdown
Member

/m

@talos-bot
talos-bot merged commit 5aeaf4e into siderolabs:main Mar 31, 2026
14 checks passed
@github-project-automation github-project-automation Bot moved this from Approved to Done in Planning Mar 31, 2026
@smira smira moved this from Proposed to Accepted in Backports to v1.13 Apr 14, 2026
@smira smira moved this from Accepted to In Progress in Backports to v1.13 Apr 15, 2026
@smira smira moved this from In Progress to Backported in Backports to v1.13 Apr 15, 2026
bernardgut added a commit to bernardgut/extensions that referenced this pull request Jun 1, 2026
Since v1.13.0 (commit 5aeaf4e, PR siderolabs#1028) the zfs-service runs
`zpool export -a` at shutdown via a blocking cmd.Run() that log.Fatalf's
on error, to release the backing device so `cryptsetup close` can finish
on upgrade (the LUKS-on-ZFS case). Talos gives extension services a fixed
10s SIGTERM->SIGKILL grace with no machine-config knob to raise it, so on
busy pools the export overruns that grace: the zpool child is SIGKILLed
mid-export, the parent is SIGKILLed too, and the containerd shim then
hangs ~20 minutes cleaning up the /dev rshared-rbind mount that still
references zvol device nodes.

Make the shutdown export configurable via the ZFS_EXPORT_TIMEOUT env var,
without changing the default:

  - unset (default): run the export unbounded, exactly as before;
  - 0: skip the export entirely (pre-v1.13 behavior);
  - >0 (a Go duration): bound the export with context.WithTimeout,
    exec.CommandContext and WaitDelay; on timeout or error, log and exit 0
    instead of log.Fatalf so the containerd shim can unmount /dev cleanly.
    Un-exported pools are recovered next boot by `zpool import -fal`.

This is a community extension, so the default is left unchanged to avoid
regressing the original LUKS-on-ZFS case, while topologies where the
export only blocks (e.g. DRBD/LUKS over zvols) get an opt-in escape hatch.
Mirrors the in-repo context + CommandContext + WaitDelay pattern from
nvidia-fabricmanager-wrapper. Documents the env var in storage/zfs/README.md.

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
bernardgut added a commit to bernardgut/extensions that referenced this pull request Jun 1, 2026
Since v1.13.0 (siderolabs#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: zpool is SIGKILLed mid-export and the
containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Make the export configurable via ZFS_EXPORT_TIMEOUT, default unchanged:
unset runs it unbounded as before; 0 skips it (pre-v1.13); a positive Go
duration bounds it and, on timeout or error, logs and exits 0 instead of
log.Fatalf so the shim can unmount /dev cleanly (pools are re-imported next
boot by `zpool import -fal`). Leaving the default unchanged avoids
regressing the original LUKS-on-ZFS case.

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
bernardgut added a commit to bernardgut/extensions that referenced this pull request Jun 2, 2026
Since v1.13.0 (siderolabs#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: the service is SIGKILLed mid-export and
the containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Bound the export with context.WithTimeout, exec.CommandContext and WaitDelay
so this PID 1 exits cleanly within the grace; on timeout or error, log and
exit 0 instead of log.Fatalf so the shim can unmount /dev in order (pools are
re-imported next boot by `zpool import -fal`). The bound is configurable via
ZFS_EXPORT_TIMEOUT (a Go duration, default 8s, under the 10s grace); 0 skips
the export entirely (pre-v1.13 behavior).

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
bernardgut added a commit to bernardgut/extensions that referenced this pull request Jun 3, 2026
Since v1.13.0 (siderolabs#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: the service is SIGKILLed mid-export and
the containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Bound the export with context.WithTimeout, exec.CommandContext and WaitDelay
so this PID 1 exits cleanly within the grace; on timeout or error, log and
exit 0 instead of log.Fatalf so the shim can unmount /dev in order (pools are
re-imported next boot by `zpool import -fal`). The bound is configurable via
ZFS_EXPORT_TIMEOUT (a Go duration, default 8s, under the 10s grace); 0 skips
the export entirely (pre-v1.13 behavior).

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
bernardgut added a commit to bernardgut/extensions that referenced this pull request Jun 4, 2026
Since v1.13.0 (siderolabs#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: the service is SIGKILLed mid-export and
the containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Bound the export with context.WithTimeout, exec.CommandContext and WaitDelay
so this PID 1 exits cleanly within the grace; on timeout or error, log and
exit 0 instead of log.Fatalf so the shim can unmount /dev in order (pools are
re-imported next boot by `zpool import -fal`). The bound is configurable via
ZFS_EXPORT_TIMEOUT (a Go duration, default 8s, under the 10s grace); 0 skips
the export entirely (pre-v1.13 behavior).

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
smira pushed a commit to bernardgut/extensions that referenced this pull request Jun 4, 2026
Since v1.13.0 (siderolabs#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: the service is SIGKILLed mid-export and
the containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Bound the export with context.WithTimeout, exec.CommandContext and WaitDelay
so this PID 1 exits cleanly within the grace; on timeout or error, log and
exit 0 instead of log.Fatalf so the shim can unmount /dev in order (pools are
re-imported next boot by `zpool import -fal`). The bound is configurable via
ZFS_EXPORT_TIMEOUT (a Go duration, default 8s, under the 10s grace); 0 skips
the export entirely (pre-v1.13 behavior).

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
Signed-off-by: Andrey Smirnov <[email protected]>
talos-bot pushed a commit that referenced this pull request Jun 9, 2026
Since v1.13.0 (#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: the service is SIGKILLed mid-export and
the containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Bound the export with context.WithTimeout, exec.CommandContext and WaitDelay
so this PID 1 exits cleanly within the grace; on timeout or error, log and
exit 0 instead of log.Fatalf so the shim can unmount /dev in order (pools are
re-imported next boot by `zpool import -fal`). The bound is configurable via
ZFS_EXPORT_TIMEOUT (a Go duration, default 8s, under the 10s grace); 0 skips
the export entirely (pre-v1.13 behavior).

Refs #1085

Signed-off-by: Bernard Gütermann <[email protected]>
Signed-off-by: Andrey Smirnov <[email protected]>
(cherry picked from commit 1b7063c)
rokoucha pushed a commit to rokoucha/siderolabs-extensions that referenced this pull request Oct 27, 2026
Since v1.13.0 (siderolabs#1028) the zfs-service runs `zpool export -a` at shutdown
via a blocking cmd.Run() that log.Fatalf's on error. Talos gives extension
services a fixed 10s SIGTERM->SIGKILL grace with no knob to raise it, so on
busy pools the export overruns it: the service is SIGKILLed mid-export and
the containerd shim then hangs ~20 minutes cleaning up the /dev rbind.

Bound the export with context.WithTimeout, exec.CommandContext and WaitDelay
so this PID 1 exits cleanly within the grace; on timeout or error, log and
exit 0 instead of log.Fatalf so the shim can unmount /dev in order (pools are
re-imported next boot by `zpool import -fal`). The bound is configurable via
ZFS_EXPORT_TIMEOUT (a Go duration, default 8s, under the 10s grace); 0 skips
the export entirely (pre-v1.13 behavior).

Refs siderolabs#1085

Signed-off-by: Bernard Gütermann <[email protected]>
Signed-off-by: Andrey Smirnov <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Backported
Archived in project

Development

Successfully merging this pull request may close these issues.

3 participants