-
Notifications
You must be signed in to change notification settings - Fork 228
Add registry proxying section #66
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
base: main
Are you sure you want to change the base?
Conversation
42589cd to
e5df360
Compare
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.
See comments & questions.
|
Why do clients need to know anything about pull-through caching if its implemented server-side? |
e5df360 to
29fdf25
Compare
The clients should know how the registry host was resolved from a given image reference. The clients don't care how the server is implemented, but they SHOULD provide information to the server which indicates what the reference being asked for is. Just as when an HTTP client connects with a PROXY server it must communicate what the upstream server is, the same is true here. Today the protocol doesn't define anyway to communicate what the upstream is and proxies end up be hardcoded to a single upstream. In a few cases you can see proxies use custom domains per upstream and require users to change the name of their images in order to use them. |
Right... isn't that the point? If I encode that "myregistry/mynamespace/myrepo" goes to "upstream/foo/bar", that's a detail for the maintainer of If the goal is to allow the client to specify "upstream/foo/bar", then I'd that the target is not really a repository anymore, but simply a working proxy, and thus, a different protocol parameter might be useful, but registries should therefore have the option to not support said parameter. |
That is one use case that will still work. In the example you mentioned, when a repository is proxied in that fashion, the puller often does know of this detail as they must explicitly provide myregistry with the intent of getting some upstream content. The use case where myregistry is some sort of blessed version of upstream is reasonable, but not the intent of the namespace parameter here.
This is the use case here and proxy may be better terminology here, but that is really a detail of the registry. The registry may act as a proxy, proxy-cache, or active mirror, that is out of scope for definition here. This parameter just enables all of those features to work across multiple namespaces. For example if you want public images from both |
Or configure two repositories, one for each? (especially since combining them could lead to merge conflicts). I'm concerned we're adding quite a bit of complexity to address a use case that has simpler solutions when configured on the registry side. |
Can you elaborate here? Configuring a repository for each mirror is non-trivial. Configuring a domain for each upstream and routing to the upstream based on the domain is not easier, that would still requires the same routing on the server side that an implementation of this would require. The client side implementation to support per-registry configuration is not simple and inherently requires catch -all conditions when trying to enforce proxying through a gateway. I did do a client side implementation of this to demonstrate the feature and allow server side implementations a client to test against. On the client side, it is not complex at all since clients should already know how to handle 404s when multiple registry endpoints are configured. On the server side, the complexity to support this isn't much more than existing proxy-cache support. |
Its non-trivial, but its not that difficult either :) My concern remains around complexity: the document as outlined, for example, says that the If we feel that pass-through proxying of other registries is, in and of itself, a feature of the protocol (rather than something configured on the registry side), then I suspect we need to give significantly more thought to the end-to-end user experience. For example, I could imagine some paths supporting proxying and others not. |
The clients have the most context and really does not need to be defined here, only that a client SHOULD make that distinction to avoid sending unnecessary redundant information. The clients themselves have both the configuration and endpoint resolution logic, so it has multiple options for determining this. In the implementation I sent I just simply did this by checking whether the endpoint was configured without push support, as this could indicate the registry being communicated with may not be the upstream source. However, I will probably add a check there for
No, the registry can simply ignore it. This is like asking a registry today which was configured to mirror docker.io to return an error if the client actually meant quay.io, the registry just isn't expected to have the same amount of context as a client in regards to the intent of the entire pull process. If the registry chooses to be handle the
They aren't expected to check for it, but rather be explicitly configured for it. A client will know if it is configured to always use a specific mirror or a mirror for multiple namespaces. I think what you are suggesting here though is the idea of registry discovery. That is a much larger topic that I would still love to see happen, in that feature a client could start with zero knowledge (except of course the domain quay.io, docker.io, etc) and discover registry capabilities and endpoints. |
|
discussion ensues on the call today. |
|
pinging @thomasmckay and @kurtismullins who are implementing mirroring on Quay -- they probably have feedback and want to track this thread |
|
is `ns` already used, so best to continue with that mnemonic? or could
it be something to not collide with the outdated concept that images
would on be named "transport/namespace/name:tag"?
|
|
@vbatts I use |
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.
LGTM
I think this is a great addition. It might be a good idea to add a few combinatoric examples of how ns and the the repo name are combined to calculate the upstream and local mirroring location.
|
@dmcgowan one thing i'm unclear on here is: can i have a single registry mirror that will be usable for more than one remote registry (i.e. remote of |
|
Notes from today's call:
Please lets find a way to classify this language (whether client or server side). So we can close out or merge this |
|
Reiterating our convo from the meeting: I actually see a lot of value in adding this query parameter, but removing any connotation that it is the blessed solution for repository mirroring. I think that by including this value, a proxy could implement lots of different behavior for the client that need not be directly related to repository mirroring. |
|
I note that harbor uses the term "replication" rather than proxy-cache or mirroring, which I quite like https://goharbor.io/docs/1.10/administration/configuring-replication/ |
658a97c to
1e3a9a4
Compare
|
Yeah I think it's safe to say that ns has become a de facto standard despite this PR stalling out. |
669cad7 to
68508bd
Compare
|
If the registry ignores a |
This is not a problem that needs to be solved here. Tag mutability, and figuring out what a tag points at when pulling from different registries or mirrors, is a known issue. If this matters to you, the correct solution is to use digests instead of tags. Beyond that, it doesn't matter where the content comes from. Allowing the client to make decisions based on where a registry reports that it is getting its content from violates separation of concerns. Pull a digest instead of a tag, and you're guaranteed to get what you want. Any hacks around "trusting" content because the server tells you it got it from a specific location, are insecure by design. |
I completely agree to using digests and signing for security, even when no proxies are involved. But we have a scenario where it's less the client trusting the proxy, and more the proxy telling the client "you asked for X and I'm choosing to give you Y instead". Or we could say proxies should not do that. Or we can keep the current language that says a proxy is within the spec to return different content than what the client requested without any notification to the client. Of the three options, another header to give the client some feedback seems the least intrusive and most flexible to implementations. |
|
I think making the client at all aware of where the request is being served from is problematic. Say I have local registry A acting as pull-through cache that runs alongside my cluster. That is backed by an organization-level registry B with only approved images, which are populated from Docker Hub via a manual sync process that requires approval. If I ask for an image from Docker Hub from either of these registries, with And why should the client care at all, if the only right way to ensure you get what you want is to use the content digest? The addressable content digest is the integrity check. Anything else is theater. |
|
@sudo-bmitch I understand your point but what is the logic you are considering there. From a client perspective, header is included and matches...good, header is not included...also good? Header is included and wrong...fail with what error. From the registry perspective, if it supported and has the content, return header and content, if it is supported and does not have the content, then 404. Either way, 404 is the way for a registry to return it understands the request and does not have the content. With proxies, it is more important for clients to understand the proxies they are communicating with and ensure that proxy is trusted. Either trusted proxy, signed content, or content by digest is the only way we should encourage these use cases. |
I think different tools may have their own logic, but the version I'm considering is:
This could be a user configurable behavior, not unlike how TLS verification is configurable in most tools. The value add to me is that there are registries that merge content from multiple upstream sources into a single global namespace. If that registry is used as a proxy, a header would make it possible to detect that content is being returned from a potentially malicious squatter on a repository path that happens to be a different mirror than the expected upstream source. Either the registry wouldn't return a header and tooling should assume it only proxies a single registry, or it should return a header indicating that the content came from a different upstream than expected. Having many different types of proxies, from the pull through cache of a single registry, a manual mirror of approved content, a mash up from multiple upstream sources, and proxies that understand and use the new |
|
I can only speak for how Spegel implements resolving tags with the ns parameter. The mirror registry should include the registry as part of the tag resolve process to avoid any name squatting. If a mirror merges multiple upstream registries it should only resolve the tag if the full registry, repository and tag matches. That is at least how Spegel implements this. As for the trust aspect, I think the same rules apply as they do today. The responsibility is on the end user to use a registry that they trust. There is nothing stopping a bad acting registry from returning whatever digest it likes to the client. It does not really matter if it is a mirror or not. |
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.
Following up on the Thursday call discussion, I added a commit with the OCI-Namespace header. If that's blocking other maintainers from approving, I can split that into a separate PR.
Changes were addressed followed by a LGTM comment.
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.
couple nits
6386ae2 to
ba13430
Compare
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 I add back the change from commit 6386ae2, or was its removal intentional?
A registry that uses the
nsquery parameter to scope the request SHOULD return thensquery parameter value in theOCI-Namespaceheader.
|
@dmcgowan I updated the maintainer vote list.. note brandon's query ^^ |
ba13430 to
2f1b040
Compare
Define repository namespace query parameter for proxying. Signed-off-by: Derek McGowan <[email protected]>
Signed-off-by: Brandon Mitchell <[email protected]>
2f1b040 to
ca746bd
Compare
|
Updated, not intentionally removed, just never had it in my local branch when rebased |
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.
LGTM
Define repository namespace query parameter for proxying.
Closes #12
Giving time for registry operators to weigh in
Maintainer approval
(mike: I updated the maintainer list in this vote to reflect the current maintainer list)