-
Notifications
You must be signed in to change notification settings - Fork 594
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
fix(consumer): duplicate ID2 breaking DB-mode #1007
Conversation
c2b8086
to
3169a69
Compare
7506c1f
to
ec7d4a8
Compare
How does this handle sort order for credentials that have the same ID2? It's effectively random, correct? I think this introduces a footgun that allows you to inadvertently replace in-use configuration, e.g.
This is somewhat mitigated because this only handles credentials for a single consumer, not credentials on separate consumers (we'll still attempt to apply those and hit the same admin API error). We'd need to further tiebreak by credential creation time to avoid that. |
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.
Generally LGTM, just a couple of small comments 👍
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.
Good explanations in the code review, thank you.
LGTM ✔️
The order is directly as returned from informer stores. Therefore, we need to treat it as effectively not guaranteed to be anything meaningful.
That is correct, and this is a part of a bigger problem: given two conflicting entities that made it through our admission validations, KIC needs to distill some valid config from it and apply it to Kong. Otherwise the only option is for KIC's sync loop to lock up, which is terrible user experience. The problem is that a fair "tie breaker" for conflicting configs is an unsolved problem. The best we can do today is to drop an arbitrary subset that makes the config no longer nonsensical.
I would like to avoid using creation time because it introduces an external factor (creation time) to KIC's semantics. This external factor is likely to surprisingly change if the user, for example, restores their k8s objects from a backup, or from a gitops repository. Therefore I don't see a clear benefit of using creation time rather than picking an arbitrary resource. I'm all in for deterministic and well-defined conflict resolution, but I would rather see something that relies on the configuration that the user controls (e.g., in case of conflicting resources, drop one that has a lexicographically greater namespace+name). I recommend leaving this as-is and creating an issue to be solved later (deterministic conflict resolution based on user-controlled factors). WDYT? |
Context: #729 Before this PR, KIC failed to apply config to DB-backed Kong, in case the config contained a Consumer with two credentials having equivalent ID2 fields (Key for key-auth, ClientID for OAuth2, etc.). This commit de-duplicates credentials of each type, by replacing the Consumer store for credentials with a map (ID2 -> credential object), and updates relevant tests. Also, this commit implements consistent credential ordering.
This REVERSES the sorting order from reverse to normal. The history behind reverse order is purely accidental. There are no known reasons in favor of one or the other. What matters is the order being deterministic.
Co-authored-by: Shane Utt <shaneutt@users.noreply.github.com>
92e8cd6
to
70dbb1a
Compare
Codecov Report
@@ Coverage Diff @@
## next #1007 +/- ##
==========================================
+ Coverage 49.56% 50.70% +1.13%
==========================================
Files 32 32
Lines 3198 3205 +7
==========================================
+ Hits 1585 1625 +40
+ Misses 1483 1440 -43
- Partials 130 140 +10
Continue to review full report at Codecov.
|
Solution blocked by discrepancy between DB-enabled and DB-less mode of Kong (as described in Kong/kong#6732). Semantics of conflict resolution to be defined following agreement with Kong/kong maintainers on the desired semantics of duplicate entries. |
Re discussion elsewhere on whether to use creation timestamp or something else, I'd like to step back and reject the underlying premise:
This is hamstrung by a lack of any valid configuration in this scenario. If you've created two credentials that collide, we can only apply one, and which we choose to apply affects the proxy behavior. I originally suggested creation timestamp because it seemed least likely to result in a change in proxy behavior, since the older resource would have a greater chance of being applied first, but it's not a great solution either. Any tiebreaker we choose is effectively arbitrary, but user-controlled tiebreakers pose an odd question: if you know that two resources collide, why would you set the tiebreaker such that one resource is used rather than either deleting one of the resources or choosing non-colliding values? If you don't know, you could try at random until your configuration wins, but I don't think it's something we'd want to encourage.
Agreed, but it at least fails relatively safely, since your proxy will continue using existing configuration. Assuming you're not aware of the conflict (again, if you are, you should resolve it by other means), using a tiebreaker results in one of the following:
These are both bad user experience, and potentially more disruptive, since the latter obliterates in-use configuration. The real issue with the sync loop blocking is that we cannot discard configuration piecemeal: it'd be a much smaller problem if it did not lock up entirely and prevent sync of other (valid) configuration added after. This is hard to solve, but I don't think attempting to mask collisions is a good way to handle it. Absent some way to report (and ideally reject) the problem configuration, I think the only safe option is to let the status quo (sync block) stand. |
I fully agree that we don't want to encourage KIC with invalid configurations. That said, as a matter of fact, users will keep feeding invalid configurations to KIC. What can we do about it? I see three layers of defense here:
(1) is achieved by CRD schemas and webhook validations. None of these is capable of validating unique constraints across all resources in the cluster, other than resource name. There are measures we can theoretically take to prevent some of these cases, but conflicts will fall through the cracks. Outside of the scope of this issue I think, but we can agree here to implement such a solution separately to improve UX. (2) KIC does this today by print warning log entries. A better way to do that would be in (3) is the clue here. It's quite clear that if KIC config contains 2 or more conflicting entities, there's no theoretical possibility to apply a working and correct config for that subset of configuration because there's no "correct" way to do it. This is obviously an unrecoverable failure scenario. In an unrecoverable failure scenario one thing that we have under control is the scope of that failure. And:
So, the question here is whether, in case of failure, we choose to degrade only to the extent of the conflicted resources, or to degrade everything. Here are the concerns about the proposed solution I've understood from #1007 (comment) (please correct me if I missed something):
On (1): I believe that we can solve this by providing better feedback about configuration errors - using On (2): the premise that old config is more meaningful than new config, and should always win, incompatible with the Kubernetes configuration model that is based on eventual consistency and no temporal relationships between entities. On (3): why not? This is a serious question. Maybe I'm missing some hidden complexity. My thinking is: "walk through all the resources in a deterministic, well known order. If the currently processed resource is conflicted with the already seen state, warn loudly and assume the fiction that it didn't exist in the config". Therefore I propose that:
WDYT @rainest? |
Removed the "blocked" label because the blocking premise (need to rely on Kong/kong maintainers' input about the discrepancy between db and dbless) is obsolete. |
Closing this PR - migration of KIC to Railgun will command a different solution. |
fixes #729
Before this PR, KIC failed to apply config to DB-backed Kong, in
case the config contained a Consumer with two credentials having
equivalent ID2 fields (Key for key-auth, ClientID for OAuth2, etc.).
This commit de-duplicates credentials of each type, by replacing the
Consumer store for credentials with a map (ID2 -> credential object),
and updates relevant tests.
Also, this commit implements consistent credential ordering.
refactor(controller): implement sortByString
This REVERSES the sorting order from reverse to normal.
The history behind reverse order is purely accidental. There are no
known reasons in favor of one or the other. What matters is the order
being deterministic.
test(controller): toDeckContent sorts creds
test(kongstate): deduplicates credentials