Skip to content

Commit d4f6dc1

Browse files
author
Akshay Kumar
committed
Merge pull request oracle#376 in OKE/oci-cloud-controller-manager from hotfix/service-controller to release-1.24
* commit '5a10f40efb215df6babbfd43ac45c0aa5ebd13d7': Deduplicating endpoints, simplifying virtual node check
2 parents 7ba71ae + 5a10f40 commit d4f6dc1

File tree

9 files changed

+355
-222
lines changed

9 files changed

+355
-222
lines changed

pkg/cloudprovider/providers/oci/ccm.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ const (
5353
// (OCI) cloud-provider.
5454
providerName = "oci"
5555
providerPrefix = providerName + "://"
56+
57+
// endpointSliceUpdatesBatchPeriod is the duration after which a service
58+
// owning an endpointslice is batched in the Service Controller
59+
endpointSliceUpdatesBatchPeriod = 5*time.Second
5660
)
5761

5862
// ProviderName uniquely identifies the Oracle Bare Metal Cloud Services (OCI)
@@ -279,7 +283,7 @@ func startOciServiceController(ctx context.Context, initContext cloudControllerM
279283
completedConfig.SharedInformers.Core().V1().Nodes(),
280284
completedConfig.SharedInformers.Discovery().V1().EndpointSlices(),
281285
completedConfig.ComponentConfig.KubeCloudShared.ClusterName,
282-
5*time.Second,
286+
endpointSliceUpdatesBatchPeriod,
283287
utilfeature.DefaultFeatureGate,
284288
)
285289
if err != nil {

pkg/cloudprovider/providers/oci/instances_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ var (
305305
Conditions: v1discovery.EndpointConditions{
306306
Ready: &ready,
307307
},
308+
Addresses: []string{"0.0.0.9"},
308309
},
309310
{
310311
TargetRef: &v1.ObjectReference{
@@ -314,6 +315,7 @@ var (
314315
Conditions: v1discovery.EndpointConditions{
315316
Ready: &ready,
316317
},
318+
Addresses: []string{"0.0.0.10"},
317319
},
318320
},
319321
},
@@ -332,6 +334,7 @@ var (
332334
Conditions: v1discovery.EndpointConditions{
333335
Ready: &ready,
334336
},
337+
Addresses: []string{"0.0.0.19"},
335338
},
336339
{
337340
TargetRef: &v1.ObjectReference{
@@ -341,6 +344,7 @@ var (
341344
Conditions: v1discovery.EndpointConditions{
342345
Ready: &ready,
343346
},
347+
Addresses: []string{"0.0.0.20"},
344348
},
345349
},
346350
},
@@ -360,6 +364,7 @@ var (
360364
Conditions: v1discovery.EndpointConditions{
361365
Ready: &ready,
362366
},
367+
Addresses: []string{"0.0.0.9"},
363368
},
364369
{
365370
TargetRef: &v1.ObjectReference{
@@ -369,6 +374,7 @@ var (
369374
Conditions: v1discovery.EndpointConditions{
370375
Ready: &ready,
371376
},
377+
Addresses: []string{"0.0.0.19"},
372378
},
373379
{
374380
TargetRef: &v1.ObjectReference{
@@ -378,6 +384,7 @@ var (
378384
Conditions: v1discovery.EndpointConditions{
379385
Ready: &ready,
380386
},
387+
Addresses: []string{"0.0.0.10"},
381388
},
382389
{
383390
TargetRef: &v1.ObjectReference{
@@ -387,6 +394,7 @@ var (
387394
Conditions: v1discovery.EndpointConditions{
388395
Ready: &ready,
389396
},
397+
Addresses: []string{"0.0.0.20"},
390398
},
391399
},
392400
},
@@ -405,6 +413,65 @@ var (
405413
Conditions: v1discovery.EndpointConditions{
406414
Ready: &ready,
407415
},
416+
Addresses: []string{"0.0.0.100"},
417+
},
418+
},
419+
},
420+
"endpointSliceDuplicate1.1": {
421+
ObjectMeta: metav1.ObjectMeta{
422+
Labels: map[string]string{
423+
v1discovery.LabelServiceName: "duplicateEndpointsService",
424+
},
425+
},
426+
Endpoints: []v1discovery.Endpoint{
427+
{
428+
TargetRef: &v1.ObjectReference{
429+
Kind: "Pod",
430+
Name: "virtualPod1",
431+
},
432+
Conditions: v1discovery.EndpointConditions{
433+
Ready: &ready,
434+
},
435+
Addresses: []string{"0.0.0.10"},
436+
},
437+
{
438+
TargetRef: &v1.ObjectReference{
439+
Kind: "Pod",
440+
Name: "virtualPod2",
441+
},
442+
Conditions: v1discovery.EndpointConditions{
443+
Ready: &ready,
444+
},
445+
Addresses: []string{"0.0.0.9"},
446+
},
447+
},
448+
},
449+
"endpointSliceDuplicate1.2": {
450+
ObjectMeta: metav1.ObjectMeta{
451+
Labels: map[string]string{
452+
v1discovery.LabelServiceName: "duplicateEndpointsService",
453+
},
454+
},
455+
Endpoints: []v1discovery.Endpoint{
456+
{
457+
TargetRef: &v1.ObjectReference{
458+
Kind: "Pod",
459+
Name: "virtualPod2",
460+
},
461+
Conditions: v1discovery.EndpointConditions{
462+
Ready: &ready,
463+
},
464+
Addresses: []string{"0.0.0.9"},
465+
},
466+
{
467+
TargetRef: &v1.ObjectReference{
468+
Kind: "Pod",
469+
Name: "virtualPod1",
470+
},
471+
Conditions: v1discovery.EndpointConditions{
472+
Ready: &ready,
473+
},
474+
Addresses: []string{"0.0.0.10"},
408475
},
409476
},
410477
},

pkg/cloudprovider/providers/oci/load_balancer.go

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"go.uber.org/zap"
2323
v1 "k8s.io/api/core/v1"
2424
discovery "k8s.io/api/discovery/v1"
25+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2526
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2627
"k8s.io/apimachinery/pkg/labels"
2728
"k8s.io/apimachinery/pkg/util/sets"
@@ -374,31 +375,23 @@ func getNodeFilter(svc *v1.Service) (labels.Selector, error) {
374375
return labels.Parse(labelSelector)
375376
}
376377

377-
// filterNodes - Separates provisioned nodes based on the label selector,
378-
// that should be backends in the load balancer, and virtual nodes.
379-
func filterNodes(logger *zap.SugaredLogger, svc *v1.Service, nodes []*v1.Node) ([]*v1.Node, []*v1.Node, error) {
378+
// filterNodes based on the label selector, if present, and returns the set of nodes
379+
// that should be backends in the load balancer.
380+
func filterNodes(svc *v1.Service, nodes []*v1.Node) ([]*v1.Node, error) {
380381

381382
selector, err := getNodeFilter(svc)
382383
if err != nil {
383-
return nil, nil, err
384+
return nil, err
384385
}
385386

386-
var provisionedNodes, virtualNodes []*v1.Node
387+
var filteredNodes []*v1.Node
387388
for _, n := range nodes {
388-
// Since virtual nodes should not be added as backends,
389-
// labels are not checked
390-
isVirtualNode, err := IsVirtualNode(n)
391-
if err != nil {
392-
logger.With(zap.Error(err)).Errorf("Failed to check if node is virtual: %s", n.Name)
393-
}
394-
if isVirtualNode {
395-
virtualNodes = append(virtualNodes, n)
396-
} else if selector.Matches(labels.Set(n.GetLabels())) {
397-
provisionedNodes = append(provisionedNodes, n)
389+
if selector.Matches(labels.Set(n.GetLabels())) {
390+
filteredNodes = append(filteredNodes, n)
398391
}
399392
}
400393

401-
return provisionedNodes, virtualNodes, nil
394+
return filteredNodes, nil
402395
}
403396

404397
// EnsureLoadBalancer creates a new load balancer or updates the existing one.
@@ -409,22 +402,17 @@ func (cp *CloudProvider) EnsureLoadBalancer(ctx context.Context, clusterName str
409402
loadBalancerType := getLoadBalancerType(service)
410403
logger := cp.logger.With("loadBalancerName", lbName, "serviceName", service.Name, "loadBalancerType", loadBalancerType)
411404

412-
// Ideally virtual nodes will be excluded since they will have the LabelNodeExcludeBalancers set on them,
413-
// However, the user could delete the label, so we need to filter out virtual nodes here
414-
provisionedNodes, virtualNodes, err := filterNodes(logger, service, nodes)
405+
nodes, err := filterNodes(service, nodes)
415406
if err != nil {
416407
logger.With(zap.Error(err)).Error("Failed to filter provisioned nodes with label selector and virtual nodes")
417408
return nil, err
418409
}
419410

420-
virtualNodeExists := len(virtualNodes) > 0
421-
if !virtualNodeExists {
422-
// Check if virtual nodes exist in the cluster
423-
virtualNodeExists, err = cp.virtualNodeExists(logger)
424-
if err != nil {
425-
logger.With(zap.Error(err)).Error("Failed to check if cluster has virtual nodes")
426-
return nil, errors.Wrap(err, "failed to check if cluster has virtual nodes")
427-
}
411+
// Check if virtual nodes exist in the cluster
412+
virtualNodeExists, err := VirtualNodeExists(cp.NodeLister)
413+
if err != nil {
414+
logger.With(zap.Error(err)).Error("Failed to check if cluster has virtual nodes")
415+
return nil, errors.Wrap(err, "failed to check if cluster has virtual nodes")
428416
}
429417

430418
var virtualPods []*v1.Pod
@@ -437,7 +425,7 @@ func (cp *CloudProvider) EnsureLoadBalancer(ctx context.Context, clusterName str
437425
}
438426
}
439427

440-
logger.With("provisioned nodes", len(provisionedNodes), "virtual pods", len(virtualPods)).Info("Ensuring load balancer")
428+
logger.With("provisioned nodes", len(nodes), "virtual pods", len(virtualPods)).Info("Ensuring load balancer")
441429

442430
dimensionsMap := make(map[string]string)
443431

@@ -493,7 +481,7 @@ func (cp *CloudProvider) EnsureLoadBalancer(ctx context.Context, clusterName str
493481
return nil, err
494482
}
495483

496-
spec, err := NewLBSpec(logger, service, provisionedNodes, virtualPods, subnets, sslConfig, cp.securityListManagerFactory, cp.config.Tags)
484+
spec, err := NewLBSpec(logger, service, nodes, virtualPods, subnets, sslConfig, cp.securityListManagerFactory, cp.config.Tags)
497485
if err != nil {
498486
logger.With(zap.Error(err)).Error("Failed to derive LBSpec")
499487
errorType = util.GetError(err)
@@ -549,7 +537,8 @@ func (cp *CloudProvider) EnsureLoadBalancer(ctx context.Context, clusterName str
549537
}
550538
}
551539

552-
if len(provisionedNodes) == 0 && !virtualNodeExists {
540+
// TODO: Revisit this condition when clusters with mixed node pools are introduced, possibly add len(virtualPods) == 0 check
541+
if len(nodes) == 0 && !virtualNodeExists {
553542
allNodesNotReady, err := cp.checkAllBackendNodesNotReady()
554543
if err != nil {
555544
logger.With(zap.Error(err)).Error("Failed to check if all backend nodes are not ready")
@@ -884,7 +873,7 @@ func (cp *CloudProvider) UpdateLoadBalancer(ctx context.Context, clusterName str
884873
}
885874

886875
// getNodesAndPodsByIPs returns slices of Nodes and Pods corresponding to the given IP addresses.
887-
func (cp *CloudProvider) getNodesAndPodsByIPs(ctx context.Context, logger *zap.SugaredLogger, backendIPs []string, service *v1.Service) ([]*v1.Node, []*v1.Pod, error) {
876+
func (cp *CloudProvider) getNodesAndPodsByIPs(ctx context.Context, backendIPs []string, service *v1.Service) ([]*v1.Node, []*v1.Pod, error) {
888877
ipToPodLookup := make(map[string]*v1.Pod)
889878
ipToNodeLookup := make(map[string]*v1.Node)
890879

@@ -895,11 +884,7 @@ func (cp *CloudProvider) getNodesAndPodsByIPs(ctx context.Context, logger *zap.S
895884

896885
var virtualNodeExists bool
897886
for _, node := range nodeList {
898-
isVirtualNode, err := IsVirtualNode(node)
899-
if err != nil {
900-
logger.With(zap.Error(err)).Errorf("Failed to check if node is virtual: %s", node.Name)
901-
}
902-
if isVirtualNode {
887+
if IsVirtualNode(node) {
903888
virtualNodeExists = true
904889
continue
905890
}
@@ -925,7 +910,7 @@ func (cp *CloudProvider) getNodesAndPodsByIPs(ctx context.Context, logger *zap.S
925910
if node, nodeExists := ipToNodeLookup[ip]; nodeExists {
926911
nodes = append(nodes, node)
927912
} else if pod, podExists := ipToPodLookup[ip]; virtualNodeExists && podExists {
928-
pods = append(pods, pod)
913+
pods = append(pods, pod)
929914
} else {
930915
return nil, nil, errors.Errorf("provisioned node or virtual pod was not found by IP %q", ip)
931916
}
@@ -1021,7 +1006,7 @@ func (cp *CloudProvider) cleanupSecListForLoadBalancerDelete(lb *client.GenericL
10211006
ipSet.Insert(*backend.IpAddress)
10221007
}
10231008
}
1024-
nodes, _, err := cp.getNodesAndPodsByIPs(ctx, logger, ipSet.List(), service)
1009+
nodes, _, err := cp.getNodesAndPodsByIPs(ctx, ipSet.List(), service)
10251010
if err != nil {
10261011
logger.With(zap.Error(err)).Error("Failed to fetch nodes by internal ips")
10271012
return errors.Wrap(err, "fetching nodes by internal ips")
@@ -1175,48 +1160,45 @@ func (cp *CloudProvider) getVirtualPodsOfService(ctx context.Context, logger *za
11751160
if err != nil {
11761161
return nil, err
11771162
}
1163+
1164+
endpointSet := make(map[string]struct{})
11781165
var virtualPods []*v1.Pod
11791166
for _, es := range endpointSlices {
11801167
for _, e := range es.Endpoints {
11811168
if e.TargetRef.Kind == "Pod" {
1169+
if _, exists := endpointSet[e.Addresses[0]]; exists {
1170+
continue
1171+
}
1172+
11821173
pod, err := cp.kubeclient.CoreV1().Pods(es.Namespace).Get(ctx, e.TargetRef.Name, metav1.GetOptions{})
11831174
if err != nil {
1175+
if apierrors.IsNotFound(err) {
1176+
logger.With(zap.Error(err)).Errorf("Pod object does not exist: %s", e.TargetRef.Name)
1177+
continue
1178+
}
11841179
return nil, err
11851180
}
1181+
11861182
node, err := cp.NodeLister.Get(pod.Spec.NodeName)
11871183
if err != nil {
1184+
if apierrors.IsNotFound(err) {
1185+
logger.With(zap.Error(err)).Errorf("Node object does not exist: %s", pod.Spec.NodeName)
1186+
continue
1187+
}
11881188
return nil, err
11891189
}
1190-
isVirtualNode, err := IsVirtualNode(node)
1191-
if err != nil {
1192-
logger.With(zap.Error(err)).Errorf("Failed to check if node is virtual: %s", node.Name)
1193-
}
1194-
if isVirtualNode {
1190+
1191+
if IsVirtualNode(node) {
11951192
virtualPods = append(virtualPods, pod)
11961193
}
1194+
1195+
endpointSet[e.Addresses[0]] = struct{}{}
11971196
}
11981197
}
11991198
}
12001199
return virtualPods, nil
12011200
}
12021201

1203-
func (cp *CloudProvider) virtualNodeExists(logger *zap.SugaredLogger) (bool, error) {
1204-
nodeList, err := cp.NodeLister.List(labels.Everything())
1205-
if err != nil {
1206-
return false, err
1207-
}
1208-
for _, node := range nodeList {
1209-
isVirtualNode, err := IsVirtualNode(node)
1210-
if err != nil {
1211-
logger.With(zap.Error(err)).Errorf("Failed to check if node is virtual: %s", node.Name)
1212-
}
1213-
if isVirtualNode {
1214-
return true, nil
1215-
}
1216-
}
1217-
return false, nil
1218-
}
1219-
12201202
func (cp *CloudProvider) getEndpointSlicesForService(service *v1.Service) ([]*discovery.EndpointSlice, error) {
12211203
esLabelSelector := labels.Set(map[string]string{
12221204
discovery.LabelServiceName: service.Name,

0 commit comments

Comments
 (0)