daemon: make the snapshotter configurable

Treat (storage/graph)Driver as snapshotter

Also moved some layerStore related initialization to the non-c8d case
because otherwise they get treated as a graphdriver plugins.

Co-authored-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Djordje Lukic <djordje.lukic@docker.com>
Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Djordje Lukic 2022-08-03 11:20:54 +02:00 committed by Sebastiaan van Stijn
parent 464882e398
commit d8d990f2e3
No known key found for this signature in database
GPG Key ID: 76698F39D527CE8C
6 changed files with 77 additions and 65 deletions

View File

@ -53,7 +53,7 @@ func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, outSt
for _, img := range imgs {
platformImg := containerd.NewImageWithPlatform(i.client, img, platform)
unpacked, err := platformImg.IsUnpacked(ctx, containerd.DefaultSnapshotter)
unpacked, err := platformImg.IsUnpacked(ctx, i.snapshotter)
if err != nil {
// TODO(thaJeztah): remove this log or change to debug once we can; see https://github.com/moby/moby/pull/43822#discussion_r937502405
logrus.WithError(err).WithField("image", img.Name).Debug("failed to check if image is unpacked")
@ -61,7 +61,7 @@ func (i *ImageService) LoadImage(ctx context.Context, inTar io.ReadCloser, outSt
}
if !unpacked {
err := platformImg.Unpack(ctx, containerd.DefaultSnapshotter)
err := platformImg.Unpack(ctx, i.snapshotter)
if err != nil {
// TODO(thaJeztah): remove this log or change to debug once we can; see https://github.com/moby/moby/pull/43822#discussion_r937502405
logrus.WithError(err).WithField("image", img.Name).Warn("failed to unpack image")

View File

@ -41,7 +41,7 @@ func (i *ImageService) Images(ctx context.Context, opts types.ImageListOptions)
return nil, err
}
snapshotter := i.client.SnapshotService(containerd.DefaultSnapshotter)
snapshotter := i.client.SnapshotService(i.snapshotter)
sizeCache := make(map[digest.Digest]int64)
snapshotSizeFn := func(d digest.Digest) (int64, error) {
if s, ok := sizeCache[d]; ok {

View File

@ -13,13 +13,15 @@ import (
// ImageService implements daemon.ImageService
type ImageService struct {
client *containerd.Client
client *containerd.Client
snapshotter string
}
// NewService creates a new ImageService.
func NewService(c *containerd.Client) *ImageService {
func NewService(c *containerd.Client, snapshotter string) *ImageService {
return &ImageService{
client: c,
client: c,
snapshotter: snapshotter,
}
}
@ -81,7 +83,7 @@ func (i *ImageService) Cleanup() error {
// StorageDriver returns the name of the default storage-driver (snapshotter)
// used by the ImageService.
func (i *ImageService) StorageDriver() string {
return ""
return i.snapshotter
}
// ReleaseLayer releases a layer allowing it to be removed

View File

@ -833,22 +833,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
}
}
var graphDriver string
if isWindows {
// On Windows we don't support the environment variable, or a user supplied graphdriver
graphDriver = "windowsfilter"
} else {
// Unix platforms however run a single graphdriver for all containers, and it can
// be set through an environment variable, a daemon start parameter, or chosen through
// initialization of the layerstore through driver priority order for example.
if drv := os.Getenv("DOCKER_DRIVER"); drv != "" {
graphDriver = drv
logrus.Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", drv)
} else {
graphDriver = config.GraphDriver // May still be empty. Layerstore init determines instead.
}
}
d.registryService = registryService
logger.RegisterPluginGetter(d.PluginStore)
@ -938,27 +922,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
return nil, err
}
layerStore, err := layer.NewStoreFromOptions(layer.StoreOptions{
Root: config.Root,
MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
GraphDriver: graphDriver,
GraphDriverOptions: config.GraphOptions,
IDMapping: idMapping,
PluginGetter: d.PluginStore,
ExperimentalEnabled: config.Experimental,
})
if err != nil {
return nil, err
}
// Configure and validate the kernels security support. Note this is a Linux/FreeBSD
// operation only, so it is safe to pass *just* the runtime OS graphdriver.
if err := configureKernelSecuritySupport(config, layerStore.DriverName()); err != nil {
return nil, err
}
imageRoot := filepath.Join(config.Root, "image", layerStore.DriverName())
d.volumes, err = volumesservice.NewVolumeService(config.Root, d.PluginStore, rootIDs, d)
if err != nil {
return nil, err
@ -972,23 +935,6 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
logrus.WithError(err).Warnf("unable to migrate engine ID; a new engine ID will be generated")
}
// We have a single tag/reference store for the daemon globally. However, it's
// stored under the graphdriver. On host platforms which only support a single
// container OS, but multiple selectable graphdrivers, this means depending on which
// graphdriver is chosen, the global reference store is under there. For
// platforms which support multiple container operating systems, this is slightly
// more problematic as where does the global ref store get located? Fortunately,
// for Windows, which is currently the only daemon supporting multiple container
// operating systems, the list of graphdrivers available isn't user configurable.
// For backwards compatibility, we just put it under the windowsfilter
// directory regardless.
refStoreLocation := filepath.Join(imageRoot, `repositories.json`)
rs, err := refstore.NewReferenceStore(refStoreLocation)
if err != nil {
return nil, fmt.Errorf("Couldn't create reference store repository: %s", err)
}
d.ReferenceStore = rs
// Check if Devices cgroup is mounted, it is hard requirement for container security,
// on Linux.
//
@ -1019,14 +965,69 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
d.linkIndex = newLinkIndex()
if d.UsesSnapshotter() {
d.imageService = ctrd.NewService(d.containerdCli)
// On Windows we don't support the environment variable, or a user supplied graphdriver
// Unix platforms however run a single graphdriver for all containers, and it can
// be set through an environment variable, a daemon start parameter, or chosen through
// initialization of the layerstore through driver priority order for example.
driverName := os.Getenv("DOCKER_DRIVER")
if isWindows {
driverName = "windowsfilter"
} else if driverName != "" {
logrus.Infof("Setting the storage driver from the $DOCKER_DRIVER environment variable (%s)", driverName)
} else {
driverName = config.GraphDriver
}
if d.UsesSnapshotter() {
// Configure and validate the kernels security support. Note this is a Linux/FreeBSD
// operation only, so it is safe to pass *just* the runtime OS graphdriver.
if err := configureKernelSecuritySupport(config, driverName); err != nil {
return nil, err
}
d.imageService = ctrd.NewService(d.containerdCli, driverName)
} else {
layerStore, err := layer.NewStoreFromOptions(layer.StoreOptions{
Root: config.Root,
MetadataStorePathTemplate: filepath.Join(config.Root, "image", "%s", "layerdb"),
GraphDriver: driverName,
GraphDriverOptions: config.GraphOptions,
IDMapping: idMapping,
PluginGetter: d.PluginStore,
ExperimentalEnabled: config.Experimental,
})
if err != nil {
return nil, err
}
// Configure and validate the kernels security support. Note this is a Linux/FreeBSD
// operation only, so it is safe to pass *just* the runtime OS graphdriver.
if err := configureKernelSecuritySupport(config, layerStore.DriverName()); err != nil {
return nil, err
}
imageRoot := filepath.Join(config.Root, "image", layerStore.DriverName())
ifs, err := image.NewFSStoreBackend(filepath.Join(imageRoot, "imagedb"))
if err != nil {
return nil, err
}
// We have a single tag/reference store for the daemon globally. However, it's
// stored under the graphdriver. On host platforms which only support a single
// container OS, but multiple selectable graphdrivers, this means depending on which
// graphdriver is chosen, the global reference store is under there. For
// platforms which support multiple container operating systems, this is slightly
// more problematic as where does the global ref store get located? Fortunately,
// for Windows, which is currently the only daemon supporting multiple container
// operating systems, the list of graphdrivers available isn't user configurable.
// For backwards compatibility, we just put it under the windowsfilter
// directory regardless.
refStoreLocation := filepath.Join(imageRoot, `repositories.json`)
rs, err := refstore.NewReferenceStore(refStoreLocation)
if err != nil {
return nil, fmt.Errorf("Couldn't create reference store repository: %s", err)
}
d.ReferenceStore = rs
imageStore, err := image.NewImageStore(ifs, layerStore)
if err != nil {
return nil, err

View File

@ -822,7 +822,7 @@ func configureKernelSecuritySupport(config *config.Config, driverName string) er
return nil
}
if driverName == "overlay" || driverName == "overlay2" {
if driverName == "overlay" || driverName == "overlay2" || driverName == "overlayfs" {
// If driver is overlay or overlay2, make sure kernel
// supports selinux with overlay.
supported, err := overlaySupportsSelinux()

View File

@ -1045,8 +1045,17 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
if daemon.configStore.Rootless {
opts = append(opts, WithRootless(daemon))
}
var snapshotter, snapshotKey string
if daemon.UsesSnapshotter() {
snapshotter = daemon.imageService.StorageDriver()
snapshotKey = c.ID
}
return &s, coci.ApplyOpts(context.Background(), nil, &containers.Container{
ID: c.ID,
ID: c.ID,
Snapshotter: snapshotter,
SnapshotKey: snapshotKey,
}, &s, opts...)
}