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

Determine upgrade path for dynamic metadata #4100

Closed
curiouserrandy opened this issue Aug 9, 2018 · 22 comments
Closed

Determine upgrade path for dynamic metadata #4100

curiouserrandy opened this issue Aug 9, 2018 · 22 comments
Labels
design proposal Needs design doc/proposal before implementation

Comments

@curiouserrandy
Copy link
Contributor

Title: Evaluate upgrade path from RequestInfo::dynamicMetadata to new DynamicMetadata class

Description:

As part of working on implementing a new DynamicMetadata class for arbitrarily typed communication between filters, I've been evaluating current uses of RequestInfo::dynamicMetadata(). After some discussion with @htuch, I wanted to poll the experts on the current uses of that method about whether they think an upgrade to the new method is feasible. Would each of you be willing to take a look at the design and comment as to whether you think there's a reasonable deprecation path from the old method to the new one, whether the two methods should be kept on in parallel, or if you have another preference? (The old method is an arbitrary proto indexed by RDNS filter name, the new method is an arbitrary C++ object indexed by RDNS organization+data name.)

Lua filter: @dio
RBAC filter: @yangminzhu
HeaderToMetadata: @rgs1
FYI: @mattklein123 @alyssawilk

Relevant Links
Design doc: https://docs.google.com/document/d/1GNawM59Pp09WZ34zqJYiO_qmERjuGbOUeAqF1GG6v9Q/edit#
(The key section for this issue is "Accessing data produced in one filter from another")

Implementation PR: #3918

@htuch
Copy link
Member

htuch commented Aug 9, 2018

@qiwzhang as well, plus @lizan and other Istio security folks. Can we rollover RBAC to Randy's new metadata approach? We don't want to maintain two metadata schemes and would like to turn down the old one unless it needs to be supported, e.g. due to semantic expresiveness missing in the new scheme.

@rgs1
Copy link
Member

rgs1 commented Aug 9, 2018

We use the HeaderToMetadata filter to dynamically match requests with endpoints in the subset LB, so migrating both in one go is probably easier (or, the subset LB would have to go first).

Here's how the subset LB matches a request to an endpoint based on metadata: https://github.com/envoyproxy/envoy/blob/master/source/common/upstream/subset_lb.cc#L286

Per the design doc, "... the producer and consumer must agree on the type of the data being accessed". I am guessing this shouldn't be a problem when matching an endpoint's metadata (deserialized from config/eds) and incoming request's metadata? That is, does the new Metadata class provides a way for comparing objects and introspecting types without a previous agreement (haven't looked at the implementation, so not sure)?

@lizan
Copy link
Member

lizan commented Aug 9, 2018

RBAC filters is heavily using the MetadataMatcher. It takes advantage of the metadata being a protobuf Struct so arbitrary data can be queried. From the design doc this seems hard since the accessor is not structured.

@yangminzhu
Copy link
Contributor

As @lizan mentioned, the MetadataMatcher should be covered in the doc.

