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

feat: implement cmpd's PolicyRules #8328

Open
wants to merge 31 commits into
base: main
Choose a base branch
from
Open

Conversation

cjc7373
Copy link
Contributor

@cjc7373 cjc7373 commented Oct 24, 2024

Fixes #8310. Things done in this PR:

  • implements cmpd's PolicyRules
  • changes the semantics of serviceAccountName in cluster and component CR. KB now does not create rbac resources if user has specified a service account.
  • serviceaccount is now within a component's level, with a name of kb-<clusterName>-<compName>.

Addon changes (like update pg addon's cmpd policyRule since we removed kubeblocks-patroni-pod-role) will be addressed in apecloud/kubeblocks-addons#1197.

@github-actions github-actions bot added the size/XL Denotes a PR that changes 500-999 lines. label Oct 24, 2024
@cjc7373 cjc7373 changed the title feature: implement cmpd's PolicyRules feat: implement cmpd's PolicyRules Oct 24, 2024
@apecloud-bot apecloud-bot requested a review from realzyy October 24, 2024 15:05
Copy link

codecov bot commented Oct 25, 2024

Codecov Report

Attention: Patch coverage is 66.50485% with 69 lines in your changes missing coverage. Please review.

Project coverage is 60.30%. Comparing base (c206d0e) to head (9e56c89).

Files with missing lines Patch % Lines
controllers/apps/transformer_component_rbac.go 72.44% 21 Missing and 14 partials ⚠️
controllers/apps/transformer_component_deletion.go 59.61% 14 Missing and 7 partials ⚠️
pkg/controller/factory/builder.go 21.42% 11 Missing ⚠️
controllers/apps/transformer_cluster_deletion.go 50.00% 0 Missing and 1 partial ⚠️
pkg/controller/component/synthesize_component.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8328      +/-   ##
==========================================
+ Coverage   60.04%   60.30%   +0.25%     
==========================================
  Files         376      377       +1     
  Lines       45858    45915      +57     
==========================================
+ Hits        27535    27688     +153     
+ Misses      15739    15621     -118     
- Partials     2584     2606      +22     
Flag Coverage Δ
unittests 60.30% <66.50%> (+0.25%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@cjc7373 cjc7373 marked this pull request as ready for review October 28, 2024 07:30
@cjc7373 cjc7373 requested review from leon-inf, Y-Rookie and a team as code owners October 28, 2024 07:30
@apecloud-bot apecloud-bot added the approved PR Approved Test label Oct 31, 2024
@apecloud-bot apecloud-bot removed the approved PR Approved Test label Nov 14, 2024
@cjc7373
Copy link
Contributor Author

cjc7373 commented Nov 14, 2024

relevant addon PR: apecloud/kubeblocks-addons#1197

// The service account will be bound to a default role named "kubeblocks-cluster-pod-role" which is installed together with KubeBlocks.
// If not specified, KubeBlocks automatically assigns a default ServiceAccount named "kb-{cluster.name}"
// If not specified, KubeBlocks automatically creates a default ServiceAccount named
// "kb-{cluster.name}-{component.name}", bound to a role with rules defined in ComponentDefinition's
Copy link
Contributor

Choose a reason for hiding this comment

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

As a further improvement, components with the same cmp can share a default service account.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So that the rbac provision can be moved to cmpd controller?

Copy link
Contributor Author

@cjc7373 cjc7373 Nov 27, 2024

Choose a reason for hiding this comment

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

I ignored a problem. Cmpd is not namespaced, but serviceaccount/rolebinding is. So that it is not feasible to move rbac provision to cmpd controller. Cmpd controller can watch a component to trigger reconcile. The reconcilation related to rbac may look like this:

  • It lists all components that references the cmpd. Find all the namespaces of them (list 1).
  • It lists all managed rbac resources (serviceaccount/rolebinding/role) using label selector. Find all the namespaces of them (list 2).
  • Create/update rbac resources in list 1.
  • Delete rbac resouces in list 2 but not in list 1.

@github-actions github-actions bot added size/XXL Denotes a PR that changes 1000+ lines. and removed size/XL Denotes a PR that changes 500-999 lines. labels Nov 29, 2024
@cjc7373
Copy link
Contributor Author

cjc7373 commented Nov 29, 2024

After a second thought, rbac provision will remain in component controller.

To share rbac resources among multiple components, these rbac resources will use the component which first creates them as their owner. If the component has been deleted, their owner will be transfered to another component which shares a same cmpd. If no such component can be found, they will be deleted.

Another note: equality.Semantic is used to replace reflect.DeepEqual to avoid the false alarm of something like reflect.DeepEqual([]v1.LocalObjectReference(nil), []v1.LocalObjectReference{})

if serviceAccount == nil {
transCtx.Logger.V(1).Info("buildServiceAccounts returns serviceAccount nil")
if !viper.GetBool(constant.EnableRBACManager) {
transCtx.EventRecorder.Event(transCtx.Cluster, corev1.EventTypeWarning, EventReasonRBACManager, "RBAC manager is disabled")
Copy link
Contributor

Choose a reason for hiding this comment

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

No need to initiate a warning event, logging or a normal event is sufficient.

string(ictrlutil.ErrorTypeNotFound), fmt.Sprintf("ServiceAccount %s is not exist", serviceAccount.Name))
return ictrlutil.NewRequeueError(time.Second, "RBAC manager is disabled, but service account is not exist")
var err error
if serviceAccountName == "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Even if the service account is specified by user, should we consider setting a finalizer to prevent accidental deletion by the user?

return nil
graphCli, _ := transCtx.Client.(model.GraphClient)

if err := cleanOldResource(transCtx, graphCli, dag, synthesizedComp); err != nil {
Copy link
Contributor

@leon-inf leon-inf Dec 3, 2024

Choose a reason for hiding this comment

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

This can be implemented when transitioning old version clusters to version 1.0.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Where is the transitioning code?

Owns(&corev1.ServiceAccount{})
} else {
b.Watches(&rbacv1.RoleBinding{}, handler.EnqueueRequestsFromMapFunc(r.filterComponentResources)).
Watches(&corev1.ServiceAccount{}, handler.EnqueueRequestsFromMapFunc(r.filterComponentResources))
Copy link
Contributor

Choose a reason for hiding this comment

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

How should it be handled when the service account is specified by user?

Copy link
Contributor

Choose a reason for hiding this comment

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

It's not owned by the component controller.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMO a service account specified by user should not be modified by KB, even if it's deleted by user. So kb doesn't need to receive events from these service accounts.

if len(rules) == 0 {
return nil
}
return builder.NewRoleBuilder(synthesizedComp.Namespace, saName).
Copy link
Contributor

Choose a reason for hiding this comment

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

If the role is shared within a cmpd, the name should not use the service account name, as it might be specified by user.

Copy link
Contributor Author

@cjc7373 cjc7373 Dec 4, 2024

Choose a reason for hiding this comment

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

Ok, I'll use cmpd's name as role/rolebinding's name.

return nil
}
return builder.NewRoleBuilder(synthesizedComp.Namespace, saName).
AddLabelsInMap(constant.GetCompLabels(synthesizedComp.ClusterName, synthesizedComp.Name)).
Copy link
Contributor

Choose a reason for hiding this comment

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

And these labels become meaningless because they do not belong to any specific object.

return false, err
}
// if any, transfer ownership to any other component
for _, otherComp := range compList.Items {
Copy link
Contributor

Choose a reason for hiding this comment

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

skip deleting component

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/user-interaction size/XXL Denotes a PR that changes 1000+ lines.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Features] Implement ComponentDefinition's PolicyRules
6 participants