-
Notifications
You must be signed in to change notification settings - Fork 39.7k
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
[Umbrella] Make client-go lighter and easier to consume #127888
Comments
Tagging some of the people I know will be interested/impacted |
Here's one more thought: If a simple Go client doesn't need I'm aware that this raises challenges for our publishing bot because we don't want to change the import paths. For example, if Can Go handle the transition of a package into its own module? For v0.31.0, |
Let me take this one step further: if don't do this, how much can we really reduce the dependencies of client-go? It doesn't help to remove a dependency from e.g. |
that is the thing, if it does not depend on apimachinery, or if apimachinery is lighter, or if we break apimachinery in smaller modules, .... but we should not use as excuse that there is already dependencies to add new, it is in the best for all of us maintainers to untangle things as much as possible |
I agree that it makes sense to simplify. But removing a dependency on "bar" from "foo" should not be based on the argument that it's being done to remove "bar" from the client-go dependency tree unless there really is a plan how that can be achieved. |
why not, everything that removes dependencies that are not necessary helps |
If some package becomes cleaner because it avoids some dependency, that's fine. But if it becomes more complex and client-go still depends on "bar", then it's a net loss. |
absolutely, goal is simplifying across the stack , as soon as things require more design and consensus we need a KEP with details ... but per example, since we have now a fork of go-yaml kubernetes-sigs/yaml#76 we can switch all the dependencies to it to have just one path and also avoid possible code drifting ... things like this can help to reduce the problem scope |
Related to simplifying across the stack, there are a number of in-progress transitions or duplications of code/effort in the tree. They don’t get much attention, and we tend to frown upon “blanket deprecation” PRs, but I do think it would be good to make progress on some of them, especially if they can help reduce dependency trees. For example, |
In my experience it works reasonably well. In theory, when a module is split out, the “main” module must declare a dependency on the new module, so that existing users aren’t broken on upgrades; but that defeats the purpose if the goal is to simplify dependency trees. |
#127889 makes me wonder if we could move parts of apimachinery that meet k8s.io/utils’ requirements to k8s.io/utils? apimachinery has a big set of dependencies, k8s.io/utils has a minimal set and is supposed to keep it that way. For example, all of apimachinery validation could be moved to k8s.io/utils if we move validation/fields, errors and sets too (for sets, replace it with k8s.io/utils sets). Put another way, we’ve ended up with two repositories of dependency-less utilities in k8s.io, apimachinery and sets, sometimes with duplicates. I think it would help this overall endeavour if we decided where these should live. |
Consolidating on sigs.k8s.io/yaml doesn’t help with the dependency tree, but it does improve consistency. See #127901 |
From my POV there are two aspects to 'light' -- low dependencies (less chance of dep hell, less licenses, etc), and smaller size (impacting final binary size which impacts end users). WRT to the smaller size, a very substantial portion of this is due to basically any import of (Unfortunately, even in an optimal package layout, if you depend on the tiny ConfigMap you also depend on the huge Pod) |
To make this more concrete, this example https://github.com/howardjohn/k8s-client-go/blob/e0023d6daa2795430e532f5813108f8087ec2014/generics/example/main.go#L19 (which compiles) is 9.8Mb stripped, 15M unstripped. With an import of FWIW in a not-direct comparison, using kube-rs (rust), it is more like 7.6M/11M. |
And the main reason for importing k8s.io/client-go/kubernetes even when using some sort of dynamic client is the scheme. The scheme in turn is needed to go from go type to GVK and vice versa. I don't know if there is much use-case for the latter outside of the kube-apiserver and the former would be much better solved by adding this info to the types rather than to a global (ideally together with restmapping, to avoid needing that lookup for dynamic clients). |
/triage accepted |
One other aspect we're looking for is ease of switching Kubernetes API versions specifically, ideally the transport layer etc is pretty stable and you should be able to quickly adopt and implement custom behaviors for the new types without needing to update any mess of dependencies, just a package with the types. I've been thinking a bit about how we might approach this and avoid breaking anyone at the same time.
I would go a step further actually: some of this should be in non-staged libraries that are actually versioned and developed with stable consumption in mind in their own repos, rather than being "staged" out as unstable v0.x But I think the first step is making it easier to consume the API types, with which you could bring your own client or skew the client (and use dynamic or a new generic API). If I read #127888 (comment) right, I think alvaro is roughly advocating for that part at least as well, and I have recently floated the concept to a few people (like antonio) who seem to agree. We're in the middle of enhancements freeze right now and will probably all have more bandwidth for this soon, possibly even at KubeCon? |
Related to this issue from the user's perspective: ideally |
Description
The current structure of client-go, with its dependencies on
k8s.io/api
andk8s.io/apimachinery
present some significant challenges:How to repro
Using the workqueue example https://github.com/kubernetes/kubernetes/tree/master/staging/src/k8s.io/client-go/examples/workqueue and creating a new project, after doing
go mod tidy
thego.mod
file looks like:go.mod
and its size is
Proposal
Design Details
k8s.io/api
Ideally this should be a self contained module without dependencies, but it depends on apimachinery for the generated code and registering the types
kubernetes/staging/src/k8s.io/api/go.mod
Lines 3 to 13 in 7b28a11
It requires
k8s.io/apimachinery
because of:NOTE This validation can be easily avoided and it seems is only to match a constant (cc: @pohly )
kubernetes/staging/src/k8s.io/api/resource/v1alpha3/types.go
Line 186 in 7b28a11
k8s.io/apimachinery
This is the more tricky, and it is bringing a lot of dependencies
kubernetes/staging/src/k8s.io/apimachinery/go.mod
Lines 3 to 33 in 7b28a11
k8s.io/client-go
These module contains all the generated code, the typed clients and the dynamic client. Thanks to @skitt we already have Generics to share code in client-go
In addition to the dynamic client we could have a Generic client, that will be able to work with different versions of k8s.io/api, allowing users to work with skew between k8s.io/client-go and k8s.io/api, though this requires a very high bar on these modules to avoid breaking clients and provide stability across the ecosystem.
kubernetes/staging/src/k8s.io/client-go/go.mod
Lines 3 to 37 in 7b28a11
Ideally we should be able to split the API types from the tooling and allow consumers to use generics, something like
and use generic controllers, we already have some intree
kubernetes/staging/src/k8s.io/apiserver/pkg/admission/plugin/policy/internal/generic/interface.go
Lines 27 to 59 in a7fcc89
Tasks
References
Notes
I don't create a KEP because there are a considerable number of dimensions in this problem, so as first step I just want to gather feedback and take a more iterative approach, there are things like dependency pruning that can be worked out without a KEP, once we reach a point we need to implement some user facing change I will open the corresponding KEP
/area code-organization
/sig architecture
/sig api-machinery
The text was updated successfully, but these errors were encountered: