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

feat(kuma-cp) k8s performance optimisation #1113

Merged
merged 14 commits into from
Nov 3, 2020
Merged

Conversation

lobkovilya
Copy link
Contributor

@lobkovilya lobkovilya commented Oct 26, 2020

Summary

Add cached k8s client

Kuma CP did an unlimited number of requests to Kubernetes API Server. That was leading to the "throttling" of Kubernetes API Server. Cached K8s client solves the problem. But default Cache is inefficient from a memory usage perspective. Every Get/List request returns a deep copy. I copied this Cache to Kuma codebase and got rid of deepCopy(). Also, since cached k8s client needs to be explicitly started (as a Component) I moved ClusterId creation into a separate component.

Add cache for marshaled resources

Alongside SimpleConverter I added CachedConverter which caches Marshal operation. We can't use it for webhooks because they take objects from Request (not from the Store) and these objects don't have ResourceVersion which makes such caching impossible.

Documentation

  • No need, behavior is preserved

@lobkovilya lobkovilya marked this pull request as ready for review October 27, 2020 05:59
@lobkovilya lobkovilya requested a review from a team as a code owner October 27, 2020 05:59
Copy link
Contributor

@jakubdyszkiewicz jakubdyszkiewicz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work! 👏

pkg/core/resources/model/resource.go Outdated Show resolved Hide resolved
*/

// Package cache is a copy of the package sigs.k8s.io/controller-runtime/pkg/cache
// but without deepCopy on Get and List methods
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although I understand the importance of having this K8S cache with modifications I want to discuss the long term strategy. I find such copy paste hard to maintain. Action items that IMHO needs to be applied here

  • Provide a more explanation why deepCopy was removed
  • Clearly mark fragments in the code that were modified for example
// Kuma modification start
// Kuma modification end
  • Please start the conversation with Kubernetes community and let's try to put this in upstream. I don't expect this to be easy, but let's at least try to raise the problem.
  • We need to remember about this when upgrading Kubernetes library. Any ideas?

pkg/plugins/extensions/k8s/context.go Show resolved Hide resolved
pkg/plugins/extensions/k8s/context.go Outdated Show resolved Hide resolved
pkg/plugins/resources/k8s/store.go Show resolved Hide resolved
pkg/plugins/extensions/k8s/context.go Outdated Show resolved Hide resolved
runtime.SetClusterId(clusterId)

return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of putting this in defaults? I'd love to avoid having a separate package in pkg just for this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did so, but then figured out defaults and clusterid work in different modes, defaults runs everywhere, clusterid runs only in Global and Standalone mode.

I don't mind having clusterid as a separate component (even if it's tiny). I think we can create dir pkg/components and move all components here. Every component should have func Setup(rt runtime.Runtime) error function, own logger, documentation, and component's level tests. That's pretty much what we have today but it's not really ordered

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know if you remember my presentation on one of the community call, but I also wanted to segment into a couple of main packages (util, core, api, components, plugins), where there are clear rules about dependencies between all packages. Components leave in separate components package. The main thing that I would like to see is to have 0 dependencies between components. They should be like separate processes that can be pulled off from the code.
https://docs.google.com/presentation/d/1EyEGpji6UHFYPyD4krORcIsD8aubDE9GXfDVlhhUNOo/edit?usp=sharing

but in terms of clusterid and defaults. Look that signing key is created also in global and standalone, but I put this in defaults. If you think about this, it's a matter of where you put the "if".

  1. Put if whether to run small component
  2. Put if in bigger component that creates defaults.
    I prefer the second one, in this case, I think we "overpackage" many places in the codebase.
    But I leave your judgment on which one to do, I'm not strongly attached to the second option.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, of course, I remember your presentation. I totally get your idea about bigger components with less packaging. But unlike signingKey this clusterid doesn't really have "defaulting" functionality. It's more like "cluster init" functionality. So I'm not sure it belongs here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClusterID is the same "default" as Signing Key which is a random value.

pkg/plugins/bootstrap/k8s/plugin.go Outdated Show resolved Hide resolved
Signed-off-by: Ilya Lobkov <[email protected]>
Signed-off-by: Ilya Lobkov <[email protected]>

# Conflicts:
#	app/kuma-cp/cmd/run.go
Signed-off-by: Ilya Lobkov <[email protected]>
@lobkovilya lobkovilya merged commit a71c953 into master Nov 3, 2020
@lobkovilya lobkovilya deleted the feat/k8s-perf-opt branch November 3, 2020 11:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants