opencontainers / image-spec

OCI Image Format
https://www.opencontainers.org/
Apache License 2.0
3.52k stars 652 forks source link

Using an image index to reference nested related artifacts #1217

Open arewm opened 6 days ago

arewm commented 6 days ago

We have encountered some use cases where we would like to associate multiple related artifacts but which would still benefit from having their own namespace location.

Since an image index only has a reference to the digest for the referenced image index/manifest, it is not possible to map to reference any nested artifacts. Any client that is interested in supporting this functionality would need to add some form of client-specific encoding (i.e. via annotations) on the image index.

While some might be interested in having an image index refer to arbitrary pullspecs, I think that it is better to scope the references only to nested relationships as it is likely easier for registries to implement authorization models for these relationships. Being able to have a common authorization for all referenced artifacts would result in a better user experience.

sudo-bmitch commented 6 days ago

Hi @arewm. I believe it's possible to have a nested index today with the current specs. What is the specific change you are looking for from the spec? Is it for a standard around querying annotations?

arewm commented 6 days ago

I might have made a poor choice of terms. I assume that it is possible to have an image index point to another image index within the same namespace. What isn't possible possible is to point to an image within a further scoped namespace.

What does work:

Produce an image in a repository ``` $ echo "unnested image" > unnested.txt $ oras push quay.io/arewm/oci-spec-1217:unnested ./unnested.txt ✓ Exists application/vnd.oci.empty.v1+json 2/2 B 100.00% 0s └─ sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a ✓ Uploaded unnested.txt 15/15 B 100.00% 2s └─ sha256:052ec3b6a7a72037458b61f231635552122aa059b58f096cc7e1b3fb0c69ea60 ✓ Uploaded application/vnd.oci.image.manifest.v1+json 591/591 B 100.00% 4s └─ sha256:fb84505a92c39564f1976b8753bec1c10443a5b89bb9e900973cbd377d59ec4c Pushed [registry] quay.io/arewm/oci-spec-1217:unnested ArtifactType: application/vnd.unknown.artifact.v1 Digest: sha256:fb84505a92c39564f1976b8753bec1c10443a5b89bb9e900973cbd377d59ec4c $ oras manifest fetch --descriptor quay.io/arewm/oci-spec-1217:unnested {"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:fb84505a92c39564f1976b8753bec1c10443a5b89bb9e900973cbd377d59ec4c","size":591}% ``` Create an image index referring to that ``` $ echo '{"schemaVersion":2,"mediaType": "application/vnd.oci.image.index.v1+json","manifests": [{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:fb84505a92c39564f1976b8753bec1c10443a5b89bb9e900973cbd377d59ec4c","size":591}]}' > unnested-manifest.json $ oras manifest push quay.io/arewm/oci-spec-1217:index unnested-manifest.json Pushed [registry] quay.io/arewm/oci-spec-1217:index Digest: sha256:2763178e5ddad8f5ff33ce5ae7d6dcc0ad6ccc46fedeff20f96c07a2c732d065$ oras manifest fetch --pretty quay.io/arewm/oci-spec-1217:index { "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", "manifests": [ { "mediaType": "application/vnd.oci.image.manifest.v1+json", "digest": "sha256:fb84505a92c39564f1976b8753bec1c10443a5b89bb9e900973cbd377d59ec4c", "size": 591 } ] } ``` Is wrapping this in an image index what is supposed to be supported by the spec? ``` $ echo '{"schemaVersion":2,"mediaType": "application/vnd.oci.image.index.v1+json","manifests": [{"mediaType":"application/vnd.oci.image.index.v1+json","digest":"sha256:2763178e5ddad8f5ff33ce5ae7d6dcc0ad6ccc46fedeff20f96c07a2c732d065","size":243}]}' > nested-index.json $ oras manifest push quay.io/arewm/oci-spec-1217:nested-index nested-index.json ```

What doesn't work but is proposed:

Produce an image in a repository ``` $ oras push quay.io/arewm/oci-spec-1217/nested:manifest ./nested.txt ✓ Exists nested.txt 13/13 B 100.00% 0s └─ sha256:6106ccab4c28daa60df08ab663b42c27a3f884ea58da65ac8d6d848055f25588 ✓ Exists application/vnd.oci.empty.v1+json 2/2 B 100.00% 0s └─ sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a ✓ Uploaded application/vnd.oci.image.manifest.v1+json 589/589 B 100.00% 3s └─ sha256:99d5be857b2bd8906bb3fcd742119b28bbb637859d6ac2fb382c71058dceb01d Pushed [registry] quay.io/arewm/oci-spec-1217/nested:manifest ArtifactType: application/vnd.unknown.artifact.v1 Digest: sha256:99d5be857b2bd8906bb3fcd742119b28bbb637859d6ac2fb382c71058dceb01d $ oras manifest fetch --descriptor quay.io/arewm/oci-spec-1217/nested:manifest {"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:99d5be857b2bd8906bb3fcd742119b28bbb637859d6ac2fb382c71058dceb01d","size":589}% ``` Then trying to point to that from an image index in a "parent" namespace ``` $ echo '{"schemaVersion":2,"mediaType": "application/vnd.oci.image.index.v1+json","manifests": [{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:99d5be857b2bd8906bb3fcd742119b28bbb637859d6ac2fb382c71058dceb01d","size":589}]}' > nested-manifest.json $ oras manifest push quay.io/arewm/oci-spec-1217:index nested-manifest.json Error response from registry: failed to tag index: manifest invalid: manifest invalid: map[message:Could not find child manifest with digest `sha256:99d5be857b2bd8906bb3fcd742119b28bbb637859d6ac2fb382c71058dceb01d`] ```

Proposed change to the spec to add support for nested artifact namespaces

In the details above that don't work, quay returns an error because the registry couldn't find a manifest with the provided digest. If we add an additional optional property for the manifests pointing to a child namespace then a registry could look for the digest there instead.

arewm commented 6 days ago

This issue also come from me, as a registry user, expecting that namespaces within a registry should roughly correspond to logically similar artifacts. When it comes to binary containers, for example (i.e. ko above), my expectation is that each application binary is in its own namespace instead of being in the same namespace with only a unique tag.

Artifacts stored in a registry have relationships to each other. For me, the relationships can be described with:

sudo-bmitch commented 5 days ago

There's no concept of a cross-repository descriptor in OCI, every descriptor references content in the same repository. Trying to change that is likely to face a lot of resistance due to all the issues it creates. A few issues I can think of:

Right now, any cross repository logic is registry specific and requires client configuration. E.g. it is possible to push an artifact with a subject digest that does not exist in the current repository. However, registries are permitted to implement their own garbage collection process that would include that content, and clients would need to know how to find the subject digest from another repository and be configured with the repository name to perform the referrers API.

Similarly, it's possible to push an Index that has descriptors that do not exist in the local repository (this is specifically desired for sparse copies that only include specific platforms used in an environment). However, most registries reject that as part of their validation, and many clients would break if they attempted to consume content and follow the path to a missing digest. To support your own use case, you would need a registry that doesn't validate the Index, and would need client tooling that knows how to find the content in different repositories.

Overall, the easy answer is to put all of the content in the same repository, but realize that some registries may reject a nested Index even when the referenced content exists (I recall someone validating the media types listed in an OCI Index were limited to only an OCI Image). Also, clients need to be configured to know how to walk a nested Index to find their content.