-
Notifications
You must be signed in to change notification settings - Fork 264
A40 - xDS Configuration Dump via Client Status Discovery Service in gRPC #223
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
Changes from 2 commits
9b49087
1270633
e263e6a
90b438e
d6564eb
5d9cd4a
dcdd1e3
d8b5cc2
b6f5539
cad45d5
aadbb4c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,250 @@ | ||
| xDS Configuration Dump via Client Status Discovery Service in gRPC | ||
| ---- | ||
| * Author(s): lidizheng | ||
| * Approver: markdroth | ||
| * Status: In-Review | ||
| * Implemented in: All languages | ||
| * Last updated: 2021-02-16 | ||
| * Discussion at: https://groups.google.com/g/grpc-io/c/zL45YyxtJ08 | ||
|
|
||
| ## Abstract | ||
|
|
||
| [Client Status Discovery | ||
| Service](https://github.com/envoyproxy/envoy/blob/main/api/envoy/service/status/v3/csds.proto) | ||
| (CSDS) is a service that exposes xDS config of a given client. It’s commonly | ||
| used to query control planes for the synced xDS config of a particular sidecar | ||
| proxy. However, it can also be used to query an xDS-compliant application for | ||
| its received xDS configuration. This doc proposes a solution to implement a CSDS | ||
| servicer in gRPC, so our users can debug their service mesh easily. | ||
|
sergiitk marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| ## Background | ||
|
|
||
| Envoy [started](https://github.com/envoyproxy/envoy/pull/9383) the CSDS | ||
| development process in Dec 2019. The CSDS API has been available since xDS v2, | ||
| and it’s under active development. But, Envoy proxies do not support or | ||
| understand this service, only the control plane does. Envoy already provides | ||
| config dump via its [admin | ||
| interface](https://www.envoyproxy.io/docs/envoy/latest/operations/admin) for | ||
| years. There is no visible plan for Envoy to support serving CSDS directly as a | ||
|
markdroth marked this conversation as resolved.
|
||
| proxy. | ||
|
sergiitk marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| ### Related Proposals: | ||
| * [A38 - Admin Interface API](https://github.com/grpc/proposal/pull/218) | ||
|
sergiitk marked this conversation as resolved.
|
||
|
|
||
| ## Proposal | ||
|
|
||
| ### CSDS in gRPC | ||
| The goal of adding a CSDS servicer to gRPC is to enable programmatic access to | ||
| the operating xDS configs of a running gRPC application. To make this more | ||
| clear, an xDS-compliant application receives many xDS configs, which may be | ||
| rejected or ignored or obsoleted. **The gRPC CSDS servicer should always return | ||
| the currently accepted xDS configs.** | ||
|
|
||
| ### Config Status in gRPC | ||
|
markdroth marked this conversation as resolved.
Outdated
|
||
|
|
||
| One critical field in CSDS responses is the config status. The config status is | ||
|
sergiitk marked this conversation as resolved.
Outdated
|
||
| an additional signal to help users debug, which indicates **the synchronization | ||
| state of the given xDS resources with the control plane**. CSDS designed config | ||
| statuses from a control plane point of view, and it only works at the | ||
| granularity of xDS config type. | ||
|
|
||
| This gRFC proposes adding following status enum to | ||
| ([config_dump.proto](https://github.com/envoyproxy/envoy/blob/main/api/envoy/admin/v3/config_dump.proto). | ||
|
lidizheng marked this conversation as resolved.
Outdated
|
||
| `ClientResourceStatus` better represents the viewpoint of xDS clients and it can | ||
| be as specific as per individual xDS resources. | ||
|
|
||
| ```protobuf | ||
| // Resource status from the view of a xDS client, which tells the synchronization | ||
| // status between the xDS client and the xDS server. | ||
| enum ClientResourceStatus { | ||
| // Resource status is not available/unknown. | ||
| UNKNOWN = 0; | ||
|
|
||
| // Client requested this resource but hasn't received any update from management | ||
| // server. The client will not fail requests, but will queue them until update | ||
| // arrives or the client times out waiting for the resource. | ||
| REQUESTED = 1; | ||
|
|
||
| // This resource has been requested by the client but has either not been | ||
| // delivered by the server or was previously delivered by the server and then | ||
| // subsequently removed from resources provided by the server. For more | ||
| // information, please refer to the :ref:`"Knowing When a Requested Resource | ||
| // Does Not Exist" <xds_protocol_resource_not_existed>` section. | ||
| DOES_NOT_EXIST = 2; | ||
|
|
||
| // Client received this resource and replied with ACK. | ||
| ACKED = 3; | ||
|
|
||
| // Client received this resource and replied with NACK. | ||
| NACKED = 4; | ||
| } | ||
| ``` | ||
|
|
||
| ### ADS Parsing Logic Update: Continue After First Error | ||
|
|
||
| Current gRPC ADS parsing logic is when the response parser observes an error in | ||
| the ADS response, it fails the entire message and aborts parsing. | ||
|
|
||
| To improve the debuggability of gRPC, gRPC needs to populate **the reason** and | ||
| **affected resources** when rejecting an update response. This information | ||
| requires the ADS parser to continue parsing past the first error. Here are the | ||
| expected behavior under scenarios: | ||
|
|
||
| * If the entire message won’t parse: no need to record anything in CSDS, since | ||
| we don’t know what type of xDS config or what resources are being updated; | ||
| * If one resource won’t parse: don’t abort the parsing, record the error in the | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The handling is still a bit ambiguous. I guess we would only record the first error, so the parsing does not need to continue. But would attach the error message to all previously accepted resources that the current response is attempting to update.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you specify the cases that are ambiguous here? I guess the wording here is not accurate enough, if one resource (e.g., a cluster) has validation error, the parsing should continue; or one of its field has parsing error, e.g. a config in Any failed to deserialize, the parsing should continue. In other word, the parsing should continue when possible. If you need a reference PR, please see grpc/grpc#25329.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks C-core is concatenating errors together if there are more than one error resources. I don't see much benefit of doing so, other than showing a giant error message while may still not showing all errors (e.g., multiple validation errors for a single resource). Anyway, I am fine with what's being implemented in C-core.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the important part is peeking into the ADS response to see what set of resources is being updated, then pasting the error details to their |
||
| error string. The error string will be attached to other resources that are | ||
|
sergiitk marked this conversation as resolved.
Outdated
|
||
| successfully recognized; | ||
| * If one resource has validation error: record the error, and attach the error | ||
| string to all resources including itself. | ||
|
sergiitk marked this conversation as resolved.
Outdated
|
||
|
|
||
| Here is an example of NACK information handling with new ADS changes: | ||
|
|
||
| ``` | ||
| # Imagine we have endpoint A, B, C | ||
| EDS -> {A, B, C}, version 1 | ||
| gRPC -> ACK | ||
| CSDS -> {Endpoint A, version 1}, {Endpoint B, version 1}, {Endpoint C, version 1} | ||
|
lidizheng marked this conversation as resolved.
Outdated
|
||
|
|
||
| # The newer endpoint B contains parsing error | ||
| EDS -> {A, B}, version 2 | ||
| gRPC -> NACK, Failed to parse endpoint B | ||
| CSDS -> {Endpoint A, version 1, rejected version 2, rejected reason: Failed to parse endpoint B } {Endpoint B, version 1, rejected version 2, rejected reason: Failed to parse endpoint B} {Endpoint C, version 1} | ||
|
lidizheng marked this conversation as resolved.
Outdated
|
||
|
|
||
| # Accepted update will clean error states | ||
| EDS -> {B, C} version 3 | ||
| gRPC -> ACK | ||
| CSDS -> {Endpoint A, version 1, rejected version 2, rejected reason: Failed to parse endpoint B } {Endpoint B, version 3}, {Endpoint C, version 3} | ||
| ``` | ||
|
|
||
|
|
||
| ### xDS Config Error State | ||
|
|
||
| When an ADS response is rejected, gRPC should provide debug information via | ||
| CSDS. This is done via `UpdateFailureState` within the `config_dump.proto`, | ||
|
lidizheng marked this conversation as resolved.
|
||
| which includes the version, timestamp, and the reason of the rejected update: | ||
|
|
||
| ```proto | ||
|
markdroth marked this conversation as resolved.
Outdated
|
||
| message UpdateFailureState { | ||
| ... | ||
|
|
||
| // Time of the latest failed update attempt. | ||
| google.protobuf.Timestamp last_update_attempt = 2; | ||
|
|
||
| // Details about the last failed update attempt. | ||
| string details = 3; | ||
|
|
||
| // This is the version of the rejected resource. | ||
| string version_info = 4; | ||
| } | ||
| ``` | ||
|
|
||
| ### CSDS Servicer Design | ||
|
|
||
| Ideally, the CSDS servicer should be reusable by our users, instead of just an | ||
| internal tool for the gRPC library. So, the CSDS servicer should be implemented | ||
| in wrapper languages and Java/Go. There are three major parts in the servicer | ||
| design: | ||
|
|
||
| * Cache resources in the global XdsClient; | ||
| * Collect additional metadata about the cached resource (update timestamp, | ||
| version, etc.); | ||
| * Assemble cached resources into the gigantic config dump response. | ||
|
sergiitk marked this conversation as resolved.
|
||
|
|
||
| For Java and Go, it’s straightforward that this feature can be implemented | ||
| bottom-up in the same language, and it’s possible to avoid an additional copy of | ||
| the message itself. But Core needs to transport the collected xDS configs across | ||
| the language boundary. The API needs to convert proto messages into C-compatible | ||
| types (e.g. `char *`, either bytes or JSON). | ||
|
|
||
| #### Detail: No xDS v2 Support | ||
|
|
||
| CSDS was meant to be a RPC service made for xDS management servers before this | ||
| proposal. But the service itself has the potential to serve client status on xDS | ||
| clients. However, during development, we found several constraints about the | ||
| existing service protocol, hence we merged several updates (see above) to | ||
| improve the CSDS service to meet our standard. The updates are made to xDS v3 | ||
| and xDS v4 (alpha) only, since xDS v2 is in deprecated state. This doc proposes | ||
| to not support xDS v2 for CSDS. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What to do if the underlying client is speaking v2?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. By underlying client, do you mean the gPRC application? I thought gRPC processes all xDS config into v3, so the dumped xDS config is agnostic to v2/v3. If the external CSDS client is only speaking v2, they won't be able to invoke the v3 method, because the fully-qualified-method-name includes the service name which has "v3" in it. So, the v2 external CSDS client will get UNIMPLEMENTED by default, in theory.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here's what TD does for v3 (currently only v2 supported):
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice, so in practicce, the old client will also get UNIMPLEMENTED.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that the CSDS RPC service name is different between v2 and v3, because the major version is part of the proto package name. So I think all we need to do here is to implement only the v3 service, not the v2 service. Then clients will get UNIMPLEMENTED if they try to use the v2 service, just like they would for any other unimplemented RPC service.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine to send v2 protos inside of the
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It's not one type of resource. All the resources in xds v2 are v2. E.g.
That's right.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's fine for CSDS client to need v2 protos if the client is using v2. That's independent of the fact that we're only supporting v3 of the CSDS RPC service itself. This is no different than ADS -- it's possible for a client to use v3 of ADS but v2 of the resource protos, or vice versa. In fact, in Envoy, those are two independent knobs. In gRPC, we just simplified it and avoided one of the knobs by depending on the fact that we didn't happen to use any fields in v2 that were being removed in v3, so we could just unconditionally treat all of the resource protos as v3.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This SGTM (and is actually easier to do :)) Let's update the gRFC to clarify this? This doesn't sound accurate:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated to
The section title also updated to |
||
|
|
||
| #### Detail: Cache Lifecycle | ||
|
sergiitk marked this conversation as resolved.
Outdated
|
||
|
|
||
| gRPC doesn't use xDS messages directly, but interprets them into language-native | ||
| class/struct. The lifecycle of the cached xDS messages should be identical to | ||
| the interpreted structure in each stack, so there is no memory management logic | ||
| change needed. | ||
|
|
||
| #### Detail: Expose xDS Config As Is | ||
|
|
||
| To date, gRPC supports the majority of xDS config but not all. Alternatively, we | ||
| could only dump the config that gRPC understands. However, doing so will create | ||
| a behavior difference between the gRPC and the control plane. It might be | ||
| confusing to users that some fields are missing. Also, during the configuration | ||
| dump, Envoy also dumps its entire configuration even if it doesn’t understand | ||
| some of the configuration fields (think of fields for Envoy extensions). So, for | ||
| correctness and simplicity, we should **cache and expose the xDS config the way | ||
| gRPC receives them**. | ||
|
|
||
| #### Detail: Node Matching | ||
|
|
||
| The node matching mechanism is not designed for gRPC’s use case, but for | ||
| querying the control plane. This doc proposes to ignore the Node matching query. | ||
|
lidizheng marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| ## Alternatives | ||
|
|
||
| ### Solution: Config Dump By Attaching An HTTP Server | ||
|
|
||
| Although it is the most straightforward way of implementing an admin interface, | ||
| Java doesn’t have a good enough built-in web server and it is challenging to | ||
| introduce yet another dependency into Core. Exposing application states via HTTP | ||
| will be challenging from engineering perspective. | ||
|
|
||
| ### Solution: Config Dump via Channelz | ||
|
|
||
| Though only a subset of xDS resources is applicable to a channel, xDS configs | ||
| (listeners, routes, clusters, endpoints) are global resources to a gRPC | ||
| application. One unsolved problem is that if we choose to use CSDS to expose xDS | ||
| configs, **the users won’t have the ability to query the set of effective xDS | ||
| configs for a channel**. The CSDS is not designed for finer granularity than | ||
| individual processes. | ||
|
|
||
| If we decided to support sharing XdsClient across multiple channels, the | ||
|
markdroth marked this conversation as resolved.
Outdated
|
||
| boundary of each channel’s xDS config will be blurry. Injecting xDS info into a | ||
| channel tracing service won’t be the right direction in the long term. | ||
|
|
||
| ### Solution: Config Dump via File | ||
|
|
||
| This approach saves the active xDS configuration onto a memory-based file system | ||
| location, like `sysctl`, or Envoy Runtime. However, due to the lack of two-way | ||
| communication and the complexity of the new machinery, this solution could cost | ||
| more engineering resources but yield less functionality. | ||
|
|
||
|
|
||
| ## Implementation | ||
|
|
||
| ### CSDS Proto Updates | ||
|
|
||
| * [envoy#13121]: the config synchronization status was defined from the xDS | ||
| management server point of view, this PR adds a set of ENUM to present the | ||
| config synchronization status from a client-side view. | ||
| * [envoy#14689]: the CSDS focused on dumping the in-effective xDS configs, but | ||
| we can do better to improve gRPC’s debuggability. This PR adds fields to | ||
| config dump protos to allow CSDS to return information about the rejected | ||
| update. | ||
| * [envoy#14900]: this PR adds two additional status to client configs, the | ||
| REQUESTED and the DOES_NOT_EXIST (read more). | ||
|
lidizheng marked this conversation as resolved.
Outdated
|
||
|
|
||
| ### CSDS Implementation | ||
|
|
||
| * Core: https://github.com/grpc/grpc/pull/25038 | ||
| * Golang: To be linked | ||
| * Java: To be linked | ||
|
|
||
| [envoy#13121]: https://github.com/envoyproxy/envoy/pull/13121 | ||
|
|
||
| [envoy#14689]: https://github.com/envoyproxy/envoy/pull/14689 | ||
|
|
||
| [envoy#14900]:https://github.com/envoyproxy/envoy/pull/14900 | ||
Uh oh!
There was an error while loading. Please reload this page.