(Also recently we started to use RequestInfo.Metadata to pass data between different filters in Istios' proxy implementation. cc @diemtvu)

@qiwzhang
Copy link
Contributor

Also dynamicData is used in AccessLog::Instance log() phase. Not sure if the design covers that phase. Can that phase access any dynamicData?

@htuch
Copy link
Member

htuch commented Aug 10, 2018

Yeah, I think I'm convinced that we're going to need to keep the dynamic metadata for config purposes. @curiouserrandy do you think we could come up with a name for the new dynamic metadata that doesn't confuse and conveys its intended use? Something like "inter-filter state", "request filter state", etc.

@curiouserrandy
Copy link
Contributor Author

Agreed; the impedance mismatch is just too large :-{.

In terms of naming, I'm inclined to stay away from "metadata" since that has a well defined meaning inside of envoy. FilterState? GeneratedFilterState? I'd be good with either, but I'll go with the first in the name of terseness if no one else has an opinion.

@htuch
Copy link
Member

htuch commented Aug 10, 2018

+1 FilterState.

@qiwzhang
Copy link
Contributor

how about SafelySharedFilterState to indicate the data is shared across filters, it is safe, non-intended filters could not access them.

@curiouserrandy
Copy link
Contributor Author

I have a preference is against "SafelyShared" because a) I have more of a single producer/multiple consumer model for the state--any particular item isn't shared in that only one filter can source it, though multiple others can read it, and b) I'm not sure when the implementation of the dependency management portion of the design will be done (which I take as generating the "Safely" portion of your suggestion).

Having said that, my feelings on naming are weak; if there's a consensus around SafelySharedFilterState I'll happily accept that.

@lizan
Copy link
Member

lizan commented Aug 10, 2018

+1 FilterState.

Btw I think this proposal let the state holds arbitrary C++ object in it, so perhaps we can wrap the metadata proto and use the new mechanism. @htuch thoughts?

@htuch
Copy link
Member

htuch commented Aug 10, 2018

@lizan yeah, I had similar thoughts on this, @curiouserrandy have chatted IRL. There's a valid view that these are essentially orthogonal, and if you want to maintain the property that you set any given slot in only one filter, then it's probably too coarse grained to place the metadata proto in there, since multiple filters might want to manipulate it.

@mattklein123 mattklein123 added the design proposal Needs design doc/proposal before implementation label Aug 10, 2018
@mattklein123
Copy link
Member

FWIW, I would vote for something along the lines of PerRequestState to indicate that this is state shared across the request and between filters. Similarly for network filters, perhaps PerConnectionState or similar. I don't feel very strongly about it though. I agree that wrapping the generic metadata in a C++ object seems like a fine way of merging both mechanisms.

@curiouserrandy
Copy link
Contributor Author

+1 for Per{Request,Connection}State; that's something that hasn't historically been captured in the name.

I'll point out that how the mechanisms are implemented isn't visible at the API level, and I'd argue isn't very important for that reason. But (as @htuch says) I do think that the "single source" aspect of PerRequestState gets in the way of layering dynamicMetadata() on top of it--it's possible that current usage patterns wouldn't violate that requirement, but it's hard to tell since the lua filter exposes arbitrary modifications of the dynamic metadata to programs written in configurations, so we need to know the usage across the universe of configurations, not just what's in the source repository.

@htuch
Copy link
Member

htuch commented Aug 12, 2018

Also +1` on Per{Request,Connection}State.

@cmluciano
Copy link
Member

Following up on the PR that @lizan mentioned above:

We agree that something like ConnectionState would be useful for network filters. My next question is what do we use to propagate the required metadata between filters on different Envoy hosts? For HTTP filters we convert whatever needs passed to headers, but I'm uncertain what method we would use for a connection oriented protocol.

cc @ggreenway @alyssawilk

@zuercher
Copy link
Member

I added something similar to the TCP connection pool for upstream connections -- users of the conn pool can attach state to an upstream connection. I doubt that's of use here (where you wish to attach state to downstream connections), but if the new mechanism can be applied to either downstream or upstream connections, the TCP conn pool version could probably be replaced.

@hans-stripe
Copy link

This looks super helpful for us too! We'd like to build an extension that can convert the client cert subject DN into its component parts (which would be a vector of pairs of strings) and share it with some Lua that we run on every request (in addition to some static per-route metadata). Doing the conversion as a network filter makes the most sense, while the Lua itself is a request filter -- being able to pass this state around would be great.

@stale
Copy link

stale bot commented Oct 10, 2018

This issue has been automatically marked as stale because it has not had activity in the last 30 days. It will be closed in the next 7 days unless it is tagged "help wanted" or other activity occurs. Thank you for your contributions.

@stale stale bot added the stale stalebot believes this issue/PR has not been touched recently label Oct 10, 2018
@htuch
Copy link
Member

htuch commented Oct 10, 2018

@curiouserrandy is there something we should be doing with this issue? Looks like we had agreement earlier in the thread that we can't do the impedance match.

@stale stale bot removed the stale stalebot believes this issue/PR has not been touched recently label Oct 10, 2018
@curiouserrandy
Copy link
Contributor Author

Yup. From my perspective, this issue was resolved with our agreement that the impedance match was too large (and in picking the name :-}). I didn't really track the discussion after that around ConnectionState, so I didn't respond to the stale marker figuring the other folks commenting on the issue could revive it if needed.

@htuch
Copy link
Member

htuch commented Oct 10, 2018

Closing out as resolved, thanks @curiouserrandy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
design proposal Needs design doc/proposal before implementation
Projects
None yet
Development

No branches or pull requests

10 participants