Skip to content

Commit 04381a3

Browse files
authored
Merge pull request #8558 from gvnc/cluster-autoscaler-release-1.30
OCI Cloudprovider feature Backport for 1.30
2 parents d311621 + 905d32e commit 04381a3

File tree

2 files changed

+128
-8
lines changed

2 files changed

+128
-8
lines changed

cluster-autoscaler/cloudprovider/oci/nodepools/oci_manager.go

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const (
4040
nodepoolTags = "nodepoolTags"
4141
min = "min"
4242
max = "max"
43+
minSize = "minSize"
44+
maxSize = "maxSize"
4345
)
4446

4547
var (
@@ -90,6 +92,9 @@ func CreateNodePoolManager(cloudConfigPath string, nodeGroupAutoDiscoveryList []
9092
var err error
9193
var configProvider common.ConfigurationProvider
9294

95+
// enable SDK to look up the IMDS endpoint to figure out the right realmDomain
96+
common.EnableInstanceMetadataServiceLookup()
97+
9398
if os.Getenv(ipconsts.OciUseWorkloadIdentityEnvVar) == "true" {
9499
klog.Info("using workload identity provider")
95100
configProvider, err = auth.OkeWorkloadIdentityConfigurationProvider()
@@ -212,21 +217,34 @@ func autoDiscoverNodeGroups(m *ociManagerImpl, okeClient okeClient, nodeGroup no
212217
if validateNodepoolTags(nodeGroup.tags, nodePoolSummary.FreeformTags, nodePoolSummary.DefinedTags) {
213218
nodepool := &nodePool{}
214219
nodepool.id = *nodePoolSummary.Id
215-
nodepool.minSize = nodeGroup.minSize
216-
nodepool.maxSize = nodeGroup.maxSize
220+
// set minSize-maxSize from nodepool free form tags, or else use nodeGroupAutoDiscovery configuration
221+
nodepool.minSize = getIntFromMap(nodePoolSummary.FreeformTags, minSize, nodeGroup.minSize)
222+
nodepool.maxSize = getIntFromMap(nodePoolSummary.FreeformTags, maxSize, nodeGroup.maxSize)
217223

218224
nodepool.manager = nodeGroup.manager
219225
nodepool.kubeClient = nodeGroup.kubeClient
220226

221227
m.staticNodePools[nodepool.id] = nodepool
222-
klog.V(5).Infof("auto discovered nodepool in compartment : %s , nodepoolid: %s", nodeGroup.compartmentId, nodepool.id)
228+
klog.V(4).Infof("auto discovered nodepool in compartment : %s , nodepoolid: %s ,minSize: %d, maxSize:%d", nodeGroup.compartmentId, nodepool.id, nodepool.minSize, nodepool.maxSize)
223229
} else {
224230
klog.Warningf("nodepool ignored as the tags do not satisfy the requirement : %s , %v, %v", *nodePoolSummary.Id, nodePoolSummary.FreeformTags, nodePoolSummary.DefinedTags)
225231
}
226232
}
227233
return true, nil
228234
}
229235

236+
func getIntFromMap(m map[string]string, key string, defaultValue int) int {
237+
value, ok := m[key]
238+
if !ok {
239+
return defaultValue
240+
}
241+
i, err := strconv.Atoi(value)
242+
if err != nil {
243+
return defaultValue
244+
}
245+
return i
246+
}
247+
230248
func validateNodepoolTags(nodeGroupTags map[string]string, freeFormTags map[string]string, definedTags map[string]map[string]interface{}) bool {
231249
if nodeGroupTags != nil {
232250
for tagKey, tagValue := range nodeGroupTags {
@@ -391,11 +409,35 @@ func (m *ociManagerImpl) TaintToPreventFurtherSchedulingOnRestart(nodes []*apiv1
391409
func (m *ociManagerImpl) forceRefresh() error {
392410
// auto discover node groups
393411
if m.nodeGroups != nil {
394-
// empty previous nodepool map to do an auto discovery
412+
// create a copy of m.staticNodePools to use it in comparison
413+
staticNodePoolsCopy := make(map[string]NodePool)
414+
for k, v := range m.staticNodePools {
415+
staticNodePoolsCopy[k] = v
416+
}
417+
418+
// empty previous nodepool map to do a fresh auto discovery
395419
m.staticNodePools = make(map[string]NodePool)
420+
421+
// run auto-discovery
396422
for _, nodeGroup := range m.nodeGroups {
397423
autoDiscoverNodeGroups(m, m.okeClient, nodeGroup)
398424
}
425+
426+
// compare the new and previous nodepool list to log the updates
427+
for nodepoolId, nodepool := range m.staticNodePools {
428+
if _, ok := staticNodePoolsCopy[nodepoolId]; !ok {
429+
klog.Infof("New nodepool discovered. [id: %s ,minSize: %d, maxSize:%d]", nodepool.Id(), nodepool.MinSize(), nodepool.MaxSize())
430+
} else if staticNodePoolsCopy[nodepoolId].MinSize() != nodepool.MinSize() || staticNodePoolsCopy[nodepoolId].MaxSize() != nodepool.MaxSize() {
431+
klog.Infof("Nodepool min/max sizes are updated. [id: %s ,minSize: %d, maxSize:%d]", nodepool.Id(), nodepool.MinSize(), nodepool.MaxSize())
432+
}
433+
}
434+
435+
// log if there are nodepools removed from the list
436+
for k := range staticNodePoolsCopy {
437+
if _, ok := m.staticNodePools[k]; !ok {
438+
klog.Infof("Previously auto-discovered nodepool removed from the managed nodepool list. nodepoolid: %s", k)
439+
}
440+
}
399441
}
400442
// rebuild nodepool cache
401443
err := m.nodePoolCache.rebuild(m.staticNodePools, maxGetNodepoolRetries)

cluster-autoscaler/cloudprovider/oci/nodepools/oci_manager_test.go

Lines changed: 82 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ package nodepools
66

77
import (
88
"context"
9+
"fmt"
910
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/nodepools/consts"
1011
"net/http"
1112
"reflect"
1213
"testing"
14+
"time"
1315

1416
apiv1 "k8s.io/api/core/v1"
1517
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
@@ -20,6 +22,10 @@ import (
2022
oke "k8s.io/autoscaler/cluster-autoscaler/cloudprovider/oci/vendor-internal/github.com/oracle/oci-go-sdk/v65/containerengine"
2123
)
2224

25+
const (
26+
autoDiscoveryCompartment = "ocid1.compartment.oc1.test-region.test"
27+
)
28+
2329
func TestNodePoolFromArgs(t *testing.T) {
2430
value := `1:5:ocid`
2531
nodePool, err := nodePoolFromArg(value)
@@ -318,8 +324,15 @@ func TestBuildGenericLabels(t *testing.T) {
318324

319325
type mockOKEClient struct{}
320326

321-
func (c mockOKEClient) GetNodePool(context.Context, oke.GetNodePoolRequest) (oke.GetNodePoolResponse, error) {
322-
return oke.GetNodePoolResponse{}, nil
327+
func (c mockOKEClient) GetNodePool(ctx context.Context, req oke.GetNodePoolRequest) (oke.GetNodePoolResponse, error) {
328+
return oke.GetNodePoolResponse{
329+
NodePool: oke.NodePool{
330+
Id: req.NodePoolId,
331+
NodeConfigDetails: &oke.NodePoolNodeConfigDetails{
332+
Size: common.Int(1),
333+
},
334+
},
335+
}, nil
323336
}
324337
func (c mockOKEClient) UpdateNodePool(context.Context, oke.UpdateNodePoolRequest) (oke.UpdateNodePoolResponse, error) {
325338
return oke.UpdateNodePoolResponse{}, nil
@@ -333,7 +346,39 @@ func (c mockOKEClient) DeleteNode(context.Context, oke.DeleteNodeRequest) (oke.D
333346
}, nil
334347
}
335348

336-
func (c mockOKEClient) ListNodePools(context.Context, oke.ListNodePoolsRequest) (oke.ListNodePoolsResponse, error) {
349+
func (c mockOKEClient) ListNodePools(ctx context.Context, req oke.ListNodePoolsRequest) (oke.ListNodePoolsResponse, error) {
350+
// below test data added for auto-discovery tests
351+
if req.CompartmentId != nil && *req.CompartmentId == autoDiscoveryCompartment {
352+
freeformTags1 := map[string]string{
353+
"ca-managed": "true",
354+
}
355+
freeformTags2 := map[string]string{
356+
"ca-managed": "true",
357+
"minSize": "4",
358+
"maxSize": "10",
359+
}
360+
definedTags := map[string]map[string]interface{}{
361+
"namespace": {
362+
"foo": "bar",
363+
},
364+
}
365+
resp := oke.ListNodePoolsResponse{
366+
Items: []oke.NodePoolSummary{
367+
{
368+
Id: common.String("node-pool-1"),
369+
FreeformTags: freeformTags1,
370+
DefinedTags: definedTags,
371+
},
372+
{
373+
Id: common.String("node-pool-2"),
374+
FreeformTags: freeformTags2,
375+
DefinedTags: definedTags,
376+
},
377+
},
378+
}
379+
return resp, nil
380+
}
381+
337382
return oke.ListNodePoolsResponse{}, nil
338383
}
339384

@@ -390,8 +435,41 @@ func TestRemoveInstance(t *testing.T) {
390435
}
391436
}
392437

438+
func TestNodeGroupAutoDiscovery(t *testing.T) {
439+
var nodeGroupArg = fmt.Sprintf("clusterId:ocid1.cluster.oc1.test-region.test,compartmentId:%s,nodepoolTags:ca-managed=true&namespace.foo=bar,min:1,max:5", autoDiscoveryCompartment)
440+
nodeGroup, err := nodeGroupFromArg(nodeGroupArg)
441+
if err != nil {
442+
t.Errorf("Error: #{err}")
443+
}
444+
nodePoolCache := newNodePoolCache(nil)
445+
nodePoolCache.okeClient = mockOKEClient{}
446+
447+
cloudConfig := &ocicommon.CloudConfig{}
448+
cloudConfig.Global.RefreshInterval = 5 * time.Minute
449+
cloudConfig.Global.CompartmentID = autoDiscoveryCompartment
450+
451+
manager := &ociManagerImpl{
452+
nodePoolCache: nodePoolCache,
453+
nodeGroups: []nodeGroupAutoDiscovery{*nodeGroup},
454+
okeClient: mockOKEClient{},
455+
cfg: cloudConfig,
456+
staticNodePools: map[string]NodePool{},
457+
}
458+
// test data to use as initial nodepools
459+
nodepool2 := &nodePool{
460+
id: "node-pool-2", minSize: 1, maxSize: 5,
461+
}
462+
manager.staticNodePools[nodepool2.id] = nodepool2
463+
nodepool3 := &nodePool{
464+
id: "node-pool-3", minSize: 2, maxSize: 5,
465+
}
466+
manager.staticNodePools[nodepool3.id] = nodepool3
467+
468+
manager.forceRefresh()
469+
}
470+
393471
func TestNodeGroupFromArg(t *testing.T) {
394-
var nodeGroupArg = "clusterId:ocid1.cluster.oc1.test-region.test,compartmentId:ocid1.compartment.oc1.test-region.test,nodepoolTags:ca-managed=true&namespace.foo=bar,min:1,max:5"
472+
var nodeGroupArg = fmt.Sprintf("clusterId:ocid1.cluster.oc1.test-region.test,compartmentId:%s,nodepoolTags:ca-managed=true&namespace.foo=bar,min:1,max:5", autoDiscoveryCompartment)
395473
nodeGroupAutoDiscovery, err := nodeGroupFromArg(nodeGroupArg)
396474
if err != nil {
397475
t.Errorf("Error: #{err}")

0 commit comments

Comments
 (0)