-
Notifications
You must be signed in to change notification settings - Fork 169
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(kubernetes): Pruning #131
Conversation
Todo
|
Before, the name of the internally used Environment type was different depending on the argument passed on the command line, even though it resulted in the same environment after all (relative vs absolute paths, etc.) This fixes the issue by using the `jpath` package to compute baseDir and rootDir, using the relative path from rootDir to baseDir as the name. This results in stable names, regardless which directory representation is used.
The environment's name (relative path from rootDir) is now added into each created resource as a label, to be able to easily identify objects by their origin. Furthermore, the Kubernetes type now includes the entire Environment (had only the spec before), to be able to access the env's name in that package as well
Allows to query all known apiResources from the server
Adds support for removing orphaned objects from the cluster. They can be viewed in diff and removed in apply
Pruning defaults to enabled, but can be opted out using `--prune=false`
Broken in upstream, nothing we can do anything about
All of our current commands take environments, only the import analysis works on plain files ... this has no benefit, it actually makes the implementation harder, as we cannot use stable paths there. Switches to environments as the target.
making it opt out can result in dangerous moments when the local sources are not recent enough. As this could kill entire clusters, we are going to make it opt in
@rfratto @malcolmholmes I guess this is ready for another round of review.
I think it is safe for production usage now. WDYT? |
How will CRDs work in this? (Basically: Why not just duplicate the logic used in kubecfg and descendents (ksonnet, qbec, etc)?) |
I don't think CRDs will work with this particularly well. The Kubernetes API does not provide a "list all resources" API (well it does, but the 'all' that it lists is just a subset of resources). There is |
Kind of. While implementing a similar feature in kubectl, it became an obvious limitation that we cannot check all kinds at once ... this is a design thing of the API and cannot be fixed easily. Instead, kubectl uses a whitelist of the most common objects – which obviously won't include CRD's. Tanka uses the same list, but also supports checking the entire list, but this will be much slower. Of course we could add a flag that allows you to extend the whitelist on the CLI. So @anguslees to answer the question:
|
presumably you could also add the whitelist in spec.json? Then, if there are specific resource types that aren't in the default list, you know they will ALWAYS be checked for the relevant environments? |
I think it is the wrong place, because such a thing applies per library (libraries introduce CRD's after all) and not per environment. Otherwise, you would need to track the whitelist across all JSON files, which leads to config drift, which is the entire goal of Tanka to prevent this. Thus said, we could instead introduce a special {
"tanka.dev": {
"additionalPruneKinds": [ ... ],
}
} This also means the library that introduces a CRD can specify it directly, users won't even notice it |
That could work too. It would be ignored as regarding kubernetes resources, which is good. I would suggest:
Or better still:
"additional" implied by jsonnet construct. |
Like that! Depends on whether we can preseed the initial Jsonnet object though ... @sbarzowski is this possible? And are there any drawbacks? |
Repeating ^. I think the authors/reviewers of this PR should be aware that kubecfg/ksonnet/qbec follow an algorithm different to kubectl/helm, and I think it addresses a number of weaknesses in the kubectl-prune approach (disclaimer: I wrote the initial version in kubecfg). In particular they walk all the GroupKinds (using api-versions introspection) and work just fine with CRDs since they contain no hard-coded list. Happy to swap notes further if it's useful - mostly just wanted to ensure you're choosing the proposed whitelist-approach with knowledge of alternatives. |
@anguslees To be honest, we did not consider other approaches in the ecosystem when designing this ... we took Could you please share some details on the approach you suggest?
We are not fixed to what is done in this PR, if there are better ways to address the issue I am happy to abandon this one and use something else :D |
Replying here so that when this feature is resumed, it can be discovered:
The relevant bit of kubecfg's code is https://github.com/bitnami/kubecfg/blob/f07144e10f55b35eed18e5fd0e1335be91105a1a/pkg/kubecfg/update.go#L338 From memory, qbec implements (mostly) the same algorithm using different code, if you want another source. qbec's gc docs are https://qbec.io/reference/garbage-collection/ and are a good summary of the issues involved.
Correct, there is no whitelist.
It takes as long as it takes to do an API list for each groupkind. In my experience this is dominated by the round trip time to the server (assuming they're done sequentially) - for a "local" apiserver, the entire garbage collection process takes 10-ish seconds for my 100-ish-pod cluster.
Works fine. The key point here is to track objects by uid, not by apigroup+namespace+name. The "same" resource willl have the same uid, even when viewed through multiple apigroups/versions.
Don't know the tanka codebase well enough to answer that. I suspect the hardest part will be building the list of apigroups, since the output from |
This PR is another take on implementing a garbage collection of resources, that are no longer present in the Jsonnet code.
@malcolmholmes already experimented with using a label and removing resources (#117) and
kubectl apply --prune
(#123). Both attempts had their shortcomings (performance, reliability).Just out of interest I tried what I could come up with and so far I think this is robust enough to be used in production:
tanka.dev/environment: <relative-path-from-project-root>
kubectl apply --prune
uses) and check if there is anything labeled in there we don't know about--prune=false
, labeling can be disabled usingspec.injectLabels.environment
.Can I get some opinions on this @rfratto @gouthamve @tomwilkie?
Co-authored-by: Malcolm Holmes [email protected]