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

doc/spec, registry: immutable manifest reference support #211

Merged

Conversation

stevvooe
Copy link
Collaborator

Manifests are now fetched by a field called "reference", which may be a tag or a digest. When using digests to reference a manifest, the data is immutable. The routes and specification have been updated to allow this. There are a few caveats to this approach:

  1. It may be problematic to rely on data format to differentiate between a tag and a digest. Currently, they are disjoint but there may modifications on either side that break this guarantee.
  2. The caching characteristics of returned content are very different for digest versus tag-based references. Digest urls can be cached forever while tag urls cannot.

Both of these are minimal caveats that we can live with in the future.

Most of the changes follow from modifications to ManifestService. Once updates were made across the repo to implement these changes, the http handlers were change accordingly. The new methods on ManifestService will be broken out into tagging service in a later PR.

Unfortunately, due to complexities around managing the manifest tag index in an eventually consistent manner, direct deletes of manifests have been disabled.

Closes #46. Implements the registry portion of moby/moby#10740.

@stevvooe stevvooe added this to the Registry/Beta milestone Feb 26, 2015
@stevvooe stevvooe self-assigned this Feb 26, 2015
@stevvooe
Copy link
Collaborator Author

cc @ncdc

@ncdc
Copy link

ncdc commented Feb 27, 2015

@stevvooe awesome, thanks! I'll take a look tonight/tomorrow.

@vbatts
Copy link

vbatts commented Mar 2, 2015

looking over this, it LGTM

Looks like there may be a few failures that need to be cleaned up though

registry/storage/manifeststore.go:20: cannot use manifestStore literal (type *manifestStore) as type distribution.ManifestService in assignment:
        *manifestStore does not implement distribution.ManifestService (wrong type for Delete method)
                have Delete(digest.Digest) error
                want Delete(string) error
registry/storage/registry.go:78: cannot use manifestStore literal (type *manifestStore) as type distribution.ManifestService in return argument:
        *manifestStore does not implement distribution.ManifestService (wrong type for Delete method)
                have Delete(digest.Digest) error
                want Delete(string) error

@stevvooe
Copy link
Collaborator Author

stevvooe commented Mar 2, 2015

@vbatts The build seems to be okay. Did you see this on your local version? Perhaps, you need to clear pkg in your GOPATH for the updated interfaces?

@ncdc
Copy link

ncdc commented Mar 2, 2015

I've been able to compile and run cmd/registry/main.go locally

