Skip to content

Commit e8ca5fd

Browse files
committed
Add support for edge zones in Azure provider
1 parent 6415be0 commit e8ca5fd

File tree

2 files changed

+109
-8
lines changed

2 files changed

+109
-8
lines changed

cluster-autoscaler/cloudprovider/azure/azure_scale_set.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ func (scaleSet *ScaleSet) SetScaleSetSize(size int64) error {
254254
Sku: vmssInfo.Sku,
255255
Location: vmssInfo.Location,
256256
}
257+
258+
if vmssInfo.ExtendedLocation != nil {
259+
op.ExtendedLocation = &compute.ExtendedLocation{
260+
Name: vmssInfo.ExtendedLocation.Name,
261+
Type: vmssInfo.ExtendedLocation.Type,
262+
}
263+
264+
klog.V(3).Infof("Passing ExtendedLocation information if it is not nil, with Edge Zone name:(%s)", *op.ExtendedLocation.Name)
265+
}
266+
257267
ctx, cancel := getContextWithTimeout(vmssContextTimeout)
258268
defer cancel()
259269
klog.V(3).Infof("Waiting for virtualMachineScaleSetsClient.CreateOrUpdateAsync(%s)", scaleSet.Name)

cluster-autoscaler/cloudprovider/azure/azure_scale_set_test.go

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ import (
3232
"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/vmssvmclient/mockvmssvmclient"
3333
)
3434

