overlay: Require opt-in if idmap mounts are not supported.

If we don't use idmap mounts, doing a chown per pod is very expensive:
it implies duplicating the container storage for the image for every pod
and the latency to start a new pod is affected too.

Let's make sure users are aware of this, by having them opt-in, for
snapshotters that we have a better solution (like overlayfs, that has
support for idmap mounts).

Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
This commit is contained in:
Rodrigo Campos 2023-09-19 13:08:05 +02:00
parent 00666764b8
commit ec9e0dca91
3 changed files with 36 additions and 2 deletions

View File

@ -46,6 +46,7 @@ type SnapshotterConfig struct {
ms MetaStore ms MetaStore
mountOptions []string mountOptions []string
remapIds bool remapIds bool
slowChown bool
} }
// Opt is an option to configure the overlay snapshotter // Opt is an option to configure the overlay snapshotter
@ -98,6 +99,11 @@ func WithRemapIds(config *SnapshotterConfig) error {
return nil return nil
} }
func WithSlowChown(config *SnapshotterConfig) error {
config.slowChown = true
return nil
}
type snapshotter struct { type snapshotter struct {
root string root string
ms MetaStore ms MetaStore
@ -105,6 +111,7 @@ type snapshotter struct {
upperdirLabel bool upperdirLabel bool
options []string options []string
remapIds bool remapIds bool
slowChown bool
} }
// NewSnapshotter returns a Snapshotter which uses overlayfs. The overlayfs // NewSnapshotter returns a Snapshotter which uses overlayfs. The overlayfs
@ -161,6 +168,7 @@ func NewSnapshotter(root string, opts ...Opt) (snapshots.Snapshotter, error) {
upperdirLabel: config.upperdirLabel, upperdirLabel: config.upperdirLabel,
options: config.mountOptions, options: config.mountOptions,
remapIds: config.remapIds, remapIds: config.remapIds,
slowChown: config.slowChown,
}, nil }, nil
} }

View File

@ -28,7 +28,8 @@ import (
) )
const ( const (
capaRemapIds = "remap-ids" capaRemapIds = "remap-ids"
capaOnlyRemapIds = "only-remap-ids"
) )
// Config represents configuration for the overlay plugin. // Config represents configuration for the overlay plugin.
@ -38,6 +39,11 @@ type Config struct {
UpperdirLabel bool `toml:"upperdir_label"` UpperdirLabel bool `toml:"upperdir_label"`
SyncRemove bool `toml:"sync_remove"` SyncRemove bool `toml:"sync_remove"`
// slowChown allows the plugin to fallback to a recursive chown if fast options (like
// idmap mounts) are not available. See more info about the overhead this can have in
// github.com/containerd/containerd/docs/user-namespaces/.
SlowChown bool `toml:"slow_chown"`
// MountOptions are options used for the overlay mount (not used on bind mounts) // MountOptions are options used for the overlay mount (not used on bind mounts)
MountOptions []string `toml:"mount_options"` MountOptions []string `toml:"mount_options"`
} }
@ -76,6 +82,14 @@ func init() {
ic.Meta.Capabilities = append(ic.Meta.Capabilities, capaRemapIds) ic.Meta.Capabilities = append(ic.Meta.Capabilities, capaRemapIds)
} }
if config.SlowChown {
oOpts = append(oOpts, overlay.WithSlowChown)
} else {
// If slowChown is false, we use capaOnlyRemapIds to signal we only
// allow idmap mounts.
ic.Meta.Capabilities = append(ic.Meta.Capabilities, capaOnlyRemapIds)
}
ic.Meta.Exports["root"] = root ic.Meta.Exports["root"] = root
return overlay.NewSnapshotter(root, oOpts...) return overlay.NewSnapshotter(root, oOpts...)
}, },

View File

@ -26,7 +26,8 @@ import (
) )
const ( const (
capabRemapIDs = "remap-ids" capabRemapIDs = "remap-ids"
capaOnlyRemapIds = "only-remap-ids"
) )
// WithRemapperLabels creates the labels used by any supporting snapshotter // WithRemapperLabels creates the labels used by any supporting snapshotter
@ -72,6 +73,17 @@ func resolveSnapshotOptions(ctx context.Context, client *Client, snapshotterName
return parent, nil return parent, nil
} }
capaOnlyRemap := false
for _, capa := range capabs {
if capa == capaOnlyRemapIds {
capaOnlyRemap = true
}
}
if capaOnlyRemap {
return "", fmt.Errorf("snapshotter %q doesn't support idmap mounts on this host, configure `slow_chown` to allow a slower and expensive fallback", snapshotterName)
}
var ctrUID, hostUID, length uint32 var ctrUID, hostUID, length uint32
_, err = fmt.Sscanf(uidMap, "%d:%d:%d", &ctrUID, &hostUID, &length) _, err = fmt.Sscanf(uidMap, "%d:%d:%d", &ctrUID, &hostUID, &length)
if err != nil { if err != nil {