Skip to content
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

Ensure the ServiceAccount IRSA annotation is in place on each reconciliation loop #87

Closed
wants to merge 3 commits into from

Conversation

diranged
Copy link
Contributor

@diranged diranged commented Aug 3, 2021

close #86

What did I want?

The original code only created the ServiceAccount resource and set the eks.amazonaws.com/role-arn annotation once - at creation time. If that failed for any reason, or became out of date, the controller did not fix it for you. The controllers job should be to constantly ensure that the desired state of the world is correct, including the ServiceAccount link.

What did I do?

A few things.. primarily I added in the "create/update service account" into the handler for state=ready. While I was here, I wanted to introduce some logic to get the current state of the ServiceAccount so that we can make a decision as to whether or not we need to apply a change or not. Finally, in order to do that cleanly, I moved some constants around because there were package import issues.

Why the new constants package?

The original constants were stored in internal/config .. but internal/config/config.go depends on k8s/client.go. That made it impossible to import a constant into the k8s package. I have pulled the true global constants out of the internal/config package and put them into a truly isolated constants package.

Whats up with the EnsureServiceAccount function?

The existing CreateOrUpdateServiceAccount function is good in that it is fairly simple. I wanted to add some logic to prevent making create/update calls if they are unnecessary, and I did not want to introduce that complexity into the existing function.

@diranged
Copy link
Contributor Author

diranged commented Aug 3, 2021

You can see our internal PR at Nextdoor#4 - with some of the comments and discussions we have had. We've been running our own fork based on this code for the last 3-4 weeks now with great success.

@diranged diranged changed the title Fix loop 3 Ensure the ServiceAccount IRSA annotation is in place on each reconciliation loop Aug 3, 2021
@mnkg561
Copy link
Contributor

mnkg561 commented Aug 9, 2021

You can see our internal PR at Nextdoor#4 - with some of the comments and discussions we have had. We've been running our own fork based on this code for the last 3-4 weeks now with great success.

sure. I will check those conversations too. will update in couple of days.

@diranged
Copy link
Contributor Author

diranged commented Sep 7, 2021

@mnkg561 Any update on this? I am digging into a race-condition error in iam.go right now .. but when I fix it, it would be nice to know that this change got landed. We're still using our custom build in our environment and it's been working well (with the exception of a delete race condition)...

Copy link
Contributor

@mnkg561 mnkg561 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My bad- I was busy with other project https://github.com/keikoproj/alert-manager and everytime i tried to do the review i lost track of it since its a big PR.

We should meet up some time to understand more on how you guys are using so we can learn from each other.

And, Thank you for the contribution. I like the way you expanded ServiceAccount methods- neat!!

//oh oh.. This is delete use case
//Lets make sure to clean up the iam role
// oh oh.. This is delete use case
// Lets make sure to clean up the iam role
if iamRole.Status.RetryCount != 0 {
iamRole.Status.RetryCount = iamRole.Status.RetryCount + 1
}
log.Info("Iamrole delete request")
if iamRole.Status.State != iammanagerv1alpha1.PolicyNotAllowed {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are checking for RoleName presence then this line probably NOT required anymore-

IamRoleARN: iamRole.Status.RoleARN,
ServiceAccountName: saName,
}
if _, err := rbac.EnsureServiceAccount(ctx, saRequest); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather want here a comparison instead of "updating" anything- Lets do the comparison here - Like Service account should've had annotation but doesn't then it qualifies for "fall through". Observe we don't do any "updates" here in this section rather just compare it and do the updates in "default" section

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also- its a duplicate code here and default section

shouldManageSa, saName := utils.ParseIRSAAnnotation(ctx, iamRole)

// Get a RBAC object we can use to modify the ServiceAccount if we need to.
rbac, err := k8s.NewK8sClient()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably shouldn't do this since there are users who doesn't use IRSA and getting the client at the front doesn't like a good idea. We should get the client only if it is needed- For example: If shouldManageSa -> get the reusable client so you can use it to get the service account for the comparison and update the service account at the end if needed

currentVal, _ := sa.Annotations[constants.ServiceAccountRoleAnnotation]

// Does it match? If so, we're done here. Return.
if currentVal == req.IamRoleARN {
Copy link
Contributor

@mnkg561 mnkg561 Sep 7, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are you guys using IRSA? Can you have multiple iam roles per namespace?
Scenario:

  1. IamRole1 created with IRSA annotation serviceaccount -> sa-namespace
  2. Pods with sa-namespace now have IamRole1 access
  3. IamRole2 create with IRSA annotation with same service account name sa-namespace
  4. This code will overwrite with IamRole2 and pods in step2 will lose the access to IamRole1

Our use case is one iam role per namespace so we probably wound't run into this issue but we have to think more here than just updating with new iam role ARN. (Thinking out loud) We either have to decline iamrole creation request stating that Service account is already associated with other iam role. Let me know if you have any ideas?

r.Recorder.Event(&iamRole, v1.EventTypeWarning, string(iammanagerv1alpha1.Error), "unable to delete the role due to "+err.Error())

return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
if roleName != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, That i'm checking more on IRSA- we might have to clean up the service account too to make sure we no longer have "deleted iam role" annotation to the service account

@diranged
Copy link
Contributor Author

@mnkg561 Hey.. I'm circling back here. We've been running this PR in in production for 6+ months and it's pretty good and stable. Do you think you'd be willing to finish whatever is necessary to get it over the hump and merge it in? Or give me some explicit guidelines on what you think needs to be finished?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ServiceAccount resource is not considered as part of the reconciliation loop
2 participants