35+
const (
36+
testASG = "test-asg"
37+
testLocation = "eastus"
38+
)
39+
3540
func newTestScaleSet(manager *AzureManager, name string) *ScaleSet {
3641
return &ScaleSet{
3742
azureRef: azureRef{
@@ -44,6 +49,18 @@ func newTestScaleSet(manager *AzureManager, name string) *ScaleSet {
4449
}
4550
}
4651

52+
func newTestScaleSetMinSizeZero(manager *AzureManager, name string) *ScaleSet {
53+
return &ScaleSet{
54+
azureRef: azureRef{
55+
Name: name,
56+
},
57+
manager: manager,
58+
minSize: 0,
59+
maxSize: 5,
60+
enableForceDelete: manager.config.EnableForceDelete,
61+
}
62+
}
63+
4764
func newTestVMSSList(cap int64, name, loc string, orchmode compute.OrchestrationMode) []compute.VirtualMachineScaleSet {
4865
return []compute.VirtualMachineScaleSet{
4966
{
@@ -61,6 +78,22 @@ func newTestVMSSList(cap int64, name, loc string, orchmode compute.Orchestration
6178
}
6279
}
6380

81+
func newTestVMSSListForEdgeZones(capacity int64, name string) *compute.VirtualMachineScaleSet {
82+
return &compute.VirtualMachineScaleSet{
83+
Name: to.StringPtr(name),
84+
Sku: &compute.Sku{
85+
Capacity: to.Int64Ptr(capacity),
86+
Name: to.StringPtr("Standard_D4_v2"),
87+
},
88+
VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{},
89+
Location: to.StringPtr(testLocation),
90+
ExtendedLocation: &compute.ExtendedLocation{
91+
Name: to.StringPtr("losangeles"),
92+
Type: compute.ExtendedLocationTypes("EdgeZone"),
93+
},
94+
}
95+
}
96+
6497
func newTestVMSSVMList(count int) []compute.VirtualMachineScaleSetVM {
6598
var vmssVMList []compute.VirtualMachineScaleSetVM
6699
for i := 0; i < count; i++ {
@@ -122,6 +155,15 @@ func TestMinSize(t *testing.T) {
122155
assert.Equal(t, provider.NodeGroups()[0].MinSize(), 1)
123156
}
124157

158+
func TestMinSizeZero(t *testing.T) {
159+
provider := newTestProvider(t)
160+
registered := provider.azureManager.RegisterNodeGroup(
161+
newTestScaleSetMinSizeZero(provider.azureManager, testASG))
162+
assert.True(t, registered)
163+
assert.Equal(t, len(provider.NodeGroups()), 1)
164+
assert.Equal(t, provider.NodeGroups()[0].MinSize(), 0)
165+
}
166+
125167
func TestTargetSize(t *testing.T) {
126168
ctrl := gomock.NewController(t)
127169
defer ctrl.Finish()
@@ -177,24 +219,33 @@ func TestIncreaseSize(t *testing.T) {
177219
for _, orchMode := range orchestrationModes {
178220

179221
provider := newTestProvider(t)
180-
expectedScaleSets := newTestVMSSList(3, "test-asg", "eastus", orchMode)
222+
expectedScaleSets := newTestVMSSList(3, testASG, testLocation, orchMode)
223+
224+
// Include Edge Zone scenario here, testing scale from 3 to 5 and scale from zero cases.
225+
expectedEdgeZoneScaleSets := newTestVMSSListForEdgeZones(3, "edgezone-vmss")
226+
expectedEdgeZoneMinZeroScaleSets := newTestVMSSListForEdgeZones(0, "edgezone-minzero-vmss")
227+
expectedScaleSets = append(expectedScaleSets, *expectedEdgeZoneScaleSets, *expectedEdgeZoneMinZeroScaleSets)
181228

182229
mockVMSSClient := mockvmssclient.NewMockInterface(ctrl)
183230
mockVMSSClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup).Return(expectedScaleSets, nil).AnyTimes()
184-
mockVMSSClient.EXPECT().CreateOrUpdateAsync(gomock.Any(), provider.azureManager.config.ResourceGroup, "test-asg", gomock.Any()).Return(nil, nil)
231+
mockVMSSClient.EXPECT().CreateOrUpdateAsync(gomock.Any(), provider.azureManager.config.ResourceGroup, testASG, gomock.Any()).Return(nil, nil)
232+
// This should be Anytimes() because the parent function of this call - updateVMSSCapacity() is a goroutine
233+
// and this test doesn't wait on goroutine, hence, it is difficult to write exact expected number (which is 3 here)
234+
// before we return from this this.
235+
// This is a future TODO: sync.WaitGroup should be used in actual code and make code easily testable
185236
mockVMSSClient.EXPECT().WaitForCreateOrUpdateResult(gomock.Any(), gomock.Any(), provider.azureManager.config.ResourceGroup).Return(&http.Response{StatusCode: http.StatusOK}, nil).AnyTimes()
186237
provider.azureManager.azClient.virtualMachineScaleSetsClient = mockVMSSClient
187238

188239
if orchMode == compute.Uniform {
189240

190241
mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl)
191-
mockVMSSVMClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup, "test-asg", gomock.Any()).Return(expectedVMSSVMs, nil).AnyTimes()
242+
mockVMSSVMClient.EXPECT().List(gomock.Any(), provider.azureManager.config.ResourceGroup, testASG, gomock.Any()).Return(expectedVMSSVMs, nil).AnyTimes()
192243
provider.azureManager.azClient.virtualMachineScaleSetVMsClient = mockVMSSVMClient
193244
} else {
194245

195246
provider.azureManager.config.EnableVmssFlex = true
196247
mockVMClient := mockvmclient.NewMockInterface(ctrl)
197-
mockVMClient.EXPECT().ListVmssFlexVMsWithoutInstanceView(gomock.Any(), "test-asg").Return(expectedVMs, nil).AnyTimes()
248+
mockVMClient.EXPECT().ListVmssFlexVMsWithoutInstanceView(gomock.Any(), testASG).Return(expectedVMs, nil).AnyTimes()
198249
provider.azureManager.azClient.virtualMachinesClient = mockVMClient
199250
}
200251
err := provider.azureManager.forceRefresh()
@@ -206,23 +257,63 @@ func TestIncreaseSize(t *testing.T) {
206257
assert.Equal(t, expectedErr, err)
207258

208259
registered := provider.azureManager.RegisterNodeGroup(
209-
newTestScaleSet(provider.azureManager, "test-asg"))
260+
newTestScaleSet(provider.azureManager, testASG))
210261
assert.True(t, registered)
211262
assert.Equal(t, len(provider.NodeGroups()), 1)
212263

213-
// current target size is 2.
264+
// Current target size is 3.
214265
targetSize, err := provider.NodeGroups()[0].TargetSize()
215266
assert.NoError(t, err)
216267
assert.Equal(t, 3, targetSize)
217268

218-
// increase 3 nodes.
269+
// Increase 2 nodes.
219270
err = provider.NodeGroups()[0].IncreaseSize(2)
220271
assert.NoError(t, err)
221272

222-
// new target size should be 5.
273+
// New target size should be 5.
223274
targetSize, err = provider.NodeGroups()[0].TargetSize()
224275
assert.NoError(t, err)
225276
assert.Equal(t, 5, targetSize)
277+
278+
// Testing Edge Zone scenario. Scale from 3 to 5.
279+
registeredForEdgeZone := provider.azureManager.RegisterNodeGroup(
280+
newTestScaleSet(provider.azureManager, "edgezone-vmss"))
281+
assert.True(t, registeredForEdgeZone)
282+
assert.Equal(t, len(provider.NodeGroups()), 2)
283+
284+
targetSizeForEdgeZone, err := provider.NodeGroups()[1].TargetSize()
285+
assert.NoError(t, err)
286+
assert.Equal(t, 3, targetSizeForEdgeZone)
287+
288+
mockVMSSClient.EXPECT().CreateOrUpdateAsync(gomock.Any(), provider.azureManager.config.ResourceGroup,
289+
"edgezone-vmss", gomock.Any()).Return(nil, nil)
290+
err = provider.NodeGroups()[1].IncreaseSize(2)
291+
assert.NoError(t, err)
292+
293+
targetSizeForEdgeZone, err = provider.NodeGroups()[1].TargetSize()
294+
assert.NoError(t, err)
295+
assert.Equal(t, 5, targetSizeForEdgeZone)
296+
297+
// Testing Edge Zone scenario scaleFromZero case. Scale from 0 to 2.
298+
registeredForEdgeZoneMinZero := provider.azureManager.RegisterNodeGroup(
299+
newTestScaleSetMinSizeZero(provider.azureManager, "edgezone-minzero-vmss"))
300+
assert.True(t, registeredForEdgeZoneMinZero)
301+
assert.Equal(t, len(provider.NodeGroups()), 3)
302+
303+
// Current target size is 0.
304+
targetSizeForEdgeZoneMinZero, err := provider.NodeGroups()[2].TargetSize()
305+
assert.NoError(t, err)
306+
assert.Equal(t, 0, targetSizeForEdgeZoneMinZero)
307+
308+
mockVMSSClient.EXPECT().CreateOrUpdateAsync(gomock.Any(), provider.azureManager.config.ResourceGroup,
309+
"edgezone-minzero-vmss", gomock.Any()).Return(nil, nil)
310+
err = provider.NodeGroups()[2].IncreaseSize(2)
311+
assert.NoError(t, err)
312+
313+
// New target size should be 2.
314+
targetSizeForEdgeZoneMinZero, err = provider.NodeGroups()[2].TargetSize()
315+
assert.NoError(t, err)
316+
assert.Equal(t, 2, targetSizeForEdgeZoneMinZero)
226317
}
227318
}
228319

0 commit comments

Comments
 (0)