diff --git a/image.go b/image.go index 40dc3ff6cb73c..76b77ee4cb6e5 100644 --- a/image.go +++ b/image.go @@ -336,6 +336,8 @@ func WithUnpackDuplicationSuppressor(suppressor kmutex.KeyedLocker) UnpackOpt { } } +type DiscardUnpackedLayersKey struct{} + func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...UnpackOpt) error { ctx, done, err := i.client.WithLease(ctx) if err != nil { @@ -384,7 +386,24 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...Unpa for _, layer := range layers { unpacked, err = rootfs.ApplyLayerWithOpts(ctx, layer, chain, sn, a, config.SnapshotOpts, config.ApplyOpts) if err != nil { - return err + // layer not found in content, try to fetch layer and retry unpack + if errdefs.IsNotFound(err) { + pullOpts := []RemoteOpt{} + if discardUnpackedLayers, ok := ctx.Value(DiscardUnpackedLayersKey{}).(bool); ok && discardUnpackedLayers { + pullOpts = append(pullOpts, WithChildLabelMap(images.ChildGCLabelsFilterLayers)) + } + + if _, err2 := i.client.Pull(ctx, i.Name(), pullOpts...); err2 != nil { + return fmt.Errorf("fetch lost layer failed: %w : %w", err2, err) + } + // retry + unpacked, err = rootfs.ApplyLayerWithOpts(ctx, layer, chain, sn, a, config.SnapshotOpts, config.ApplyOpts) + if err != nil { + return err + } + } else { + return err + } } if unpacked { diff --git a/pkg/cri/server/container_create.go b/pkg/cri/server/container_create.go index 9483778d19e00..48929bf14a8a7 100644 --- a/pkg/cri/server/container_create.go +++ b/pkg/cri/server/container_create.go @@ -259,6 +259,9 @@ func (c *criService) CreateContainer(ctx context.Context, r *runtime.CreateConta }() var cntr containerd.Container + if c.config.ContainerdConfig.DiscardUnpackedLayers { + ctx = context.WithValue(ctx, containerd.DiscardUnpackedLayersKey{}, true) + } if cntr, err = c.client.NewContainer(ctx, id, opts...); err != nil { return nil, fmt.Errorf("failed to create containerd container: %w", err) } diff --git a/pkg/cri/server/sandbox_run.go b/pkg/cri/server/sandbox_run.go index ebe9facda760d..461a9d99f389f 100644 --- a/pkg/cri/server/sandbox_run.go +++ b/pkg/cri/server/sandbox_run.go @@ -173,6 +173,9 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox containerd.WithContainerExtension(sandboxMetadataExtension, &sandbox.Metadata), containerd.WithRuntime(ociRuntime.Type, runtimeOpts)} + if c.config.ContainerdConfig.DiscardUnpackedLayers { + ctx = context.WithValue(ctx, containerd.DiscardUnpackedLayersKey{}, true) + } container, err := c.client.NewContainer(ctx, id, opts...) if err != nil { return nil, fmt.Errorf("failed to create containerd container: %w", err)