-
Notifications
You must be signed in to change notification settings - Fork 386
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
Resource exporter/importer and unit test #3024
Resource exporter/importer and unit test #3024
Conversation
7b380a2
to
646bf65
Compare
eef025e
to
adc61a8
Compare
b61b082
to
be4ab6e
Compare
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.
A general question - why we need to label the exported service? Could not we just identify the Services based on ServiceExport?
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
type fakeRemoteCluster struct { |
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.
Please add comments to indicate this is for unit tests.
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
"antrea.io/antrea/multicluster/controllers/multicluster/internal" | ||
) | ||
|
||
// we should only have one remote leader cluster for demo purpose |
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.
Nit: we -> We
only have -> have only
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.
Why we have "demo" in the comments? If it is a temporary status, say "temporarily" or "at this moment", etc.
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
|
||
// we should only have one remote leader cluster for demo purpose | ||
// so check and return the first remote cluster. | ||
func getRemoteCluster(remoteMgr *internal.RemoteClusterManager) (internal.RemoteCluster, 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.
I feel not necessary to add a separate file for this func. Can we move it to service_controller.go?
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.
sure, both service_controller.go and serviceexport_controller.go will call it, so I move it into utils.go. let me it move back.
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
import "k8s.io/apimachinery/pkg/types" | ||
|
||
const ( | ||
AntreaMcsLabel = "antrea.io/multi-cluster" |
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 we follow our convention to use upper cases for abbrs, then "Mcs" should be "MCS".
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.
Why we use label but not annotation?
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.
the main reason is there is no annotation selector, so I use label.
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.
Sorry, how we use label selectors?
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 use labelselector to filter resource export in resourceexport_controller.go, eg https://github.com/antrea-io/antrea/pull/3024/files#diff-4a5af6131176d9b4bd232b0185161872343c0f501be3f061e07a555cc3b2dcb8R168
and
https://github.com/antrea-io/antrea/pull/3024/files#diff-4a5af6131176d9b4bd232b0185161872343c0f501be3f061e07a555cc3b2dcb8R318 etc. I feel in some cases we can use annotation, and some other cases we need label so we can use label selector. for service controller part, I will check if possible to use annotation instead.
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 feel ideally we should not add labels in user created resources. It is redundant data, and more importantly we cannot prevent users from removing the labels. If example, they can just apply a yaml to update an existing Services and that will remove labels added by us.
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.
indeed, that make sense, thanks to point out, I will check how to achieve the same feature in a different way.
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.
hi @jianjuns I updated it with an annotation instead of a label, the main purpose of this info is to reduce the service/endpoint update events and watch those exported resource event only https://github.com/antrea-io/antrea/pull/3024/files#diff-1e1d6e2558b5bb86a952c580e877a8a072c499a0c278194afb4d0948ae459d10R407-R443, we can skip adding any annotation and watch all services/endpoints, but I feel it will be a big effort to handle unnecessary services/endpoints change in ServiceExport reconciler. let me know what's your thought. thanks.
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.
But annotation is the same as label that can be removed by users (sorry if my previous comments are not clear). I feel watching all Services and Endpoints is ok, as it is just by one controller in the cluster. AntreaProxy watches all Services and Endpoints in all hosts.
Separator = '/' | ||
) | ||
|
||
// TODO: Use NamespacedName stringer method instead of this. eg nsName.String() |
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.
. eg -> , e.g.
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
|
||
// GetNamespacedName returns the objects name as NamespacedName struct. | ||
func GetNamespacedName(namespace, name string) types.NamespacedName { | ||
return types.NamespacedName{ |
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.
Do we need a func for this?
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.
yes, it help us to build up a new types.NamespacedName with given strings, not from K8s object directly, so we construct it by ourself, mainly purpose is to avoid duplicate codes, only remote_resourceimport_controller.go use it for now, let me move it from helper to remote_resourceimport_controller.go
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.
But types.NamespacedName{namespace, name} is very simple and just one line.
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.
yeah, we can use types.NamespacedName{namespace, name} but it will give us a warning about k8s.io/apimachinery/pkg/types.NamespacedName composite literal uses unkeyed fieldscomposites
, so I feel it's a little bit long to have both key and name.
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.
let me change it back to struct directly, so we have less function
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
} | ||
} | ||
|
||
func GetPointer(str string) *string { |
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.
Why we need a func?
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.
there are a few fields requires string pointer,https://github.com/antrea-io/antrea/pull/3024/files#diff-1e1d6e2558b5bb86a952c580e877a8a072c499a0c278194afb4d0948ae459d10R362-R371, I added this to avoid define a string and get its pointer repeatedly, but looks like only serviceexporter_controller.go use this function, I will move it and name it as getPointer
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
multicluster/controllers/multicluster/resourceexport_controller.go
Outdated
Show resolved
Hide resolved
Codecov Report
@@ Coverage Diff @@
## feature/multi-cluster #3024 +/- ##
=========================================================
+ Coverage 39.76% 40.92% +1.15%
=========================================================
Files 189 188 -1
Lines 21880 22568 +688
=========================================================
+ Hits 8701 9236 +535
- Misses 12324 12392 +68
- Partials 855 940 +85
Flags with carried forward coverage won't be shown. Click here to find out more.
|
be5de9c
to
479dfc3
Compare
metadata: | ||
name: serviceexports.multicluster.x-k8s.io | ||
spec: | ||
group: multicluster.x-k8s.io |
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.
Hi @jianjuns , I am wondering if it's OK to copy serviceexports CRD definition from mcs api repo? or we should move it as own one API group? if we move it to our own group, I think we need to define ServiceExport and ServiceImport objects.
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 feel ok to copy the yaml. Let us see if @tnqn has an opinion.
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.
Is it possible to put these copied yamls in a separate directory?
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.
Reminder for the question.
Is it possible to put these copied yamls in a separate directory?
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.
yes, I was thinking to move it in a separate PR when we rename the core
package.
AntreaMcsLabel = "antrea.io/multi-cluster" | ||
AntreaMcsAutoGenLabel = "antrea.io/multi-cluster-autogenerated" | ||
SourceImportLabel = "antrea.io/resource-import-name" | ||
AntreaMCSAutoGenAnnotation = "antrea.io/multi-cluster-autogenerated" |
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.
What you think about "multicluster.antrea.io/imported-service" and "multicluster.antrea.io/resource-import-name"?
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.
ok, will do.
@@ -209,7 +209,7 @@ func (r *ResourceImportReconciler) handleResImpUpdateForEndpoints(ctx context.Co | |||
r.installedResImports.Add(*resImp) | |||
return ctrl.Result{}, nil | |||
} | |||
if _, ok := ep.Labels[common.AntreaMcsAutoGenLabel]; !ok { | |||
if _, ok := ep.Labels[common.AntreaMCSAutoGenAnnotation]; !ok { |
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.
Have you done the change to switch from label to annotation, and remove the "multi-cluster" label on exported Services?
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.
yes, @jianjuns , this is a multi-cluster service created by our own codes, so I suppose it should be ok to add a label?
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.
That is ok, but I think you plan to change from label to annotation?
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 you like to use label selector for imported services? But you changed the constant name to AntreaMCSAutoGenAnnotation
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.
yeah, my mistake, I think both label or annotation should work, I will check and move it as annotation if it can filter event based on annotation.
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.
Do you watch with filters? I remember watch can have the apiserver side filter the updates with labels. Not sure about annotation.
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.
yes, there is a standalone service_controller.go to do clean up job in case ResourceImport in leader have been removed but member cluster fail to watch the event eg: mcs controller is down accidentally.
controller-runtime provides a predicate to do the filter. I used it like below in service_controller.go, I think annotation should also work with custom predicate funcs, I will try locally first.
func (r *ServiceReconciler) SetupWithManager(mgr ctrl.Manager) error {
instance, _ := predicate.LabelSelectorPredicate(metav1.LabelSelector{
MatchLabels: map[string]string{
common.AntreaMCSAutoGenAnnotation: "true",
},
})
return ctrl.NewControllerManagedBy(mgr).
For(&corev1.Service{}).WithEventFilter(instance).
WithOptions(controller.Options{
MaxConcurrentReconciles: common.DefaultWorkerCount,
}).
Complete(r)
}
9b32acf
to
f55dbad
Compare
99a9737
to
839a110
Compare
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 commit message:
remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding
create -> creates
@@ -88,6 +93,11 @@ func run(o *Options) error { | |||
} else { | |||
o.options.CertDir = certDir | |||
} | |||
// TODO: These leader checks should go once we have a separate command for leader and member controller | |||
if o.leader { | |||
// on the leader we want the reconciler to run for a given namspace instead of cluster scope |
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.
namesapce -> Namespace
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.
sure, there are some codes from Aravinda's common area, I will leave it to her to address, then I will do a rebase after that. cc @aravindakidambi
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.
Sure, Ill address this
// TODO: These leader checks should go once we have a separate command for leader and member controller | ||
if o.leader { | ||
// on the leader we want the reconciler to run for a given namspace instead of cluster scope | ||
o.options.Namespace = env.GetPodNamespace() |
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.
Question - what will happen if a cluster is both leader and member?
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 provide Namespace based manifests for leader and member, which mean a cluster can run MCS controller both as leader and member at the same time in different Namespace.
setupLog = ctrl.Log.WithName("setup") | ||
validationWebhooks = []string{"antrea-multicluster-validating-webhook-configuration"} | ||
mutationWebhooks = []string{"antrea-multicluster-mutating-webhook-configuration"} | ||
setupLog = ctrl.Log.WithName("setup") |
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.
@tnqn once asked about using klog. What is the conclusion for that?
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.
sure,we will remove this one @aravindakidambi
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.
Ok, done.
IsMember: o.member, | ||
} | ||
if err = clusterSetReconciler.SetupWithManager(mgr); err != nil { | ||
setupLog.Error(err, "unable to create controller", "controller", "ClusterSet") |
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 typically do not long if we return the error (which will be logged by the caller too). Could you check if the error logs are necessary?
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.
Sure, will remove them
@@ -202,17 +238,32 @@ func createClients(kubeConfig *rest.Config) ( | |||
return client, aggregatorClient, apiExtensionClient, nil | |||
} | |||
|
|||
func getCAConifg() *certificate.CAConfig { | |||
func getCAConifg(isLeader bool) *certificate.CAConfig { |
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 feel it might be better not to call env.GetPodNamespace() everywhere, and so wonder can we call it once in run(), and pass it as a parameter to getCAConfig() and getValidationWebhooks() rather than passing isLeader. No strong opinion. Just for you to consider.
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.
Sure, done.
creationSucceed = true | ||
} | ||
|
||
if creationSucceed { |
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 Service is created in this func, but ServiceImport was created earlier, we should return here too, and not check changes?
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.
fixed
// Update MCS logic here | ||
if _, ok := svc.Annotations[common.AntreaMCServiceAnnotation]; !ok { | ||
klog.InfoS("Service has no desired annotation "+common.AntreaMCServiceAnnotation+", skip update", "service", svcName.String()) | ||
return ctrl.Result{}, nil |
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 is when users manually created a Service with MCS prefix, or they removed the annotation on an imported Service? Should we return an error and retry for either case?
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.
sure, I will check this.
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 add a step to check conflicts and skip creation if there is the same Service with MCS prefix, are you suggesting that we should always return error if this is a service with MCS prefix but no annotation, so admin can correct it manually?
klog.ErrorS(err, "fail to list ResourceExports, retry later") | ||
return newResImport, false, err | ||
} | ||
// when there is only one Service ResourceExport, ResourceImport should reflect the change |
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.
How MCSAPI handles this?
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.
they didn't handle this case, MCSAPI repo only create a sample for Service creation.
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.
What you think we return an error and let controller retry (until conflict is resolved)?
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 think this kind conflict can only be handled manually, do you mean this kind of situation should be corrected by admin when they do service export, so we can let controller retry after admin resolve conflict?
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, I leave the logic to update ResourceImport when there is only one ResourceExport and for other cases, it will return error. let me know if it's suitable or not.
switch resExport.Spec.Kind { | ||
case common.ServiceKind: | ||
resImport, changed, err = r.refreshServiceResourceImport(&resExport, existResImport, createResImport) | ||
case common.EndpointsKind: |
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.
Today we support exporting only the Endpoints directly, but not externalIP of LB type Services? When later we use externalIP or ClusterIP as the Endpoints, ResourceExportReconciler in the leader cluster should create EndpointImport based on the exported Service spec, or ResourceImportReconciler of member clusters should handle that?
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 think ResourceExportReconciler should do this part, I will revisit this later how to minimize the change. thanks.
e76b682
to
dff1449
Compare
@@ -40,12 +42,12 @@ import ( | |||
|
|||
const ( | |||
// cached indexer | |||
resImportIndexerByNameKind = "resourceimport.by.namekind" | |||
resImportIndexer = "resimp.indexer" |
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.
Nit - what you think about "name.kind" or even "nk".
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, rename indexer as name.kind
r.installedResImports.Add(*resImp) | ||
if len(svcImpObj.Spec.IPs) == 0 { | ||
// requeue the event to update ServiceImport's ClusterSetIP | ||
return ctrl.Result{}, fmt.Errorf("ServiceImport %s ClusterSetIP is empty", klog.KObj(svcImpObj)) |
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.
Humm - how long it takes for the retry? Thinking whether we should optimize by watching Services to get the IP faster but I know it is much complexer.
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 checked the codes, it seems using the default rate limit here https://github.com/kubernetes/client-go/blob/master/util/workqueue/default_rate_limiters.go#L39, interval should be from 5ms to 10s. if multiple failures happened, the interval will be like baseDelay*2^<num-failures>
, baseDelay
is 5ms, not sure if this kind of interval is enough or not, I will check if I can add more logic in service_controller to watch Service change, then update the IP
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 am still trying to understand if we need a Service controller or not. If not, could we think about a simpler solution to handle this, like some way to requeue the event after a short interval?
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.
service controller only watch those service with mcs annotation, so I suppose it should be OK to have one? I haven't found a valid new way to handle the case when ResourceImport is deleted but event is not handled because of crashed controller in member cluster. I will check if reconciler can run like RunOnce().
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.
@jianjuns about requeue for ClusterSetIP setting, when we return empty result with error, the event will actually be requeued, do you mean the interval controlled by default rate limit is not short enough?
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 it is always ms to seconds, that should be good enough.
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.
@jianjuns I removed service_controller and add a standard controller named stale_controller without using kuberbuilder manager framework, it will run only once if no error happens during stale Service/ServiceImport clean up. no unit test code yet, let me know if you have more comments. thanks.
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 think better to get @tnqn 's suggestion here. Could you check with him?
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.
sure, I have pinged him directly, let's see if there is comment from @tnqn
@@ -160,25 +174,27 @@ func (r *ResourceImportReconciler) handleResImpUpdateForService(ctx context.Cont | |||
return ctrl.Result{}, err | |||
} | |||
svcImpObj := getMCServiceImport(resImp) | |||
if !reflect.DeepEqual(*svc, corev1.Service{}) { |
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.
Should we just check svc.Spec.ClusterIP?
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
} | ||
|
||
if creationSucceed { | ||
if svcCreated && svcImpCreated { |
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.
Should we check both, or just svcImpCreated? At least for r.installedResImports.Add(*resImp) we should not care about svcCreated?
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.
fix via check svcImpNotFound
only
@@ -143,15 +145,27 @@ func (r *ResourceImportReconciler) handleResImpUpdateForService(ctx context.Cont | |||
if err != nil && !apierrors.IsNotFound(err) { | |||
return ctrl.Result{}, err | |||
} | |||
var creationSucceed bool | |||
mcsObj := getMCSForServiceImport(resImp) | |||
if !reflect.DeepEqual(*svc, corev1.Service{}) { |
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.
Is it to check if the Service exists or not? If so should we just check IsNotFound, or add a bool variable for that (which can replace svcCreated, svcImpCreated).
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 via using svcImpNotFound
@@ -247,6 +263,13 @@ func (r *ResourceImportReconciler) handleResImpUpdateForEndpoints(ctx context.Co | |||
if err != nil && !epNotFound { | |||
return ctrl.Result{}, err | |||
} | |||
if !reflect.DeepEqual(*ep, corev1.Endpoints{}) { |
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.
Just check the Endpoints exists or not?
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.
yes, reuse epNotFound
now
// when there is only one Service ResourceExport, ResourceImport should reflect the change | ||
// otherwise, it should skip it due to it's impossible to determine which one is desired. | ||
// When there is only one Service ResourceExport, ResourceImport should reflect the change | ||
// otherwise, it should always return error so controller can retry later if admin fix the issue |
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.
How about "assuming users can fix the conflicts"?
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
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 the commit message of "More stale cleanup and remove unnecessary subset info"
- add ResourceExport clean up in stale_controller which handle the case
add -> Add, handle -> handles
when controller in member crashed and ServiceExport is deleted during
crash.
crached -> restarts?
multicluster/controllers/multicluster/core/resourceimport_controller.go
Outdated
Show resolved
Hide resolved
multicluster/controllers/multicluster/core/resourceimport_controller.go
Outdated
Show resolved
Hide resolved
klog.InfoS("Starting StaleController") | ||
defer klog.InfoS("Shutting down StaleController") | ||
|
||
if err := c.RunOnce(); err != nil { |
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.
But we should do clean up before other controllers start to run, no?
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 only clean up those stale resources, eg, remove MC Service and ServiceImport when corresponding ResourceImport does not existing in leader cluster anymore, so it should be fine to no run before other controllers because other controllers will do nothing for a deleted resource which is already gone before reconciling and no delete event at all.
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 am thinking about any possible race condition here, e.g. stalecontroller (as it is not atomic to get imports, services, and delete) deletes new Services?
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.
stale controller will get ServiceList from local first, then ResourceImportList from leader, so it means if new derived Service being created but not in ServiceList, we either have new ResourceImport in ResourceImportList or not have it, in first case Service won't be deleted because there is corresponding ResourceImport, in second case, nothing will be done.
8aebad0
to
c86cf1a
Compare
0810d08
to
55254ac
Compare
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.
Mostly on formatting.
@@ -1079,6 +1079,217 @@ status: | |||
conditions: [] |
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 feel we should rename this yml to antrea-multicluster-member.yml. Not necessarily in this PR 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.
Sure, I think we can do this rename and move copied yaml to different directory in a new PR.
metadata: | ||
name: serviceexports.multicluster.x-k8s.io | ||
spec: | ||
group: multicluster.x-k8s.io |
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.
Is it possible to put these copied yamls in a separate directory?
multicluster/controllers/multicluster/core/resourceimport_controller.go
Outdated
Show resolved
Hide resolved
multicluster/controllers/multicluster/serviceexport_controller.go
Outdated
Show resolved
Hide resolved
multicluster/controllers/multicluster/serviceexport_controller.go
Outdated
Show resolved
Hide resolved
multicluster/controllers/multicluster/serviceexport_controller.go
Outdated
Show resolved
Hide resolved
multicluster/controllers/multicluster/serviceexport_controller.go
Outdated
Show resolved
Hide resolved
multicluster/controllers/multicluster/serviceexport_controller.go
Outdated
Show resolved
Hide resolved
d450c75
to
e6ff1e9
Compare
} | ||
if !svcNotFound { | ||
// Here we will skip creating derived MC Service when a Service with the same name | ||
// is already exists but not previously created by Importer. |
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.
is already exists -> already exists but is not
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
metadata: | ||
name: serviceexports.multicluster.x-k8s.io | ||
spec: | ||
group: multicluster.x-k8s.io |
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.
Reminder for the question.
Is it possible to put these copied yamls in a separate directory?
"service", svcImpName.String(), "resourceimport", klog.KObj(resImp)) | ||
|
||
var err error | ||
cleanup_serviceimport := func() (ctrl.Result, 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.
cleanupServiceImport
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
@@ -99,7 +99,7 @@ func (r *MemberClusterSetReconciler) SetupWithManager(mgr ctrl.Manager) error { | |||
return ctrl.NewControllerManagedBy(mgr). |
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 feel common_area.go in commonarea pkg is not a problem. But would let you decide the appropriate naming here. "core" might be too general and not accurate here.
client.Client | ||
Scheme *runtime.Scheme | ||
type ( | ||
// ResourceExportReconciler reconciles a ResourceExport object |
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.
Ah, probably we can move the comment here, like "ResourceExportReconciler reconciles ResourceExports in leader cluster"?
|
||
func (r *ResourceExportReconciler) handleDeleteEvent(ctx context.Context, resImportName types.NamespacedName, resExport *mcsv1alpha1.ResourceExport) error { | ||
reList := &mcsv1alpha1.ResourceExportList{} | ||
err := r.Client.List(ctx, reList, &client.ListOptions{LabelSelector: getLabelSelector(resExport)}) |
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.
Ok, thought we can just remove endpoints from the ResourceImport. Not sure that is a better strategy or not.
But could you add some comments?
return ctrl.Result{}, err | ||
} | ||
|
||
resImportName := types.NamespacedName{ |
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.
Minor suggestion - might be simpler if getResourceImportName() returns a NamespacedName.
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.
good point, refined it.
) | ||
|
||
var ( | ||
leaderNamespace string |
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 do not mean we must create a new struct to hold these variables, but meant for OO better not to use global variables. I saw you change to pass clusterConfig as func arguments, but originally I was thinking can they be members of ServiceExportReconciler.
multicluster/controllers/multicluster/serviceexport_controller.go
Outdated
Show resolved
Hide resolved
) | ||
|
||
// TODO: Use NamespacedName stringer method instead of this. e.g. nsName.String() | ||
func NamespacedName(namespace, name string) string { |
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.
namespace -> Namespace
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
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.
Sorry, this one is my mistake. It should be "namespace" indeed.
e6ff1e9
to
faafaf9
Compare
Hi @jianjuns @aravindakidambi I have created a separate PR #3153 to rename |
faafaf9
to
b03f63a
Compare
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.
) | ||
|
||
// TODO: Use NamespacedName stringer method instead of this. e.g. nsName.String() | ||
func NamespacedName(Namespace, name string) string { |
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.
Sorry, this one is my mistake. It should be "namespace" indeed.
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
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
b03f63a
to
1d33ce2
Compare
Hi @jianjuns I fixed the last comment in this PR, Could you help to approve this if it looks good to you? I will rebase the PR#3153 and address your comments on it. |
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
1. exporter serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via event mapping and update ResourceExport when exported Service/Endpoints are updated. resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports from different member clusters into one ResourceExport in leader cluster if the resources are exported with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind. 2. importer remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix. 3. stale controller stale controller is mainly for special cases when resource is deleted during controller restarting in leader or member cluster, it will be triggered once only when controller starts. Notes: serviceexport_controller, stale_controller and resourceimport_controller will run only in member cluster, resourceexport_controller will run only in leader cluster. Signed-off-by: Lan Luo <[email protected]>
This PR is mainly for resource exporter/importer:
serviceexport_controller is responsible to reconcile ServiceExport resource in member cluster and write
wrapped ResourceExport into leader cluster, meanwhile it will watch Service and Endpoints change via
event mapping and update ResourceExport when exported Service/Endpoints are updated.
resourceexport_controller is responsible to reconcile ResourceExport resources and computes all ResourceExports
from different member clusters into one ResourceExport in leader cluster if the resources are exported
with the same namespaced name and the same kind, for this moment, we only support Service, Endpoints kind.
importer
remote_resourceimport_controller watches leader cluster's ResourceImport events and create corresponding
ServiceImport, Service and Endpoints with AntreaMCServiceAnnotation in member cluster. ServiceImport name will
be the same as exported Service, new created Service and Endpoints will have an antrea multicluster prefix.
stale controller
stale controller is mainly for special cases when resource is deleted during controller restarting
in leader or member cluster, it will be triggered once only when controller starts.
Notes: serviceexport_controller, stale_controller and
resourceimport_controller will run only in member cluster,
resourceexport_controller will run only in leader cluster.
This PR is based on #3111, please kindly review top commit.
Signed-off-by: Lan Luo [email protected]