Skip to content
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

libimage: add support for ForceCompressionFormat for image copier and manifest #1602

Conversation

flouthoc
Copy link
Collaborator

@flouthoc flouthoc commented Aug 8, 2023

  • Bump c/image to v5.26.1-0.20230807184415-3fb422379cfa
  • libimage/copier: wire ForceCompressionFormat for image copy
  • manifest: add support ForceCompressionFormat

ForceCompressionFormat allows end users to force selected compression format (set in DestinationCtx.CompressionFormat) which ensures that while copying blobs of other compression algorithms are not reused.

See: containers/image#2068 for more details.

Signed-off-by: Aditya R <arajan@redhat.com>
@flouthoc
Copy link
Collaborator Author

flouthoc commented Aug 8, 2023

@mtrmac @vrothberg @giuseppe @rhatdan PTAL

@flouthoc flouthoc force-pushed the implement-forcecompressionformat branch 2 times, most recently from d94715a to 170f138 Compare August 8, 2023 07:01
@@ -49,6 +49,10 @@ type CopyOptions struct {
CompressionFormat *compression.Algorithm
// CompressionLevel specifies what compression level is used
CompressionLevel *int
// ForceCompressionFormat ensures that the compression algorithm set in
// DestinationCtx.CompressionFormat is used exclusively, and blobs of other
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's clear what DestinationCtx.CompressionFormat is in libimage.

I think it's important to highlight why setting CompressionFormat may not suffice.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be CompressionFormat I have amended this.


pushOptions := &PushOptions{}
pushOptions.CompressionFormat = &compression.Gzip
pushOptions.ForceCompressionFormat = true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could we verify that layers are getting compressed correctly? Should we load/pull the archive and inspect?

Copy link
Collaborator Author

@flouthoc flouthoc Aug 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Easier and actual integration test would be against a registry, where we can pre-upload a gzip and while pushing again with ForceCompressionFormat we can check push logs that no reuse candidates are there, it can be easily verified by inspecting push logs. Its easier to add this test on Podman/Buildah side.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we push to a local "oci:" directory and inspect the tarball there?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let me check that, I'll amend test if that works.

Copy link
Collaborator Author

@flouthoc flouthoc Aug 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the problem which ForceCompressionFormat is solving persists with other transports which works locally, c/image force pushes blobs for oci: and dir: transports when same destination is used even ending up creating invalid OCI images. ( I have added a test and it passes even when ForceCompressionFormat = false , I see similar behavior when directly working with buildah )

I am only able to reproduce the problem which ForceCompressionFormat solves with registry as transport where candidates are actually re-evaluated if they can reused before actually Copying content. @mtrmac could you confirm this because afaics local transports and not attempting to re-use dest blobs as registry:// is doing.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dir: can’t be used to test reuse because every write to dir: deletes the previous contents.


Local transports are also trying to reuse blobs, but they don’t look for candidates in the blob info cache.

In effect, that means that reuse happens between compressed and uncompressed versions, only if the digest from the source matches an existing blob on the destination. In particular, copying an image from an uncompressed source (most commonly c/storage) to a destination uncompressed, and then copying the same image from the same uncompressed source with compression enabled triggers a reuse.

Demo:

# Create an uncompressed source
$ skopeo copy --override-os linux --dest-decompress docker://quay.io/libpod/alpine dir:uncompressed0 

# Normal behavior of copies to OCI: compress
$ skopeo copy --override-os linux dir:uncompressed0 oci:direct                                       
$ ls -la direct/blobs/sha256 
…  2765584 … d8761bb9b4751d85618813b8f32d545dfb8dabc79ec8c2a59429851e8e5ee6f5

# Copy uncompressed first
$ skopeo copy --override-os linux --dest-oci-accept-uncompressed-layers dir:uncompressed0 oci:reuse
$ ls -la reuse/blobs/sha256                                                                                              
…  5589504 … 5e0d8111135538b8a86ce5fc969849efce16c455fd016bb3dc53131bcedc4da5

# … And then a compressed copy triggers reuse:
$ skopeo copy --override-os linux dir:uncompressed0 oci:reuse                                        
…
Copying blob 5e0d81111355 skipped: already exists  
…
# With a compressed layer not added
$ ls -la reuse/blobs/sha256                                                        
… 5589504 … 5e0d8111135538b8a86ce5fc969849efce16c455fd016bb3dc53131bcedc4da5

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mtrmac Thanks :) this worked for me in the test.

Copy link
Collaborator

@mtrmac mtrmac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks plausible at a very quick glance, I didn’t read the test now.

(An alternative would be to add an ExclusiveCompressionFormat option, which would set the algorithm + the flag in one, but that’s not orthogonal, e.g. we would need to also support setting compression level. To an extent this seems to what we anticipate the CLI design to be … and I think --force-compression-format or something like that is reasonable, and IIRC there’s precedent for an option with some similar name in Docker.)

@flouthoc
Copy link
Collaborator Author

flouthoc commented Aug 8, 2023

--force-compression-format SGTM for cli end.

@flouthoc flouthoc force-pushed the implement-forcecompressionformat branch 2 times, most recently from 6cf031c to a045159 Compare August 9, 2023 08:13
@mtrmac
Copy link
Collaborator

mtrmac commented Aug 10, 2023

--force-compression-format SGTM for cli end.

Found the original reference: containers/buildah#4613 (comment) .

@mtrmac
Copy link
Collaborator

mtrmac commented Aug 10, 2023

… which is not using the --force-compression-format spelling, because it is not a top-level CLI option at all. Still, a sort of a precedent.

@flouthoc flouthoc force-pushed the implement-forcecompressionformat branch from a045159 to 58ce959 Compare August 11, 2023 08:46
Implement containers/image#2068 for
libimage/copier.

Signed-off-by: Aditya R <arajan@redhat.com>
Implement containers/image#2068 for
libimage/manifest.Push

Signed-off-by: Aditya R <arajan@redhat.com>
@flouthoc flouthoc force-pushed the implement-forcecompressionformat branch from 58ce959 to 248cc73 Compare August 11, 2023 08:58
@flouthoc
Copy link
Collaborator Author

@vrothberg @giuseppe @mtrmac PTAL

Copy link
Member

@giuseppe giuseppe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Member

@vrothberg vrothberg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/lgtm

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Aug 11, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: flouthoc, giuseppe, vrothberg

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-merge-robot openshift-merge-robot merged commit 524b4d5 into containers:main Aug 11, 2023
7 checks passed
Comment on lines +121 to +136
// Push newly pulled alpine to directory with uncompressed blobs
pushOptions := &PushOptions{}
pushOptions.SystemContext = &types.SystemContext{}
pushOptions.SystemContext.DirForceDecompress = true
pushOptions.Writer = os.Stdout
dirDest := t.TempDir()
_, err = runtime.Push(ctx, "docker.io/library/alpine:latest", "dir:"+dirDest, pushOptions)
require.NoError(t, err)

// Pull uncompressed alpine from `dir:dirDest` as source.
pullOptions = &PullOptions{}
pullOptions.Writer = os.Stdout
pullOptions.Architecture = "arm64"
pulledImages, err = runtime.Pull(ctx, "dir:"+dirDest, config.PullPolicyAlways, pullOptions)
require.NoError(t, err)
require.Len(t, pulledImages, 1)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I didn’t test this now but I don’t think the dir: step is necessary if the test is structured primarily around c/storage.

c/storage itself is a source of always-uncompressed data.

(This works well enough as is, no need to go back and spend time changing it.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants