Ensure VMSS is not under updating before scaling out
This commit is contained in:
parent
dbc53ee62f
commit
1ae92f7bc4
|
|
@ -80,7 +80,7 @@ func (client *VirtualMachineScaleSetsClientMock) CreateOrUpdateAsync(ctx context
|
||||||
|
|
||||||
// WaitForAsyncOperationResult waits for the response of the request
|
// WaitForAsyncOperationResult waits for the response of the request
|
||||||
func (client *VirtualMachineScaleSetsClientMock) WaitForAsyncOperationResult(ctx context.Context, future *azure.Future) (*http.Response, error) {
|
func (client *VirtualMachineScaleSetsClientMock) WaitForAsyncOperationResult(ctx context.Context, future *azure.Future) (*http.Response, error) {
|
||||||
return nil, nil
|
return &http.Response{StatusCode: http.StatusOK}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteInstances deletes a set of instances for specified VirtualMachineScaleSet.
|
// DeleteInstances deletes a set of instances for specified VirtualMachineScaleSet.
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
"github.com/Azure/go-autorest/autorest/azure"
|
"github.com/Azure/go-autorest/autorest/azure"
|
||||||
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -253,7 +254,7 @@ func (scaleSet *ScaleSet) updateVMSSCapacity(future *azure.Future) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.Errorf("virtualMachineScaleSetsClient.WaitForCreateOrUpdate for scale set %q failed: %v", scaleSet.Name, err)
|
klog.Errorf("virtualMachineScaleSetsClient.WaitForAsyncOperationResult for scale set %q failed: %v", scaleSet.Name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetScaleSetSize sets ScaleSet size.
|
// SetScaleSetSize sets ScaleSet size.
|
||||||
|
|
@ -261,19 +262,27 @@ func (scaleSet *ScaleSet) SetScaleSetSize(size int64) error {
|
||||||
scaleSet.sizeMutex.Lock()
|
scaleSet.sizeMutex.Lock()
|
||||||
defer scaleSet.sizeMutex.Unlock()
|
defer scaleSet.sizeMutex.Unlock()
|
||||||
|
|
||||||
// Proactively set the VMSS size so autoscaler makes better decisions.
|
|
||||||
scaleSet.curSize = size
|
|
||||||
scaleSet.lastSizeRefresh = time.Now()
|
|
||||||
|
|
||||||
vmssInfo, rerr := scaleSet.getVMSSInfo()
|
vmssInfo, rerr := scaleSet.getVMSSInfo()
|
||||||
if rerr != nil {
|
if rerr != nil {
|
||||||
klog.Errorf("Failed to get information for VMSS (%q): %v", scaleSet.Name, rerr)
|
klog.Errorf("Failed to get information for VMSS (%q): %v", scaleSet.Name, rerr)
|
||||||
return rerr.Error()
|
return rerr.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Abort scaling to avoid concurrent VMSS scaling if the VMSS is still under updating.
|
||||||
|
// Note that the VMSS provisioning state would be updated per scaleSet.sizeRefreshPeriod.
|
||||||
|
if vmssInfo.VirtualMachineScaleSetProperties != nil && strings.EqualFold(to.String(vmssInfo.VirtualMachineScaleSetProperties.ProvisioningState), string(compute.ProvisioningStateUpdating)) {
|
||||||
|
klog.Errorf("VMSS %q is still under updating, waiting for it finishes before scaling", scaleSet.Name)
|
||||||
|
return fmt.Errorf("VMSS %q is still under updating", scaleSet.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Proactively set the VMSS size so autoscaler makes better decisions.
|
||||||
|
scaleSet.curSize = size
|
||||||
|
scaleSet.lastSizeRefresh = time.Now()
|
||||||
|
|
||||||
// Update the new capacity to cache.
|
// Update the new capacity to cache.
|
||||||
vmssSizeMutex.Lock()
|
vmssSizeMutex.Lock()
|
||||||
vmssInfo.Sku.Capacity = &size
|
vmssInfo.Sku.Capacity = &size
|
||||||
|
vmssInfo.VirtualMachineScaleSetProperties.ProvisioningState = to.StringPtr(string(compute.ProvisioningStateUpdating))
|
||||||
vmssSizeMutex.Unlock()
|
vmssSizeMutex.Unlock()
|
||||||
|
|
||||||
// Compose a new VMSS for updating.
|
// Compose a new VMSS for updating.
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute"
|
||||||
"github.com/Azure/go-autorest/autorest"
|
"github.com/Azure/go-autorest/autorest"
|
||||||
|
"github.com/Azure/go-autorest/autorest/to"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
|
@ -97,6 +99,60 @@ func TestIncreaseSize(t *testing.T) {
|
||||||
assert.Equal(t, 5, targetSize)
|
assert.Equal(t, 5, targetSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIncreaseSizeOnVMSSUpdating(t *testing.T) {
|
||||||
|
manager := newTestAzureManager(t)
|
||||||
|
vmssName := "vmss-updating"
|
||||||
|
var vmssCapacity int64 = 3
|
||||||
|
scaleSetClient := &VirtualMachineScaleSetsClientMock{
|
||||||
|
FakeStore: map[string]map[string]compute.VirtualMachineScaleSet{
|
||||||
|
"test": {
|
||||||
|
vmssName: {
|
||||||
|
Name: &vmssName,
|
||||||
|
Sku: &compute.Sku{
|
||||||
|
Capacity: &vmssCapacity,
|
||||||
|
},
|
||||||
|
VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{
|
||||||
|
ProvisioningState: to.StringPtr(string(compute.ProvisioningStateUpdating)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
manager.azClient.virtualMachineScaleSetsClient = scaleSetClient
|
||||||
|
registered := manager.RegisterAsg(newTestScaleSet(manager, vmssName))
|
||||||
|
assert.True(t, registered)
|
||||||
|
manager.regenerateCache()
|
||||||
|
|
||||||
|
provider, err := BuildAzureCloudProvider(manager, nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
// Scaling should fail because VMSS is still under updating.
|
||||||
|
scaleSet, ok := provider.NodeGroups()[0].(*ScaleSet)
|
||||||
|
assert.True(t, ok)
|
||||||
|
err = scaleSet.IncreaseSize(1)
|
||||||
|
assert.Equal(t, fmt.Errorf("VMSS %q is still under updating", scaleSet.Name), err)
|
||||||
|
|
||||||
|
// Scaling should succeed after VMSS ProvisioningState changed to succeeded.
|
||||||
|
scaleSetClient.FakeStore = map[string]map[string]compute.VirtualMachineScaleSet{
|
||||||
|
"test": {
|
||||||
|
vmssName: {
|
||||||
|
Name: &vmssName,
|
||||||
|
Sku: &compute.Sku{
|
||||||
|
Capacity: &vmssCapacity,
|
||||||
|
},
|
||||||
|
VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{
|
||||||
|
ProvisioningState: to.StringPtr(string(compute.ProvisioningStateSucceeded)),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
scaleSetStatusCache.mutex.Lock()
|
||||||
|
scaleSetStatusCache.lastRefresh = time.Now().Add(-1 * scaleSet.sizeRefreshPeriod)
|
||||||
|
scaleSetStatusCache.mutex.Unlock()
|
||||||
|
err = scaleSet.IncreaseSize(1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestBelongs(t *testing.T) {
|
func TestBelongs(t *testing.T) {
|
||||||
provider := newTestProvider(t)
|
provider := newTestProvider(t)
|
||||||
registered := provider.azureManager.RegisterAsg(
|
registered := provider.azureManager.RegisterAsg(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue