-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Conversation
f58c1e8
to
e04b4e1
Compare
Can you fill out the description a little bit more to describe what this does? I’m not exactly sure what “stack tracking” means or what a “stack” is in this context. |
@justinbarrick see #738 (comment) and #738 (comment) |
What is the purpose of the checksum? It seems to me that if we just added a label to the resources (any label really would work), you could still sweep for resources that have the label but do not match any defined resource in the repository based on type / namespace / name. AFAIK this is how Helm works. I can see checksums being useful if we just want to know if we need to update a resource, but I would expect just using kubectl gives something similar to us already. |
8acf3da
to
066c2da
Compare
Yes, true. When you have access to the names of the things that should be there, all you need to know for deletion is whether it was created by flux in the first place. So the checksum is of use only if you are concerned about reapplying manifests unnecessarily. However: we deliberately reapply manifests even if it looks unnecessary, to revert changes that have been made out-of-band. For example, if someone patches a resource with We still might want to report on things that look out of date, so I'm inclined to leave the checksums in, even if we don't use them in control flow. |
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.
I've done an initial scan over this, and made some comments on where things seem a bit out of place. It's all up for discussion :-)
I've added a flag
Resources are collected into named stacks and given a checksum before being passed to
I rewrote it to do the minimal amount of {de,en}coding.
Good question; I've punted on that for the minute.
Anything that wasn't given a
It might make any race conditions less likely to bite, but it wouldn't remove them. In any case, I think once
I've replaced the printfs with logger.Log. What may have been happening is that
Yup. I need to bring the existing tests up to date; then we'll have to put in new ones that cover the various scenarios of moving, removing, adding, resources.
I think |
While working on those commits, I did start wondering why stacks exist. I accept the argument for limiting the "blast radius" of changes (so e.g., every time you change a label somewhere, it doesn't result in every single resource being updated). But why not limit the blast radius to a single resource? |
Thanks for the extensive updates! Sorry I don't have more time to work on this right now. 😅 A hash per-resource would probably work well. This was originally based on prior art that had the stack concept, more akin to Helm/Charts. |
42bb01a
to
41dbe4e
Compare
I've rebased this and made sure the tests run and pass. The latter meant losing some coverage -- specifically, testing whether deleting a resource results in the cluster resource being deleted. I'll have to build up the tests in cluster/kubernetes to cover that. |
Anything I can help with to push this along? :-) I think I have some free time coming up. |
Upgraded to this new version in my cluster and it's working great! |
I've added some test scaffolding in |
Idea: use a sanitised git repo URL as the stack name. That means that when flux supports multiple repos, it will be able to do syncs piece-wise, a repo at a time, and not delete something that simply came from another repo. Technically, we can partition and name the stacks whatever we like. But it might be nice to have a label saying which repo a resource came from, for other purposes. And, it's useful for the stack to be a less than or equal to the unit of syncing; otherwise, there might be glitches where, say, a resource gets deleted because it has changed stack but that hasn't been applied yet. (Syncing per repo will have this issue, if a resource moves from one repo to another -- but since repos are updated independently, so will syncing all repos at once). |
@Timer I have a rebased branch that squashes the commits you marked as |
Feel free to force push anything you'd like. :-) |
1d629b0
to
9aa11a1
Compare
I think this is ready for release as an experimental feature (i.e., can be reviewed and merged). To address the TODOs:
The annotation "flux.weave.works/ignore" will effectively make something immortal -- flux won't apply it, and (if on a resource in the cluster) won't delete it, even if it's removed from the repo.  - cluster.ExportByLabel should probably be given a few failure/retry cases to handle; what about when we're limited by RBAC? Accounting for the possibilities is a bit mind-boggling. I think it might be easier to release this as an experimental feature, and try it in the real environments (by which I mean disposable environments).  - Skipped resources (v1:ComponentStatus and v1:Endpoints) shouldn't happen at listing level, but probably delete/diff level I'm not convinced we have to skip any resources at all, for correctness. We can generalise or embellish this later if necessary, though. |
@rndstr Do you mind having a look at this? I won't hold you to a definitive approval, unless you want to give one :-) |
@squaremo i likely won't be able to give it a proper look before next Tuesday |
sync/sync.go
Outdated
logger.Log("resource", res.ResourceID(), "ignore", "apply") | ||
return | ||
continue |
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.
nit: noop
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.
played around with it some more locally and it works great.
Brilliant, thanks for the review Roli! I appreciate you taking the time to check this out :-) I had another play myself and I have noticed something: resources that aren't namespaced will get deleted even if they are among the files. The cause is that when loaded from files, resources get given the "default" namespace if they don't specify one. But when loaded from the cluster, they will either have a namespace (because they've been created in a namespace implicitly) or have an empty Assigning the namespace I don't think there's anything for it other than to figure out which resources are supposed to have a namespace, and filling in the default value. Ideally we'd be able to do that in a place we're already querying for resources. |
f11b18c
to
1d86d57
Compare
08b4ff5
to
a6f0142
Compare
a6f0142
to
aeef2c6
Compare
I think all the comments have been addressed. The only missing thing is documentation. |
7bdd82d
to
e949383
Compare
The PR #1442 introduce code to determine which namespace, if any, each manifest belongs to. To distinguish between resources that need a namespace but don't have one, and resources that are cluster-scoped, it introduced the sentinel value `<cluster>` for the latter. Regrettably, I didn't accompany this with code for _parsing_ those sentinel values, since I reasoned that it would only be used internally. But the sync events generated by fluxd include a list of changed resources, and those inevitably will include things like namespaces that are cluster-scoped. The result is that fluxd will generate events that cannot then be parsed by the receiver. This commit fixes that by recognising `<cluster>` as a namespace when parsing resource IDs.
This fixes a regression introduced by fluxcd#1442 in which applying the `tag_all` pseudo policy failed for workload manifests in which the namespace is ommited. The effective namespace of the workload wasn't set after parsing, causing a mismatch in the resouce identifier (the parsed resource indentifier was cluster-scoped due to the lack of explicit namespace in the manifest).
This fixes a regression introduced by fluxcd#1442 in which applying the `tag_all` pseudo policy failed for workload manifests in which the namespace is omitted. The effective namespace of the workload wasn't set after parsing, causing a mismatch in the resource identifier (the parsed resource identifier was cluster-scoped due to the lack of explicit namespace in the manifest).
This fixes a regression introduced by #1442 in which applying the `tag_all` pseudo policy failed for workload manifests in which the namespace is omitted. The effective namespace of the workload wasn't set after parsing, causing a mismatch in the resource identifier (the parsed resource identifier was cluster-scoped due to the lack of explicit namespace in the manifest).
This pull request adds stack[1] tracking. Stack tracking attaches metadata to every object created by Flux so resources removed from the "Config Repo" can be pruned.
Every object or updated created by Flux gets assigned a label with the stack's name, e.g. (
flux.weave.works/stack: default
). Additionally, it also gets a checksum which is an aggregate of all resources in that stack:flux.weave.works/stack-checksum: cf23df2207d99a74fbe169e3eba035e633b65d94
.After cluster changes have been applied, a full list of cluster resources are retrieved by the stack label. Any resources who's
stack-checksum
do not match the most recently applied checksum are pruned.Current Test Image
You can test this PR by using the following Docker image:timer/flux-with-stacks:feature-stack-tracking-1d481d0
.Outdated.
TODOs
--experimental-deletion
cluster.Cluster
'sSync
method should probably receive a more appropriate object than2x
map[string]policy.Update
cluster.applyMetadata
should be refactored and simplifiedcluster.ExportByLabel
should probably be given a few failure/retry cases to handle; what about when we're limited by RBAC?v1:ComponentStatus
andv1:Endpoints
) shouldn't happen at listing level, but probably delete/diff levelsync.garbageCollect
mark the object for deletion and only prune it next run? This could help with any race conditions in the K8s API server (I didn't run into any, but you never know).sync.Sync
sofmt.Printf
had to be used. We should figure this out.flux.weave.works/immortal
Post-merge follow-ups
Background
propagation mode[1]: an arbitrary collection of k8s resources