gc: add a policy to skip garbage collecting new blobs

We perform inline garbage collection of orphan blobs. However, the
dist-spec poses a problem because blobs begin their life as orphan blobs
and then a manifest is add which refers to these blobs.

We use umoci's GC() to perform garbage collection and policy support
has been added recently which can control whether a blob can be skipped
for GC.

In this patch, we use a time-based policy to skip blobs.
This commit is contained in:
Ramkumar Chinchani
2020-06-30 10:56:58 -07:00
parent 80244f1282
commit 324a517ea3
6 changed files with 50 additions and 6 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ go_library(
go_test(
name = "go_default_test",
timeout = "short",
timeout = "moderate",
srcs = ["controller_test.go"],
data = [
"//:exported_testdata",
+2
View File
@@ -11,10 +11,12 @@ go_library(
deps = [
"//errors:go_default_library",
"//pkg/log:go_default_library",
"@com_github_apex_log//:go_default_library",
"@com_github_gofrs_uuid//:go_default_library",
"@com_github_opencontainers_go_digest//:go_default_library",
"@com_github_opencontainers_image_spec//specs-go/v1:go_default_library",
"@com_github_opencontainers_umoci//:go_default_library",
"@com_github_opencontainers_umoci//oci/casext:go_default_library",
"@com_github_rs_zerolog//:go_default_library",
"@io_etcd_go_bbolt//:go_default_library",
],
+39 -2
View File
@@ -11,13 +11,16 @@ import (
"path"
"path/filepath"
"sync"
"time"
"github.com/anuvu/zot/errors"
zlog "github.com/anuvu/zot/pkg/log"
apexlog "github.com/apex/log"
guuid "github.com/gofrs/uuid"
godigest "github.com/opencontainers/go-digest"
ispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/umoci"
"github.com/opencontainers/umoci/oci/casext"
"github.com/rs/zerolog"
)
@@ -25,6 +28,7 @@ const (
// BlobUploadDir defines the upload directory for blob uploads.
BlobUploadDir = ".uploads"
schemaVersion = 2
gcDelay = 1 * time.Hour
)
// BlobUpload models and upload request.
@@ -66,6 +70,20 @@ func NewImageStore(rootDir string, gc bool, dedupe bool, log zlog.Logger) *Image
is.cache = NewCache(rootDir, "cache", log)
}
if gc {
// we use umoci GC to perform garbage-collection, but it uses its own logger
// - so capture those logs, could be useful
apexlog.SetLevel(apexlog.DebugLevel)
apexlog.SetHandler(apexlog.HandlerFunc(func(entry *apexlog.Entry) error {
e := log.Debug()
for k, v := range entry.Fields {
e = e.Interface(k, v)
}
e.Msg(entry.Message)
return nil
}))
}
return is
}
@@ -492,7 +510,7 @@ func (is *ImageStore) PutImageManifest(repo string, reference string, mediaType
}
defer oci.Close()
if err := oci.GC(context.Background()); err != nil {
if err := oci.GC(context.Background(), ifOlderThan(is, repo, gcDelay)); err != nil {
return "", err
}
}
@@ -568,7 +586,7 @@ func (is *ImageStore) DeleteImageManifest(repo string, reference string) error {
}
defer oci.Close()
if err := oci.GC(context.Background()); err != nil {
if err := oci.GC(context.Background(), ifOlderThan(is, repo, gcDelay)); err != nil {
return err
}
}
@@ -1025,3 +1043,22 @@ func ensureDir(dir string, log zerolog.Logger) {
log.Panic().Err(err).Str("dir", dir).Msg("unable to create dir")
}
}
func ifOlderThan(is *ImageStore, repo string, delay time.Duration) casext.GCPolicy {
return func(ctx context.Context, digest godigest.Digest) (bool, error) {
blobPath := is.BlobPath(repo, digest)
fi, err := os.Stat(blobPath)
if err != nil {
return false, err
}
if fi.ModTime().Add(delay).After(time.Now()) {
return false, nil
}
is.log.Info().Str("digest", digest.String()).Str("blobPath", blobPath).Msg("perform GC on blob")
return true, nil
}
}