diff --git a/cache/blobs.go b/cache/blobs.go index 88ea08b8a00b..81e5b8e93fda 100644 --- a/cache/blobs.go +++ b/cache/blobs.go @@ -1,11 +1,17 @@ package cache import ( + "bufio" "context" "fmt" + "io" "os" + "path" "strconv" + obdlabel "github.com/containerd/accelerated-container-image/pkg/label" + obdcmd "github.com/containerd/accelerated-container-image/pkg/utils" + "github.com/containerd/containerd/content" "github.com/containerd/containerd/diff" "github.com/containerd/containerd/diff/walking" "github.com/containerd/containerd/leases" @@ -96,7 +102,17 @@ func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool compressorFunc, finalize := comp.Type.Compress(ctx, comp) mediaType := comp.Type.MediaType() - + var isOverlaybd = false + if sr.cm.Snapshotter.Name() == "overlaybd" { + snStat, err := sr.cm.Snapshotter.Stat(ctx, sr.getSnapshotID()) + if err != nil { + return nil, err + } + if snStat.Labels[obdlabel.LocalOverlayBDPath] != "" { + isOverlaybd = true + mediaType = ocispecs.MediaTypeImageLayer + } + } var lowerRef *immutableRef switch sr.kind() { case Diff: @@ -162,7 +178,7 @@ func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool // (in which case lower and upper may differ by more than one layer), so print warn log on unexpected // failure. logWarnOnErr = sr.kind() != Diff - case "fuse-overlayfs", "native": + case "fuse-overlayfs", "native", "overlaybd": // not supported with fuse-overlayfs snapshotter which doesn't provide overlayfs mounts. // TODO: add support for fuse-overlayfs enableOverlay = false @@ -188,6 +204,13 @@ func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool } } + if isOverlaybd { + if err := commitOverlaybd(ctx, sr, &desc); err != nil { + return nil, err + } + desc.MediaType = mediaType + } + if desc.Digest == "" && !isTypeWindows(sr) && comp.Type.NeedsComputeDiffBySelf() { // These compression types aren't supported by containerd differ. So try to compute diff on buildkit side. // This case can be happen on containerd worker + non-overlayfs snapshotter (e.g. native). @@ -462,3 +485,45 @@ func ensureCompression(ctx context.Context, ref *immutableRef, comp compression. }) return err } + +func commitOverlaybd(ctx context.Context, sr *immutableRef, desc *ocispecs.Descriptor) error { + snStat, err := sr.cm.Snapshotter.Stat(ctx, sr.getSnapshotID()) + if err != nil { + return errors.Wrapf(err, "failed to Stat overlaybd") + } + dir := path.Dir(snStat.Labels[obdlabel.LocalOverlayBDPath]) + commitPath := path.Join(dir, "overlaybd.commit") + err = obdcmd.Commit(ctx, dir, dir, true, "-t", "-z") + if err != nil { + return errors.Wrapf(err, "failed to overlaybd-commit") + } + cw, err := sr.cm.ContentStore.Writer(ctx, content.WithRef(sr.ID())) + if err != nil { + return errors.Wrapf(err, "failed to open writer") + } + fi, err := os.Open(commitPath) + if err != nil { + return errors.Wrapf(err, "failed to open overlaybd commit file") + } + sz, err := io.Copy(cw, bufio.NewReader(fi)) + if err != nil { + return errors.Wrapf(err, "failed to do io.Copy()") + } + dgst := cw.Digest() + labels := map[string]string{ + containerdUncompressed: dgst.String(), + obdlabel.OverlayBDBlobDigest: dgst.String(), + obdlabel.OverlayBDBlobSize: fmt.Sprintf("%d", sz), + } + err = cw.Commit(ctx, sz, dgst, content.WithLabels(labels)) + if err != nil { + return errors.Wrapf(err, "failed to do cw.Commit") + } + desc.Digest = dgst + desc.Size = sz + desc.Annotations = map[string]string{ + obdlabel.OverlayBDBlobDigest: string(desc.Digest), + obdlabel.OverlayBDBlobSize: fmt.Sprintf("%d", desc.Size), + } + return nil +} diff --git a/cache/manager.go b/cache/manager.go index 48a6f612fb0c..8c8881d0dc6f 100644 --- a/cache/manager.go +++ b/cache/manager.go @@ -8,12 +8,14 @@ import ( "sync" "time" + obdlabel "github.com/containerd/accelerated-container-image/pkg/label" "github.com/containerd/containerd/content" "github.com/containerd/containerd/diff" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/filters" "github.com/containerd/containerd/gc" "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/snapshots" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/cache/metadata" "github.com/moby/buildkit/client" @@ -615,6 +617,10 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, sess session.Gr }); rerr != nil { return nil, rerr } + } else if cm.Snapshotter.Name() == "overlaybd" && parent != nil { + // Snapshotter will create a R/W block device directly as rootfs with this label + rwLabels := map[string]string{obdlabel.SupportReadWriteMode: "dev"} + err = cm.Snapshotter.Prepare(ctx, snapshotID, parentSnapshotID, snapshots.WithLabels(rwLabels)) } else { err = cm.Snapshotter.Prepare(ctx, snapshotID, parentSnapshotID) } diff --git a/cache/refs.go b/cache/refs.go index 338dbd664c96..5fad69a00040 100644 --- a/cache/refs.go +++ b/cache/refs.go @@ -9,6 +9,7 @@ import ( "sync" "time" + obdlabel "github.com/containerd/accelerated-container-image/pkg/label" "github.com/containerd/containerd/content" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/images" @@ -39,7 +40,7 @@ import ( "golang.org/x/sync/errgroup" ) -var additionalAnnotations = append(compression.EStargzAnnotations, containerdUncompressed) +var additionalAnnotations = append(append(compression.EStargzAnnotations, obdlabel.OverlayBDAnnotations...), containerdUncompressed) // Ref is a reference to cacheable objects. type Ref interface { @@ -1010,6 +1011,10 @@ func (sr *immutableRef) Extract(ctx context.Context, s session.Group) (rerr erro return err } return rerr + } else if sr.cm.Snapshotter.Name() == "overlaybd" { + if rerr = sr.prepareRemoteSnapshotsOverlaybdMode(ctx, s); rerr == nil { + return sr.unlazy(ctx, sr.descHandlers, sr.progress, s, true) + } } return sr.unlazy(ctx, sr.descHandlers, sr.progress, s, true) @@ -1126,6 +1131,60 @@ func (sr *immutableRef) prepareRemoteSnapshotsStargzMode(ctx context.Context, s return err } +func (sr *immutableRef) prepareRemoteSnapshotsOverlaybdMode(ctx context.Context, s session.Group) error { + _, err := sr.sizeG.Do(ctx, sr.ID()+"-prepare-remote-snapshot", func(ctx context.Context) (_ interface{}, rerr error) { + dhs := sr.descHandlers + for _, r := range sr.layerChain() { + r := r + snapshotID := r.getSnapshotID() + if _, err := r.cm.Snapshotter.Stat(ctx, snapshotID); err == nil { + continue + } + + dh := dhs[digest.Digest(r.getBlob())] + if dh == nil { + // We cannot prepare remote snapshots without descHandler. + return nil, nil + } + + defaultLabels := snapshots.FilterInheritedLabels(dh.SnapshotLabels) + if defaultLabels == nil { + defaultLabels = make(map[string]string) + } + defaultLabels["containerd.io/snapshot.ref"] = snapshotID + + // Prepare remote snapshots + var ( + key = fmt.Sprintf("tmp-%s %s", identity.NewID(), r.getChainID()) + opts = []snapshots.Opt{ + snapshots.WithLabels(defaultLabels), + } + ) + parentID := "" + if r.layerParent != nil { + parentID = r.layerParent.getSnapshotID() + } + if err := r.cm.Snapshotter.Prepare(ctx, key, parentID, opts...); err != nil { + if errdefs.IsAlreadyExists(err) { + // Check if the targeting snapshot ID has been prepared as + // a remote snapshot in the snapshotter. + _, err := r.cm.Snapshotter.Stat(ctx, snapshotID) + if err == nil { // usable as remote snapshot without unlazying. + // Try the next layer as well. + continue + } + } + } + + // This layer and all upper layers cannot be prepared without unlazying. + break + } + + return nil, nil + }) + return err +} + func makeTmpLabelsStargzMode(labels map[string]string, s session.Group) (fields []string, res map[string]string) { res = make(map[string]string) // Append unique ID to labels for avoiding collision of labels among calls @@ -1284,7 +1343,12 @@ func (sr *immutableRef) unlazyLayer(ctx context.Context, dhs DescHandlers, pg pr key := fmt.Sprintf("extract-%s %s", identity.NewID(), sr.getChainID()) - err = sr.cm.Snapshotter.Prepare(ctx, key, parentID) + if sr.cm.Snapshotter.Name() == "overlaybd" { + err = sr.cm.Snapshotter.Prepare(ctx, key, parentID, + snapshots.WithLabels(map[string]string{"containerd.io/snapshot.ref": string(desc.Digest)})) + } else { + err = sr.cm.Snapshotter.Prepare(ctx, key, parentID) + } if err != nil { return err } diff --git a/docs/overlaybd.md b/docs/overlaybd.md new file mode 100644 index 000000000000..f39a69cb59ec --- /dev/null +++ b/docs/overlaybd.md @@ -0,0 +1,40 @@ +# Overlaybd + +[Overlaybd](https://github.com/containerd/overlaybd) is a novel layering block-level image format, which is design for container, secure container and applicable to virtual machine. And it is an open-source implementation of paper [DADI: Block-Level Image Service for Agile and Elastic Application Deployment. USENIX ATC'20"](https://www.usenix.org/conference/atc20/presentation/li-huiba). + +## Build Overlaybd Images + +Before building overlaybd images, ensure that `overlaybd-tcmu` and `overlaybd-snapshotter` are active by referring to the [QUICKSTART](https://github.com/containerd/accelerated-container-image/blob/main/docs/QUICKSTART.md#install) guide. + +To use buildkit to build overlaybd images, you should specify `--oci-worker-snapshotter=overlaybd` and `--oci-worker-proxy-snapshotter-path=/run/overlaybd-snapshotter/overlaybd.sock` when start buildkitd: + +```bash +buildkitd --oci-worker-snapshotter=overlaybd --oci-worker-proxy-snapshotter-path=/run/overlaybd-snapshotter/overlaybd.sock +``` + +After that, you can build a new overlaybd image from an existing overlaybd image. It is essential to include `--oci-mediatypes=true` and `--compression=uncompressed` while running buildctl: + +```bash +buildctl build ... \ +--output type=image,name=,push=true,oci-mediatypes=true,compression=uncompressed +``` + +## Performance + +In our test case Dockerfile, we used a 5GB OCI image (and corresponding overlaybd format), wrote some new layers of identical size, and recorded the time cost of image pull (as **pull** in the table below), building all lines in Dockerfile (as **build**), and exporting to image and pushing (as **push**). + +OCI: + +| **size per layer** | **layers** | **pull** | **build** | **push** | **total** | +| -------- | ---- | ---- | ----- | ---- | ---- | +| 4GB | 1 | 105.7| 23.5 | 219.4| 348.6| +| 1GB | 4 | 88.5 | 34.0 | 123.8| 246.3| +| 256MB | 10 | 92.1 | 20.7 | 63.6 | 176.4| + +Overlaybd: + +| **size per layer** | **layers** | **pull** | **build** | **push** | **total** | +| -------- | ---- | ---- | ----- | ---- | ---- | +| 4GB | 1 | 0.9 | 21.5 | 166.2| 188.6| +| 1GB | 4 | 0.9 | 24.9 | 72.9 | 98.7 | +| 256MB | 10 | 0.7 | 18.4 | 48.9 | 68.0 | \ No newline at end of file diff --git a/go.mod b/go.mod index e1effadf0104..850bb404dcc4 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.56 github.com/aws/aws-sdk-go-v2/service/s3 v1.30.6 github.com/aws/smithy-go v1.13.5 + github.com/containerd/accelerated-container-image v0.6.5 github.com/containerd/console v1.0.3 github.com/containerd/containerd v1.7.1 github.com/containerd/continuity v0.4.1 diff --git a/go.sum b/go.sum index 041a7d2ca9b2..62c858ca8aa6 100644 --- a/go.sum +++ b/go.sum @@ -285,6 +285,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20160425231609-f8ad88b59a58/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codahale/rfc6979 v0.0.0-20141003034818-6a90f24967eb h1:EDmT6Q9Zs+SbUoc7Ik9EfrFqcylYqgPZ9ANSbTAntnE= +github.com/containerd/accelerated-container-image v0.6.5 h1:XArcWyUbQ4pD7f9rh3qDQCdyu85ezdSvTZHvNb74VsQ= +github.com/containerd/accelerated-container-image v0.6.5/go.mod h1:RZB4r386ZnUEuYdwJplVoI4avEE+oxWB75uOB3quctA= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/aufs v0.0.0-20201003224125-76a6863f2989/go.mod h1:AkGGQs9NM2vtYHaUen+NljV0/baGCAPELGm2q9ZXpWU= github.com/containerd/aufs v0.0.0-20210316121734-20793ff83c97/go.mod h1:kL5kd6KM5TzQjR79jljyi4olc1Vrx6XBlcyj3gNv2PU= diff --git a/source/containerimage/pull.go b/source/containerimage/pull.go index 509d2a994660..d3d76923488c 100644 --- a/source/containerimage/pull.go +++ b/source/containerimage/pull.go @@ -307,6 +307,7 @@ func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (cach for k, v := range estargz.SnapshotLabels(p.manifest.Ref, p.manifest.Descriptors, i) { labels[k] = v } + labels["containerd.io/snapshot/image-ref"] = p.manifest.Ref p.descHandlers[desc.Digest] = &cache.DescHandler{ Provider: p.manifest.Provider, Progress: progressController, diff --git a/vendor/github.com/containerd/accelerated-container-image/LICENSE b/vendor/github.com/containerd/accelerated-container-image/LICENSE new file mode 100644 index 000000000000..f49a4e16e68b --- /dev/null +++ b/vendor/github.com/containerd/accelerated-container-image/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/vendor/github.com/containerd/accelerated-container-image/pkg/label/label.go b/vendor/github.com/containerd/accelerated-container-image/pkg/label/label.go new file mode 100644 index 000000000000..038dabc9652a --- /dev/null +++ b/vendor/github.com/containerd/accelerated-container-image/pkg/label/label.go @@ -0,0 +1,117 @@ +/* + Copyright The Accelerated Container Image Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package label + +// support on-demand loading by the labels +const ( + // TargetSnapshotRef is the interface to know that Prepare + // action is to pull image, not for container Writable snapshot. + // + // NOTE: Only available in >= containerd 1.4.0 and containerd.Pull + // with Unpack option. + // + // FIXME(fuweid): With containerd design, we don't know that what purpose + // snapshotter.Prepare does for. For unpacked image, prepare is for + // container's rootfs. For pulling image, the prepare is for committed. + // With label "containerd.io/snapshot.ref" in preparing, snapshotter + // author will know it is for pulling image. It will be useful. + // + // The label is only propagated during pulling image. So, is it possible + // to propagate by image.Unpack()? + TargetSnapshotRef = "containerd.io/snapshot.ref" + + // TargetImageRef is the label to mark where the snapshot comes from. + // + // TODO(fuweid): Is it possible to use it in upstream? + TargetImageRef = "containerd.io/snapshot/image-ref" + + // OverlayBDBlobDigest is the annotation key in the manifest to + // describe the digest of blob in OverlayBD format. + // + // NOTE: The annotation is part of image layer blob's descriptor. + OverlayBDBlobDigest = "containerd.io/snapshot/overlaybd/blob-digest" + + // OverlayBDBlobSize is the annotation key in the manifest to + // describe the size of blob in OverlayBD format. + // + // NOTE: The annotation is part of image layer blob's descriptor. + OverlayBDBlobSize = "containerd.io/snapshot/overlaybd/blob-size" + + // OverlayBDBlobFsType is the annotation key in the manifest to + // describe the filesystem type to be mounted as of blob in OverlayBD format. + // + // NOTE: The annotation is part of image layer blob's descriptor. + OverlayBDBlobFsType = "containerd.io/snapshot/overlaybd/blob-fs-type" + + // AccelerationLayer is the annotation key in the manifest to indicate + // whether a top layer is acceleration layer or not. + AccelerationLayer = "containerd.io/snapshot/overlaybd/acceleration-layer" + + // RecordTrace tells snapshotter to record trace + RecordTrace = "containerd.io/snapshot/overlaybd/record-trace" + + // RecordTracePath is the file path to record trace + RecordTracePath = "containerd.io/snapshot/overlaybd/record-trace-path" + + // ZFileConfig is the config of ZFile + ZFileConfig = "containerd.io/snapshot/overlaybd/zfile-config" + + // CRIImageRef is the image-ref from cri + CRIImageRef = "containerd.io/snapshot/cri.image-ref" + + // FastOCIDigest is the index annotation key for image layer digest + FastOCIDigest = "containerd.io/snapshot/overlaybd/fastoci/target-digest" + + // FastOCIMediaType is the index annotation key for image layer media type + FastOCIMediaType = "containerd.io/snapshot/overlaybd/fastoci/target-media-type" + + // DownloadRemoteBlob is a label for download remote blob + DownloadRemoteBlob = "containerd.io/snapshot/overlaybd/download-remote-blob" + + RemoteLabel = "containerd.io/snapshot/remote" + RemoteLabelVal = "remote snapshot" +) + +// used in filterAnnotationsForSave (https://github.com/moby/buildkit/blob/v0.11/cache/refs.go#L882) +var OverlayBDAnnotations = []string{ + LocalOverlayBDPath, + OverlayBDBlobDigest, + OverlayBDBlobSize, + OverlayBDBlobFsType, +} + +// interface +const ( + // SupportReadWriteMode is used to support writable block device + // for active snapshotter. + // + // By default, multiple active snapshotters can share one block device + // from parent snapshotter(committed). Like image builder and + // sandboxed-like container runtime(KataContainer, Firecracker), those + // cases want to use the block device alone or as writable. + // There are two ways to provide writable devices: + // - 'dir' mark the snapshotter + // as wriable block device and mount it on rootfs. + // - 'dev' mark the snapshotter + // as wriable block device without mount. + SupportReadWriteMode = "containerd.io/snapshot/overlaybd.writable" + + // LocalOverlayBDPath is used to export the commit file path. + // + // NOTE: Only used in image build. + LocalOverlayBDPath = "containerd.io/snapshot/overlaybd.localcommitpath" +) diff --git a/vendor/github.com/containerd/accelerated-container-image/pkg/utils/cmd.go b/vendor/github.com/containerd/accelerated-container-image/pkg/utils/cmd.go new file mode 100644 index 000000000000..8dbf6dd5cb0c --- /dev/null +++ b/vendor/github.com/containerd/accelerated-container-image/pkg/utils/cmd.go @@ -0,0 +1,88 @@ +/* + Copyright The Accelerated Container Image Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package utils + +import ( + "context" + "os" + "os/exec" + "path" + + "github.com/pkg/errors" +) + +const ( + obdBinCreate = "/opt/overlaybd/bin/overlaybd-create" + obdBinCommit = "/opt/overlaybd/bin/overlaybd-commit" + + dataFile = "writable_data" + idxFile = "writable_index" + sealedFile = "overlaybd.sealed" + commitTempFile = "overlaybd.commit.temp" + commitFile = "overlaybd.commit" +) + +func Create(ctx context.Context, dir string, opts ...string) error { + dataPath := path.Join(dir, dataFile) + indexPath := path.Join(dir, idxFile) + os.RemoveAll(dataPath) + os.RemoveAll(indexPath) + args := append([]string{dataPath, indexPath}, opts...) + out, err := exec.CommandContext(ctx, obdBinCreate, args...).CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to overlaybd-create: %s", out) + } + return nil +} + +func Seal(ctx context.Context, dir, toDir string, opts ...string) error { + args := append([]string{ + "--seal", + path.Join(dir, dataFile), + path.Join(dir, idxFile), + }, opts...) + out, err := exec.CommandContext(ctx, obdBinCommit, args...).CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to seal writable overlaybd: %s", out) + } + return os.Rename(path.Join(dir, dataFile), path.Join(toDir, sealedFile)) +} + +func Commit(ctx context.Context, dir, toDir string, sealed bool, opts ...string) error { + var args []string + if sealed { + args = append([]string{ + "--commit_sealed", + path.Join(dir, sealedFile), + path.Join(toDir, commitTempFile), + }, opts...) + } else { + args = append([]string{ + path.Join(dir, dataFile), + path.Join(dir, idxFile), + path.Join(toDir, commitFile), + }, opts...) + } + out, err := exec.CommandContext(ctx, obdBinCommit, args...).CombinedOutput() + if err != nil { + return errors.Wrapf(err, "failed to overlaybd-commit: %s", out) + } + if sealed { + return os.Rename(path.Join(toDir, commitTempFile), path.Join(toDir, commitFile)) + } + return nil +} diff --git a/vendor/modules.txt b/vendor/modules.txt index dcf7a56e5ca6..b987245b16a5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -234,6 +234,10 @@ github.com/cenkalti/backoff/v4 # github.com/cespare/xxhash/v2 v2.2.0 ## explicit; go 1.11 github.com/cespare/xxhash/v2 +# github.com/containerd/accelerated-container-image v0.6.5 +## explicit; go 1.19 +github.com/containerd/accelerated-container-image/pkg/label +github.com/containerd/accelerated-container-image/pkg/utils # github.com/containerd/cgroups v1.1.0 ## explicit; go 1.17 github.com/containerd/cgroups/stats/v1