-
Notifications
You must be signed in to change notification settings - Fork 251
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
Canonical Config #131
Canonical Config #131
Conversation
* place kvs into own package. * add sorted insert. * update deps Signed-off-by: Bojan <[email protected]>
Redo of PR #130 to fix the signoff breakage. |
go.mod
Outdated
@@ -3,19 +3,17 @@ module kubesphere.io/fluentbit-operator | |||
go 1.13 |
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.
This also needs to be upgraded to 1.16
.
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.
Update Go version in README.md
and go.mod
files
@bojand Have to say this is a great enhancement to existing logic! You mentioned you got compile errors after upgrading to go 1.16, is it solved now? You also mentioned |
Signed-off-by: Bojan <[email protected]>
@benjaminhuo That's correct. This solution only performs deterministic consistent rendering. The alternative would look something like this: return ctrl.NewControllerManagedBy(mgr).
For(&logging.FluentBitConfig{}).
Owns(&corev1.Secret{}).
Watches(&source.Kind{Type: &logging.Input{}}, &handler.EnqueueRequestForObject{}).
Watches(&source.Kind{Type: &logging.Filter{}}, &handler.EnqueueRequestForObject{}).
Watches(&source.Kind{Type: &logging.Output{}}, &handler.EnqueueRequestForObject{}).
Watches(&source.Kind{Type: &logging.Parser{}}, &handler.EnqueueRequestForObject{}).
WithEventFilter(predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
sOld := e.ObjectOld.(*corev1.Secret)
sNew := e.ObjectNew.(*corev1.Secret)
if sOld != nil && sNew != nil {
return false
}
return true
},
}).
Complete(r) But I don't think this is what we want really... |
Agree, Thank You! |
The current FluentBitConfig controller in the operator owns Kubernetes
Secret
objects, and watches for the custom types,Input
,Output
,Parser
, andFilter
. Within theReconcile
we gather existing objects, and then performs a merge and re-render all the configuration options. However several types (especially in filter plugins) havemap[string]string
as parameters. Additionally when we load the objects, I think the order is not guaranteed to be the same every time. Due to these conditions, as we increase the number ofInput
,Filter
, andOutput
objects created that may use map parameters, the config rendering becomes increasingly likely to be non-deterministic. This results in essentially an infinite loop in the reconciler...Reconcile()
, for example a newOutput
.Secret
object is updated, which causes the Update Event to fire and notify our operator.Reconcile()
is called again.Add
orSet
params inModify
filter may be different for example. Or order of plugins may be different. When we save the configuration in theSecret
object, the Secret is actually updated, with a new resource version, and the Update Event is fired, and we get notification to reconcile again...The issue worsens with the more fluentbit config objects are present. The fewer objects, the likelihood is greater we end up with the same permutation and stop the loop. More objects, and likelihood decreases and we are constantly reconciling.
This results in two main problems:
The problem is easily reproducible by creating a lot of objects, especially Modify filter with
Set
and/orAdd
, andOutput
objects withHeaders
property.This PR attempts to fix this issue and improve the operator by the following changes:
KVs
type into its own newparams
package withinplugins
package so that it can be used within pluginsInsertStringMap
function toparams
package to be used to canonically insert a mapLoad()
functionscontrollerutil.CreateOrPatch()
function. However it seems updatingsigs.k8s.io/controller-runtime
package caused update of everything.An alternative, perhaps somewhat hacky, solution is to use an event filter in the controller, and in
Update
predicate catch that we are doing an update to the secret and returnfalse
indicating that this Update event should not be processed. This does not seem like a correct approach to me.