@stevvooe stevvooe force-pushed the immutable-manifest-references branch from e0c410a to bba344c Compare March 3, 2015 01:27
func getTag(ctx context.Context) (tag string) {
return ctxu.GetStringValue(ctx, "vars.tag")
func getReference(ctx context.Context) (reference string) {
return ctxu.GetStringValue(ctx, "vars.reference")
Copy link
Collaborator

Choose a reason for hiding this comment

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

I still don't see this value getting set, if it is supposed to be set by mux it is not.

INFO[0386] response completed                            app.id=66e8ee98-cc08-46d8-a99f-7c1aeabf9e8d http.request.host=localhost:5001 http.request.id=1c182fa2-fa29-4fe1-8304-2a2cb41816a7 http.request.method=PUT http.request.remoteaddr=127.0.0.1:48976 http.request.uri=/v2/dmcgowan/hello/manifests/anything http.request.useragent=docker/1.5.0-dev go/go1.4.1 git-commit/ed64cc9 kernel/3.18.5-101.fc20.x86_64 os/linux arch/amd64 http.response.duration=8.457093ms http.response.written=0 vars.name=dmcgowan/hello version=v2.0.0-alpha.1+unknown

Copy link

Choose a reason for hiding this comment

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

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed. 👹

t.Fatalf("unexpected error fetching manifest: %v", err)
}

if fetchedByManifest.Tag != fetchedByManifest.Tag {
Copy link

Choose a reason for hiding this comment

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

I'm guessing you want to compare fetchedByManifest.Tag with sm.Tag?

Also, similar question on line 174 if fetched.Tag != fetched.Tag {

@ncdc
Copy link

ncdc commented Mar 4, 2015

@stevvooe can you describe the issue with delete by tag?

@ncdc
Copy link

ncdc commented Mar 4, 2015

@stevvooe is there supposed to be a supported route for delete by digest?

@stevvooe stevvooe mentioned this pull request Mar 5, 2015
4 tasks
@stevvooe
Copy link
Collaborator Author

stevvooe commented Mar 5, 2015

@ncdc At this time, there is no supported route for delete by tag. After looking into implementation, the behavior of deletes invite unexpected behavior. I attempted a few different approaches. The first deleted all manifests under a given tag. This poses conflicts with a detached tag model and could lead to inconsistent behavior. The deleted the latest version using a link-based stack. This didn't go very well either.

In the interim, we'll support the ability to delete blobs, from an admin user, from the repository but it is the responsibility of the caller to maintain consistency of the manifests. This will support most use cases that require deleting older data.

In response to this, I've filed #210. Several issues are discussed there. My conclusion was that even with reference counting, one cannot be sure that a blob is unreferenced on an eventually consistent system. Erring on the side of never deleting unintentionally has resulted in deferring support for rich deletes.

That said, we are working on an alternate solution that will help us to get deletion support. Either way, my intention was to not hold up this PR on deletions.

Manifests are now fetched by a field called "reference", which may be a tag or
a digest. When using digests to reference a manifest, the data is immutable.
The routes and specification have been updated to allow this.

There are a few caveats to this approach:

1. It may be problematic to rely on data format to differentiate between a tag
   and a digest. Currently, they are disjoint but there may modifications on
   either side that break this guarantee.
2. The caching characteristics of returned content are very different for
   digest versus tag-based references. Digest urls can be cached forever while tag
   urls cannot.

Both of these are minimal caveats that we can live with in the future.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
This changeset implements immutable manifest references via the HTTP API. Most
of the changes follow from modifications to ManifestService. Once updates were
made across the repo to implement these changes, the http handlers were change
accordingly. The new methods on ManifestService will be broken out into a
tagging service in a later PR.

Unfortunately, due to complexities around managing the manifest tag index in an
eventually consistent manner, direct deletes of manifests have been disabled.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
@stevvooe stevvooe force-pushed the immutable-manifest-references branch from b4dd565 to 40273b1 Compare March 5, 2015 05:41
@ncdc
Copy link

ncdc commented Mar 5, 2015

@stevvooe what about delete by digest? I couldn't get it to work, as it appears that images.go DeleteImageManifest always returns unsupported, without checking to see if you're trying to delete by digest.

@stevvooe
Copy link
Collaborator Author

stevvooe commented Mar 6, 2015

@ncdc The above explanation applies to this case, as well: if a manifest is deleted by digest, what happens to the tag index? Does the value of the tag pointer revert to a previous value or does it force a delete of all tags? These are simple problems on a transactionally consistent backend. However, with eventually consistent storage, the implementation is non-trivial. Once we have a stable release, we need to revisit the backend implementations.

The real solution lies in first decoupling tags from the manifests, then building a consistent strategy for managing the tags.

@ncdc
Copy link

ncdc commented Mar 6, 2015

Thanks for the explanation. Makes sense.

@ncdc
Copy link

ncdc commented Mar 6, 2015

LGTM!

@dmp42
Copy link
Contributor

dmp42 commented Mar 6, 2015

LGTM

stevvooe added a commit that referenced this pull request Mar 6, 2015
doc/spec, registry: immutable manifest reference support
@stevvooe stevvooe merged commit b4cc5e3 into distribution:master Mar 6, 2015
@stevvooe stevvooe deleted the immutable-manifest-references branch March 6, 2015 01:38
@stevvooe stevvooe modified the milestones: Registry/2.0.0-beta, Registry/2.0 Mar 31, 2015
thaJeztah pushed a commit to thaJeztah/distribution that referenced this pull request Apr 22, 2021
…references

doc/spec, registry: immutable manifest reference support
thaJeztah pushed a commit to thaJeztah/distribution that referenced this pull request Jan 19, 2022
…references

doc/spec, registry: immutable manifest reference support
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Immutable image manifest references
6 participants