-
Notifications
You must be signed in to change notification settings - Fork 34
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
Istio ext authz service config #17
Conversation
Currently Istio does not provide them
Fixes issue istio/istio#36114 (comment) preventing the operator to successfully reconcile changes in the IstioOperator custom resource
ready for review @Kuadrant/engineering |
// Log is the base logger | ||
Log logr.Logger = ctrllog.NullLogger{} | ||
) |
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 don't think we require an upgrade here, right?
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.
we will when upgrading logr to 1.X
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.
LGTM!
// service: AUTHORINO SERVICE | ||
// name: kuadrant-authorization | ||
|
||
extensionProvidersObj, ok := iop.Spec.MeshConfig["extensionProviders"] |
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.
My previous comment actually applies better 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.
updated
logger := logr.FromContext(ctx) | ||
newStatus := r.calculateStatus(kObj, specErr) | ||
|
||
equalStatus := kObj.Status.Equals(newStatus, logger) |
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 suppose this is to prevent unnecessary updates on the status, where a minimum spottable diff would be the value of LastTransitionTime
of a particular condition, is that right?
Is it worth the cost of checking while:
- leader election is enabled and therefore only one replica at a time will reconcile the resource?
- status update is an idempotent operation?
Please, no need to change anything. I'm just trying to understand the 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.
To prevent unnecessary updates on the status, specifically related to the LastTransitionTime
field, conditions are first copied from the existing CR and then desired values applied. After that, they are compared. The status is only updated when there are changes.
leader election is enabled and therefore only one replica at a time will reconcile the resource?
I do not fully understand this point. The controller does not expect anyone to change the status. But even if it changes, the controller will set its desired state.
status update is an idempotent operation?
Yes it is. Identical status requests should always turn into a identical status objects in the CR.
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.
leader election is enabled and therefore only one replica at a time will reconcile the resource?
I do not fully understand this point. The controller does not expect anyone to change the status. But even if it changes, the controller will set its desired state.
When leader election is enabled in a manager, no matter how many replicas of the operator are running, only the leader will perform the reconciliation tasks under this manager; therefore, also the status update. IOW, I think there's no concurrency to worry about. (Unless reconcilers are invoked in concurrent goroutines. Are they? 🤔)
status update is an idempotent operation?
Yes it is.
So why carrying checking for changes in the subresource? Because sorting the array and marshalling 2 JSON objects cost less than sending the update request? If the update happens in the background (because we don't have to wait until it finishes to return from reconciling, right?), wouldn't it be better to just trust idempotence and skip the check?
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 procedure does not try to prevent race conditions. The race conditions and updating stale data is handled by the API server. When you update the status (same applies to the spec), the operation update makes sure the update is made from the latest available data, otherwise you get Conflict
error. If there is a race condition, one of the updates would fail and the controller needs to retry reading first the latest object data.
This procedure tries to follow the controller pattern: get existing, get desired. If existing does not exit, create desired. If existing exists, compare to desired, if there are changes, update.
So why carrying checking for changes in the subresource? Because sorting the array and marshalling 2 JSON objects cost less than sending the update request? If the update happens in the background (because we don't have to wait until it finishes to return from reconciling, right?), wouldn't it be better to just trust idempotence and skip the check?
Not very concerned about the cost, TBH. IMO, one update request has much more cost (I would say several orders of magnitude) than serializing in memory struct objects which are not expected to be "big".
It is more about my instinct of doing the right thing: I do not update if there is nothing to update. That has a cost of checking, indeed. Worth doing it most of the times. This controller is now very simple, but it could be watching many other types and get events from those types, for instance the IstioOperator. So I could expect many reconciliation loops to happen. I think it is wise to save updates and do not update all the time. Open to other approaches, though ;)
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.
In Authorino and in Authorino Operator we went with a different approach, where we trust idempotence of the status update operation and leave the rest to the API server.
But it's your call.
one update request has much more cost (I would say several orders of magnitude) than serializing in memory struct objects which are not expected to be "big"
Maybe I wasn't clear before. You don't have to wait for the state update to finish. You can fork a goroutine to handle the update and return immediately. So, from the perspective of freeing the reconciler/closing the connection, performing the update without the check is theoretically faster.
On the other hand, I totally understand if you don't want to handle this in the background (it could fail!)
And, as you said, sorting two arrays of 5-6 elements each + serializing two small structs as JSON, we're talking nanoseconds might not worth saving.
Anyway, the PR LGTM. As I said before, I was just trying to understand the flow. Not suggesting changing anything.
setupLog.Info(fmt.Sprintf("go version: %s", runtime.Version())) | ||
setupLog.Info(fmt.Sprintf("go os/arch: %s/%s", runtime.GOOS, runtime.GOARCH)) |
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.
Nice touch! I might steel this idea for kuadrant/authorino now that we're building for multi-arch. 🙂
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.
👮
Co-authored-by: Guilherme Cassolato <[email protected]>
* Fix API type to include security requirements * Generate manifests after the API type update
what
Authorino set up in Istio as a Auth GRPC service
Fixes Kuadrant/kuadrant-controller#149
debug
→info
→error
) and configurable log modes:production
,development
Ready
conditionISTIOOPERATOR_NAME
istiocontrolplane
ISTIOOPERATOR_NAMESPACE
istio-system
verification steps
create kuadrant cluster locally with kind
Check istio config does not have any kuadrant's external authorizer. For that, the
istiocontrolplane
named IstioOperator CR is checked:The result should be empty.
Create empty Kuadrant CR object
Check istio config does have kuadrant¡s external authorizer. For that, the
istiocontrolplane
named IstioOperator CR is checked:Delete the kuadrant CR
Check istio config does no longer have any kuadrant's external authorizer. For that, the
istiocontrolplane
named IstioOperator CR is checked:The result should be empty (or empty array)