Merge pull request #44934 from laurazard/c8d-layer-size

containerd integration: compute containers layer size
This commit is contained in:
Sebastiaan van Stijn 2023-03-08 08:44:17 +01:00 committed by GitHub
commit d7e5708bb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 96 additions and 23 deletions

View file

@ -49,7 +49,7 @@ type stateBackend interface {
// monitorBackend includes functions to implement to provide containers monitoring functionality.
type monitorBackend interface {
ContainerChanges(name string) ([]archive.Change, error)
ContainerInspect(name string, size bool, version string) (interface{}, error)
ContainerInspect(ctx context.Context, name string, size bool, version string) (interface{}, error)
ContainerLogs(ctx context.Context, name string, config *types.ContainerLogsOptions) (msgs <-chan *backend.LogMessage, tty bool, err error)
ContainerStats(ctx context.Context, name string, config *backend.ContainerStatsConfig) error
ContainerTop(name string, psArgs string) (*container.ContainerTopOKBody, error)

View file

@ -12,7 +12,7 @@ func (s *containerRouter) getContainersByName(ctx context.Context, w http.Respon
displaySize := httputils.BoolValue(r, "size")
version := httputils.VersionFromContext(ctx)
json, err := s.backend.ContainerInspect(vars["name"], displaySize, version)
json, err := s.backend.ContainerInspect(ctx, vars["name"], displaySize, version)
if err != nil {
return err
}

View file

@ -45,7 +45,7 @@ type Backend interface {
ActivateContainerServiceBinding(containerName string) error
DeactivateContainerServiceBinding(containerName string) error
UpdateContainerServiceConfig(containerName string, serviceConfig *clustertypes.ServiceConfig) error
ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error)
ContainerInspectCurrent(ctx context.Context, name string, size bool) (*types.ContainerJSON, error)
ContainerWait(ctx context.Context, name string, condition containerpkg.WaitCondition) (<-chan containerpkg.StateStatus, error)
ContainerRm(name string, config *types.ContainerRmConfig) error
ContainerKill(name string, sig string) error

View file

@ -361,7 +361,7 @@ func (c *containerAdapter) start(ctx context.Context) error {
}
func (c *containerAdapter) inspect(ctx context.Context) (types.ContainerJSON, error) {
cs, err := c.backend.ContainerInspectCurrent(c.container.name(), false)
cs, err := c.backend.ContainerInspectCurrent(ctx, c.container.name(), false)
if ctx.Err() != nil {
return types.ContainerJSON{}, ctx.Err()
}

View file

@ -2,8 +2,10 @@ package containerd
import (
"context"
"encoding/json"
"github.com/containerd/containerd"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/remotes/docker"
"github.com/containerd/containerd/snapshots"
@ -13,6 +15,9 @@ import (
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/registry"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/identity"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@ -139,6 +144,56 @@ func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer)
}
// GetContainerLayerSize returns the real size & virtual size of the container.
func (i *ImageService) GetContainerLayerSize(containerID string) (int64, int64) {
panic("not implemented")
func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error) {
ctr := i.containers.Get(containerID)
if ctr == nil {
return 0, 0, nil
}
cs := i.client.ContentStore()
imageManifestBytes, err := content.ReadBlob(ctx, cs, *ctr.ImageManifest)
if err != nil {
return 0, 0, err
}
var manifest ocispec.Manifest
if err := json.Unmarshal(imageManifestBytes, &manifest); err != nil {
return 0, 0, err
}
imageConfigBytes, err := content.ReadBlob(ctx, cs, manifest.Config)
if err != nil {
return 0, 0, err
}
var img ocispec.Image
if err := json.Unmarshal(imageConfigBytes, &img); err != nil {
return 0, 0, err
}
snapshotter := i.client.SnapshotService(i.snapshotter)
usage, err := snapshotter.Usage(ctx, containerID)
if err != nil {
return 0, 0, err
}
sizeCache := make(map[digest.Digest]int64)
snapshotSizeFn := func(d digest.Digest) (int64, error) {
if s, ok := sizeCache[d]; ok {
return s, nil
}
u, err := snapshotter.Usage(ctx, d.String())
if err != nil {
return 0, err
}
sizeCache[d] = u.Size
return u.Size, nil
}
chainIDs := identity.ChainIDs(img.RootFS.DiffIDs)
virtualSize, err := computeVirtualSize(chainIDs, snapshotSizeFn)
if err != nil {
return 0, 0, err
}
return usage.Size, usage.Size + virtualSize, nil
}

View file

@ -57,7 +57,7 @@ type ImageService interface {
GetLayerMountID(cid string) (string, error)
ReleaseLayer(rwlayer layer.RWLayer) error
LayerDiskUsage(ctx context.Context) (int64, error)
GetContainerLayerSize(containerID string) (int64, int64)
GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error)
Mount(ctx context.Context, container *container.Container) error
Unmount(ctx context.Context, container *container.Container) error

View file

@ -4,6 +4,8 @@
package images // import "github.com/docker/docker/daemon/images"
import (
"context"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/sirupsen/logrus"
@ -16,7 +18,7 @@ func (i *ImageService) GetLayerFolders(img *image.Image, rwLayer layer.RWLayer)
}
// GetContainerLayerSize returns the real size & virtual size of the container.
func (i *ImageService) GetContainerLayerSize(containerID string) (int64, int64) {
func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error) {
var (
sizeRw, sizeRootfs int64
err error
@ -27,7 +29,7 @@ func (i *ImageService) GetContainerLayerSize(containerID string) (int64, int64)
rwlayer, err := i.layerStore.GetRWLayer(containerID)
if err != nil {
logrus.Errorf("Failed to compute size of container rootfs %v: %v", containerID, err)
return sizeRw, sizeRootfs
return sizeRw, sizeRootfs, nil
}
defer i.layerStore.ReleaseRWLayer(rwlayer)
@ -46,5 +48,5 @@ func (i *ImageService) GetContainerLayerSize(containerID string) (int64, int64)
sizeRootfs += sizeRw
}
}
return sizeRw, sizeRootfs
return sizeRw, sizeRootfs, nil
}

View file

@ -1,6 +1,8 @@
package images
import (
"context"
"github.com/docker/docker/image"
"github.com/docker/docker/layer"
"github.com/docker/docker/pkg/system"
@ -8,9 +10,9 @@ import (
)
// GetContainerLayerSize returns real size & virtual size
func (i *ImageService) GetContainerLayerSize(containerID string) (int64, int64) {
func (i *ImageService) GetContainerLayerSize(ctx context.Context, containerID string) (int64, int64, error) {
// TODO Windows
return 0, 0
return 0, 0, nil
}
// GetLayerFolders returns the layer folders from an image RootFS

View file

@ -1,6 +1,7 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"errors"
"fmt"
"time"
@ -19,19 +20,19 @@ import (
// ContainerInspect returns low-level information about a
// container. Returns an error if the container cannot be found, or if
// there is an error getting the data.
func (daemon *Daemon) ContainerInspect(name string, size bool, version string) (interface{}, error) {
func (daemon *Daemon) ContainerInspect(ctx context.Context, name string, size bool, version string) (interface{}, error) {
switch {
case versions.LessThan(version, "1.20"):
return daemon.containerInspectPre120(name)
return daemon.containerInspectPre120(ctx, name)
case versions.Equal(version, "1.20"):
return daemon.containerInspect120(name)
}
return daemon.ContainerInspectCurrent(name, size)
return daemon.ContainerInspectCurrent(ctx, name, size)
}
// ContainerInspectCurrent returns low-level information about a
// container in a most recent api version.
func (daemon *Daemon) ContainerInspectCurrent(name string, size bool) (*types.ContainerJSON, error) {
func (daemon *Daemon) ContainerInspectCurrent(ctx context.Context, name string, size bool) (*types.ContainerJSON, error) {
ctr, err := daemon.GetContainer(name)
if err != nil {
return nil, err
@ -78,7 +79,10 @@ func (daemon *Daemon) ContainerInspectCurrent(name string, size bool) (*types.Co
ctr.Unlock()
if size {
sizeRw, sizeRootFs := daemon.imageService.GetContainerLayerSize(base.ID)
sizeRw, sizeRootFs, err := daemon.imageService.GetContainerLayerSize(ctx, base.ID)
if err != nil {
return nil, err
}
base.SizeRw = &sizeRw
base.SizeRootFs = &sizeRootFs
}

View file

@ -1,6 +1,8 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/api/types/versions/v1p19"
@ -18,7 +20,7 @@ func setPlatformSpecificContainerFields(container *container.Container, contJSON
}
// containerInspectPre120 gets containers for pre 1.20 APIs.
func (daemon *Daemon) containerInspectPre120(name string) (*v1p19.ContainerJSON, error) {
func (daemon *Daemon) containerInspectPre120(ctx context.Context, name string) (*v1p19.ContainerJSON, error) {
ctr, err := daemon.GetContainer(name)
if err != nil {
return nil, err

View file

@ -1,6 +1,8 @@
package daemon // import "github.com/docker/docker/daemon"
import (
"context"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/backend"
"github.com/docker/docker/container"
@ -12,8 +14,8 @@ func setPlatformSpecificContainerFields(container *container.Container, contJSON
}
// containerInspectPre120 get containers for pre 1.20 APIs.
func (daemon *Daemon) containerInspectPre120(name string) (*types.ContainerJSON, error) {
return daemon.ContainerInspectCurrent(name, false)
func (daemon *Daemon) containerInspectPre120(ctx context.Context, name string) (*types.ContainerJSON, error) {
return daemon.ContainerInspectCurrent(ctx, name, false)
}
func inspectExecProcessConfig(e *container.ExecConfig) *backend.ExecProcessConfig {

View file

@ -238,7 +238,10 @@ func (daemon *Daemon) reducePsContainer(ctx context.Context, container *containe
// release lock because size calculation is slow
if filter.Size {
sizeRw, sizeRootFs := daemon.imageService.GetContainerLayerSize(newC.ID)
sizeRw, sizeRootFs, err := daemon.imageService.GetContainerLayerSize(ctx, newC.ID)
if err != nil {
return nil, err
}
newC.SizeRw = sizeRw
newC.SizeRootFs = sizeRootFs
}

View file

@ -73,9 +73,12 @@ func (daemon *Daemon) ContainersPrune(ctx context.Context, pruneFilters filters.
if !matchLabels(pruneFilters, c.Config.Labels) {
continue
}
cSize, _ := daemon.imageService.GetContainerLayerSize(c.ID)
cSize, _, err := daemon.imageService.GetContainerLayerSize(ctx, c.ID)
if err != nil {
return nil, err
}
// TODO: sets RmLink to true?
err := daemon.ContainerRm(c.ID, &types.ContainerRmConfig{})
err = daemon.ContainerRm(c.ID, &types.ContainerRmConfig{})
if err != nil {
logrus.Warnf("failed to prune container %s: %v", c.ID, err)
continue