-
Notifications
You must be signed in to change notification settings - Fork 306
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
Extract firewall management into separate controller #403
Conversation
/assign @nicksardo |
Note: This does not compile because of an import cycle. Trying to fix that now, but should not affect review. |
af1b4d5
to
bbbf955
Compare
@@ -193,6 +200,9 @@ func runControllers(ctx *context.ControllerContext) { | |||
ctx.Start(stopCh) | |||
lbc.Run() |
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 believe this blocks...
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.
Oops..moved start of fwc above lbc.Run()
bbbf955
to
b9d5a35
Compare
pkg/utils/join.go
Outdated
// IngressesForObject gets Ingresses that are associated with the | ||
// passed in object. It is a wrapper around functions which do the actual | ||
// work of getting Ingresses based on a typed object. | ||
func (j *Joiner) IngressesForObject(obj interface{}) []*extensions.Ingress { |
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'd suggest ditching the wrapper and exposing the ...ForService
and ...ForBackendConfig
funcs.
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.
Ditched the wrapper
pkg/utils/join.go
Outdated
// NewJoiner returns a Joiner. | ||
func NewJoiner( | ||
ingressInformer cache.SharedIndexInformer, | ||
svcInformer cache.SharedIndexInformer, |
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.
Suggest passing in the listers instead of the full informers.
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.
Done
pkg/utils/join.go
Outdated
svcInformer cache.SharedIndexInformer, | ||
defaultBackendSvcPortID ServicePortID) *Joiner { | ||
ingLister := StoreToIngressLister{Store: ingressInformer.GetStore()} | ||
return &Joiner{ingLister, svcInformer, defaultBackendSvcPortID} |
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.
Actually, I'm not seeing a strong reason why Joiner
needs to exist as a struct. Seems more flexible to make the last two funcs static and pass in the appropriate lister. Then a consuming controller isn't forced to provide all listers even if it only uses one.
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.
So after trying the alternative, I think its much easier to read the code when Joiner exists as a struct. The reason is because the initalization of the struct will take care of storing all necessary things needed (listers, default backend service port ID) and then the function calls become nice and compact. The alternative is that each function call becomes really bloated with all the necessary arguments.
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.
To alleviate the problem of sometimes passing in stuff you don't need, maybe the Joiner can just take a ControllerContext? That contains everything it needs.
pkg/utils/taskqueue.go
Outdated
@@ -29,6 +29,7 @@ import ( | |||
type TaskQueue interface { | |||
Run(period time.Duration, stopCh <-chan struct{}) | |||
Enqueue(obj interface{}) | |||
EnqueueAll(objs []interface{}) |
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.
Variadic func?
Enqueue(obj ...interface{})
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.
Done
pkg/firewalls/controller.go
Outdated
ctx.ServiceInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{ | ||
AddFunc: func(obj interface{}) { | ||
ings := joiner.IngressesForObject(obj) | ||
lbc.ingQueue.EnqueueAll(ings) |
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.
fwc.queue
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.
Done
0b8359f
to
63bd9a7
Compare
Realized there are some things I haven't thought about that I need to add to my implementation. Marking as "WIP" for now. |
63bd9a7
to
d52021e
Compare
2dcca64
to
dc8f7bd
Compare
pkg/firewalls/controller.go
Outdated
func (fwc *FirewallController) Run(stopCh chan struct{}) { | ||
defer fwc.shutdown() | ||
go fwc.queue.Run(time.Second, stopCh) | ||
<-stopCh |
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.
If Run(...)
is supposed to block, is there any need to start the fwc.queue.Run(...)
in a goroutine? Also, fwc.shutdown()
calls firewallPool.Shutdown()
which deletes the firewall. That should only be called when we have no ingresses/NEGs.
func (fwc *FirewallController) Run(stopCh chan struct{}) {
fwc.queue.Run(time.Second, stopCh)
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.
Removed firewallPool.Shutdown from the fwc.shutdown() call.
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.
Now I think the behavior for all these shutdowns is correct. We only call shutdown on the firewall pool if there are no ingresses and we only shutdown the queue when the process itself is terminated
pkg/firewalls/controller.go
Outdated
<-stopCh | ||
} | ||
|
||
func (fwc *FirewallController) shutdown() error { |
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.
Add a comment that this should only be called when we no longer need a firewall rule.
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.
So actually the shutdown() on the controller should only consist of the queue being shutdown. Also, we should only call shutdown() on the controller when the overall process is being terminated right?
pkg/utils/join.go
Outdated
} | ||
|
||
// IngressesForBackendConfig gets all Ingresses that reference (indirectly) a BackendConfig. | ||
func (j *Joiner) IngressesForBackendConfig(beConfig *backendconfigv1beta1.BackendConfig) (ingList []*extensions.Ingress) { |
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.
Maybe add a low priority TODO note for optimizing the joining here.
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.
Done
01eec3f
to
d17223f
Compare
/lgtm |
d17223f
to
ebaf600
Compare
Made some small changes:
I tested this end-to-end and it works so it should be good to merge. |
/assign @MrHohn |
/lgtm |
This PR attempts to move the management of the L7 firewall rule into a separate controller.
Summary of changes:
Add controller.go to pkg/firewalls. This new controller also creates and interacts with the firewall pool, rather than the ClusterManager. Currently, the controller watches ingresses and services and updates the firewall rule as necessary. In the future, we can extend this to support the firewall rules for expose NEG.
Remove all firewall related stuff from ClusterManager and pkg/controller/controller.go
Move IsHealthy from ClusterManager to the controller the health check is meant for. It really has notplace in ClusterManager.
This leads well into a followup PR which can remove the ClusterManager entirely. Open to discussion on some of the design decisions in the PR. /assign @nicksardo