-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for building overlaybd images #3867
base: master
Are you sure you want to change the base?
Conversation
@tonistiigi @AkihiroSuda @ktock |
Looks good but needs rebase |
cache/manager.go
Outdated
@@ -615,6 +616,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 { | |||
rwLabels := make(map[string]string) | |||
rwLabels["containerd.io/snapshot/overlaybd.writable"] = "dev" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What’s “dev”?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a type of upper layer in overlaybd config that can specify by label, maybe we should provide a const value in overlaybd code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the "containerd.io/snapshot/overlaybd.writable" has been set as "dev", Snapshotter will create a R/W block device directly as rootfs without overlayfs // local directory (upper) + RO overlaybd (lower)
Just like devmapper :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Could you add that explanation in the code comment lines?
cache/refs.go
Outdated
@@ -1232,7 +1291,8 @@ 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) | |||
opts := snapshots.WithLabels(map[string]string{"containerd.io/snapshot.ref": string(desc.Digest)}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should not be enabled by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, now this label is only for overlaybd.
cache/blobs.go
Outdated
if snStat.Labels[obdlabel.LocalOverlayBDPath] != "" { | ||
isOverlaybd = true | ||
} | ||
mediaType = ocispecs.MediaTypeImageLayer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is overwritten regardless if isOverlaybd
is true/false, that's correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, mediaType
should be overwritten only when isOverlaybd
is true. It is now fixed.
cache/blobs.go
Outdated
@@ -105,7 +121,7 @@ func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool | |||
lowerRef = sr.layerParent | |||
} | |||
var lower []mount.Mount | |||
if lowerRef != nil { | |||
if !isOverlaybd && lowerRef != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code is becoming quite complex with these conditions added. Quite some branches are excluded if !isOverlaybd
, and stripping away that code shows that there's actually some of the other branches that are "dead code" in that case.
Perhaps out of scope for this PR, but I wonder if we need to branch earlier if isOverlaybd
is true, instead of all these "micro-conditions".
I did a very quick / naive remove of all the !isOverlaybd
paths, to get a "rough" idea what parts were unused, which gave me;
diff --git a/cache/blobs.go b/cache/blobs.go
index a8af0a96f..b3abd863b 100644
--- a/cache/blobs.go
+++ b/cache/blobs.go
@@ -7,7 +7,6 @@ import (
"io"
"os"
"path"
- "strconv"
obdlabel "github.com/containerd/accelerated-container-image/pkg/label"
obdcmd "github.com/containerd/accelerated-container-image/pkg/utils"
@@ -113,97 +112,11 @@ func computeBlobChain(ctx context.Context, sr *immutableRef, createIfNeeded bool
}
mediaType = ocispecs.MediaTypeImageLayer
}
- var lowerRef *immutableRef
- switch sr.kind() {
- case Diff:
- lowerRef = sr.diffParents.lower
- case Layer:
- lowerRef = sr.layerParent
- }
var lower []mount.Mount
- if !isOverlaybd && lowerRef != nil {
- m, err := lowerRef.Mount(ctx, true, s)
- if err != nil {
- return nil, err
- }
- var release func() error
- lower, release, err = m.Mount()
- if err != nil {
- return nil, err
- }
- if release != nil {
- defer release()
- }
- }
-
- var upperRef *immutableRef
- switch sr.kind() {
- case Diff:
- upperRef = sr.diffParents.upper
- default:
- upperRef = sr
- }
var upper []mount.Mount
- if !isOverlaybd && upperRef != nil {
- m, err := upperRef.Mount(ctx, true, s)
- if err != nil {
- return nil, err
- }
- var release func() error
- upper, release, err = m.Mount()
- if err != nil {
- return nil, err
- }
- if release != nil {
- defer release()
- }
- }
-
var desc ocispecs.Descriptor
var err error
- // Determine differ and error/log handling according to the platform, envvar and the snapshotter.
- var enableOverlay, fallback, logWarnOnErr bool
- if forceOvlStr := os.Getenv("BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF"); forceOvlStr != "" && sr.kind() != Diff {
- enableOverlay, err = strconv.ParseBool(forceOvlStr)
- if err != nil {
- return nil, errors.Wrapf(err, "invalid boolean in BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF")
- }
- fallback = false // prohibit fallback on debug
- } else if !isTypeWindows(sr) {
- enableOverlay, fallback = true, true
- switch sr.cm.Snapshotter.Name() {
- case "overlayfs", "stargz":
- // overlayfs-based snapshotters should support overlay diff except when running an arbitrary diff
- // (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":
- // not supported with fuse-overlayfs snapshotter which doesn't provide overlayfs mounts.
- // TODO: add support for fuse-overlayfs
- enableOverlay = false
- }
- }
- if !isOverlaybd && enableOverlay {
- computed, ok, err := sr.tryComputeOverlayBlob(ctx, lower, upper, mediaType, sr.ID(), compressorFunc)
- if !ok || err != nil {
- if !fallback {
- if !ok {
- return nil, errors.Errorf("overlay mounts not detected (lower=%+v,upper=%+v)", lower, upper)
- }
- if err != nil {
- return nil, errors.Wrapf(err, "failed to compute overlay diff")
- }
- }
- if logWarnOnErr {
- bklog.G(ctx).Warnf("failed to compute blob by overlay differ (ok=%v): %v", ok, err)
- }
- }
- if ok {
- desc = computed
- }
- }
-
if isOverlaybd {
if err := commitOverlaybd(ctx, sr, &desc); err != nil {
return nil, err
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code has been modified, because desc
will be overwritten in commitOverlaybd
, so there is no effect if !isOverlaybd
is not added.
cache/blobs.go
Outdated
@@ -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" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we have a const somewhere for overlaybd
? (not sure what the best place is for it though)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's irrelevant since stargz
does the same. And it doesn't make the code harder to understand:)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, definitely not a "show-stopper", and if we do, we should consider doing it for all the snapshotters (which would be out of scope for this PR).
I agree with you ("in general") that a const is not always needed for these, and sometimes a const
may make ik even harder to understand the code (so .. "it depends").
The reason I was looking if we should add a const is that there's various code-paths in multiple packages, where the code-flow depends on the snapshotter used. Having a const
for these could help discovery of those flows (i.e., find all uses of the const
in the code). If these consts would also have a strong type, it could also act as an "enum" to help discovery of "accepted values". (See #3694 for something similar).
fa544ab
to
5cc5636
Compare
@AkihiroSuda @thaJeztah @ktock |
Compilation is failing for Windows
|
@AkihiroSuda We remove a package that only uses in Unix, now it can pass all checks. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! New version looks a lot better; I left some comments/questions and was drafting along some ideas, but not sure if they're correct / make sense. I'll open a PR against your fork for consideration.
cache/blobs.go
Outdated
@@ -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" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, definitely not a "show-stopper", and if we do, we should consider doing it for all the snapshotters (which would be out of scope for this PR).
I agree with you ("in general") that a const is not always needed for these, and sometimes a const
may make ik even harder to understand the code (so .. "it depends").
The reason I was looking if we should add a const is that there's various code-paths in multiple packages, where the code-flow depends on the snapshotter used. Having a const
for these could help discovery of those flows (i.e., find all uses of the const
in the code). If these consts would also have a strong type, it could also act as an "enum" to help discovery of "accepted values". (See #3694 for something similar).
cache/blobs.go
Outdated
} | ||
if snStat.Labels[obdlabel.LocalOverlayBDPath] != "" { | ||
isOverlaybd = true | ||
mediaType = ocispecs.MediaTypeImageLayer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not new, as it was already defined at the top, but looks like mediaType
is not used until line 188, so we could move this block closer to where it's used.
cache/blobs.go
Outdated
if snStat.Labels[obdlabel.LocalOverlayBDPath] != "" { | ||
isOverlaybd = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry if it's a silly question, but what happens if the label isn't set? Is that an expected (valid) situation, or should that be an error condition?
I'm also looking at this code, and possibly part of it could be moved at the end (where it's used).
cache/blobs.go
Outdated
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curious; is the enableOverlay
supported with this snapshotter? I see there's code above that allows it to be forced, and I wonder if that is a valid case (so if the if enableOverlay
code below should be executed also for overlaybd
if that env-var is set.
Lines 151 to 156 in 13cca5a
if forceOvlStr := os.Getenv("BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF"); forceOvlStr != "" && sr.kind() != Diff { | |
enableOverlay, err = strconv.ParseBool(forceOvlStr) | |
if err != nil { | |
return nil, errors.Wrapf(err, "invalid boolean in BUILDKIT_DEBUG_FORCE_OVERLAY_DIFF") | |
} | |
fallback = false // prohibit fallback on debug |
Because if it's not needed, we can combine the isOverlayBD
code from above, and the if isOverlaybd
code from below.
cache/blobs.go
Outdated
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit; probably should be isOverlayBD
cache/blobs.go
Outdated
@@ -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 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: should probably be commitOverlayBD
(capital BD)
opened HileQAQ#1 with things I was drafting / playing with (includes some of my suggestions) |
@thaJeztah I made some modifications as suggested, except your suggestions, I set |
@tonistiigi @ktock PTAL |
48906ad
to
ff0522f
Compare
+1 for this very useful feature! We depend on Overlaybd image format and being able to build directly instead of doing conversion would be a major enhancement. Do we know if we have plan to merge this soon? |
At least this needs rebasing |
I will solve this... This PR has been pending for a long time😂
|
@AkihiroSuda @BigVan I have rebased the code, PTAL |
The related feature has been supported in Alibaba for almost two years. |
@AkihiroSuda A lint error has been fixed, please help rerun the checks |
These two failed checks should be unrelated to the code in this PR. The logic related to overlaybd includes appropriate checks and will not affect the existing logic. Additionally, I also encounter these failures when using the upstream code on my GitHub Actions occasionally. Could you please help me retry or provide some assistance? @AkihiroSuda |
Signed-off-by: liulanzheng <[email protected]>
Overlaybd is a remote image format based on the block device, which can load data on demand. You can see the paper for more information.
In order to build overlaybd images using buildkit, some changes have been made that are separate from the original process. Please refer to the docs/overlaybd.md for guidance on building overlaybd images.
Signed-off-by: Haoqi Miao [email protected]