diff --git a/contrib/nydusify/pkg/cache/cache.go b/contrib/nydusify/pkg/cache/cache.go index a8b7a7ddd40..605b795a730 100644 --- a/contrib/nydusify/pkg/cache/cache.go +++ b/contrib/nydusify/pkg/cache/cache.go @@ -29,7 +29,16 @@ import ( type Opt struct { // Maximum records(bootstrap layer + blob layer) in cache image. MaxRecords uint - Version string + // Version of cache image, we need to discard cache layers when + // the required version (specified by `--build-cache-version`) + // is unmatched with the cache image version, for example nydus + // bootstrap format has a minor upgrade. + Version string + // Bootstrap's RAFS version of cache image, we need to discard cache + // layers when the required version (specified by `--fs-version`) is + // unmatched with the fs version recorded in cache image, for example + // we can't use rafs v5 cache layers for rafs v6 image. + FsVersion string // Make cache image manifest compatible with the docker v2 media // type defined in github.com/containerd/containerd/images. DockerV2Format bool @@ -129,6 +138,7 @@ func (cache *Cache) recordToLayer(record *Record) (*ocispec.Descriptor, *ocispec Size: record.NydusBootstrapDesc.Size, Annotations: map[string]string{ utils.LayerAnnotationNydusBootstrap: "true", + utils.LayerAnnotationNydusFsVersion: cache.opt.FsVersion, utils.LayerAnnotationNydusSourceChainID: record.SourceChainID.String(), // Use the annotation to record bootstrap layer DiffID. utils.LayerAnnotationUncompressed: record.NydusBootstrapDiffID.String(), @@ -230,6 +240,7 @@ func (cache *Cache) layerToRecord(layer *ocispec.Descriptor) *Record { Size: layer.Size, Annotations: map[string]string{ utils.LayerAnnotationNydusBootstrap: "true", + utils.LayerAnnotationNydusFsVersion: cache.opt.FsVersion, utils.LayerAnnotationUncompressed: uncompressedDigestStr, }, } @@ -402,7 +413,8 @@ func (cache *Cache) Export(ctx context.Context) error { Config: *configDesc, Layers: layers, Annotations: map[string]string{ - utils.ManifestNydusCache: cache.opt.Version, + utils.ManifestNydusCache: cache.opt.Version, + utils.LayerAnnotationNydusFsVersion: cache.opt.FsVersion, }, }, } @@ -443,7 +455,7 @@ func (cache *Cache) Import(ctx context.Context) error { return errors.Wrap(err, "Unmarshal cache manifest") } - // Discard the cache mismatched version + // Discard the cache if mismatched version if manifest.Annotations[utils.ManifestNydusCache] != cache.opt.Version { return fmt.Errorf( "unmatched cache image version %s, required to be %s", @@ -451,6 +463,14 @@ func (cache *Cache) Import(ctx context.Context) error { ) } + // Discard the cache if mismatched RAFS FsVersion + if manifest.Annotations[utils.LayerAnnotationNydusFsVersion] != cache.opt.FsVersion { + return fmt.Errorf( + "unmatched cache image version %s, required to be %s", + manifest.Annotations[utils.LayerAnnotationNydusFsVersion], cache.opt.FsVersion, + ) + } + cache.importRecordsFromLayers(manifest.Layers) return nil diff --git a/contrib/nydusify/pkg/cache/cache_test.go b/contrib/nydusify/pkg/cache/cache_test.go index 8d5a7f0249e..a45eb6a263a 100644 --- a/contrib/nydusify/pkg/cache/cache_test.go +++ b/contrib/nydusify/pkg/cache/cache_test.go @@ -47,6 +47,7 @@ func makeBootstrapLayer(id int64, hasBlob bool) ocispec.Descriptor { Size: id, Annotations: map[string]string{ utils.LayerAnnotationNydusBootstrap: "true", + utils.LayerAnnotationNydusFsVersion: "6", utils.LayerAnnotationNydusSourceChainID: digest.FromString("chain-" + idStr).String(), utils.LayerAnnotationUncompressed: digest.FromString("bootstrap-uncompressed-" + idStr).String(), }, @@ -76,6 +77,7 @@ func testWithBackend(t *testing.T, _backend backend.Backend) { MaxRecords: 3, DockerV2Format: false, Backend: _backend, + FsVersion: "6", }) assert.Nil(t, err) diff --git a/contrib/nydusify/pkg/converter/cache.go b/contrib/nydusify/pkg/converter/cache.go index 259f6988460..af08d053bfc 100644 --- a/contrib/nydusify/pkg/converter/cache.go +++ b/contrib/nydusify/pkg/converter/cache.go @@ -29,7 +29,7 @@ type cacheGlue struct { } func newCacheGlue( - ctx context.Context, maxRecords uint, version string, dockerV2Format bool, remote *remote.Remote, cacheRemote *remote.Remote, backend backend.Backend, + ctx context.Context, maxRecords uint, version string, fsVersion string, dockerV2Format bool, remote *remote.Remote, cacheRemote *remote.Remote, backend backend.Backend, ) (*cacheGlue, error) { if cacheRemote == nil { return &cacheGlue{}, nil @@ -41,6 +41,7 @@ func newCacheGlue( cache, err := cache.New(cacheRemote, cache.Opt{ MaxRecords: maxRecords, Version: version, + FsVersion: fsVersion, DockerV2Format: dockerV2Format, Backend: backend, }) diff --git a/contrib/nydusify/pkg/converter/converter.go b/contrib/nydusify/pkg/converter/converter.go index 5b77a46bf31..8aad6d26bb3 100644 --- a/contrib/nydusify/pkg/converter/converter.go +++ b/contrib/nydusify/pkg/converter/converter.go @@ -183,7 +183,7 @@ func (cvt *Converter) convert(ctx context.Context) (retErr error) { // Try to pull Nydus cache image from remote registry cg, err := newCacheGlue( - ctx, cvt.CacheMaxRecords, cvt.CacheVersion, cvt.DockerV2Format, cvt.TargetRemote, cvt.CacheRemote, cvt.storageBackend, + ctx, cvt.CacheMaxRecords, cvt.CacheVersion, cvt.FsVersion, cvt.DockerV2Format, cvt.TargetRemote, cvt.CacheRemote, cvt.storageBackend, ) if err != nil { return errors.Wrap(err, "Pull cache image") @@ -254,6 +254,7 @@ func (cvt *Converter) convert(ctx context.Context) (retErr error) { forcePush: cvt.BackendForcePush, alignedChunk: cvt.BackendAlignedChunk, referenceBlobs: blobLayers, + fsVersion: cvt.FsVersion, } parentBuildLayer = buildLayer buildLayers = append(buildLayers, buildLayer) diff --git a/contrib/nydusify/pkg/converter/layer.go b/contrib/nydusify/pkg/converter/layer.go index 447606671e2..40f18793652 100644 --- a/contrib/nydusify/pkg/converter/layer.go +++ b/contrib/nydusify/pkg/converter/layer.go @@ -56,8 +56,8 @@ type buildLayer struct { backend backend.Backend forcePush bool alignedChunk bool - - referenceBlobs []ocispec.Descriptor + fsVersion string + referenceBlobs []ocispec.Descriptor } // parseSourceMount parses mounts object returned by the Mount method in @@ -159,6 +159,7 @@ func (layer *buildLayer) pushBootstrap(ctx context.Context) (*ocispec.Descriptor // DiffID of layer defined in OCI spec utils.LayerAnnotationUncompressed: uncompressedDigest.String(), utils.LayerAnnotationNydusBootstrap: "true", + utils.LayerAnnotationNydusFsVersion: layer.fsVersion, }, } if len(layer.referenceBlobs) > 0 { diff --git a/contrib/nydusify/pkg/converter/manifest.go b/contrib/nydusify/pkg/converter/manifest.go index 1a1f09f0935..b652af0932c 100644 --- a/contrib/nydusify/pkg/converter/manifest.go +++ b/contrib/nydusify/pkg/converter/manifest.go @@ -253,6 +253,7 @@ func (mm *manifestManager) Push(ctx context.Context, buildLayers []*buildLayer) utils.LayerAnnotationNydusBlobIDs: true, utils.LayerAnnotationNydusReferenceBlobIDs: true, utils.LayerAnnotationNydusBootstrap: true, + utils.LayerAnnotationNydusFsVersion: true, } for idx, desc := range layers { layerDiffID := digest.Digest(desc.Annotations[utils.LayerAnnotationUncompressed]) diff --git a/contrib/nydusify/pkg/utils/constant.go b/contrib/nydusify/pkg/utils/constant.go index dbcde40044d..bafdf59d8bf 100644 --- a/contrib/nydusify/pkg/utils/constant.go +++ b/contrib/nydusify/pkg/utils/constant.go @@ -16,6 +16,7 @@ const ( LayerAnnotationNydusBlobSize = "containerd.io/snapshot/nydus-blob-size" LayerAnnotationNydusBlobIDs = "containerd.io/snapshot/nydus-blob-ids" LayerAnnotationNydusBootstrap = "containerd.io/snapshot/nydus-bootstrap" + LayerAnnotationNydusFsVersion = "containerd.io/snapshot/nydus-fs-version" LayerAnnotationNydusSourceChainID = "containerd.io/snapshot/nydus-source-chainid" LayerAnnotationNydusReferenceBlobIDs = "containerd.io/snapshot/nydus-reference-blob-ids"