Merge pull request #85885 from nilo19/qi-vmss-cache

Provider/Azure: Add cache for VMSS.
This commit is contained in:
Kubernetes Prow Robot 2019-12-06 21:43:09 -08:00 committed by GitHub
commit 50437b4c5d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 87 additions and 2 deletions

View File

@ -60,6 +60,7 @@ type scaleSet struct {
// (e.g. master nodes) may not belong to any scale sets.
availabilitySet VMSet
vmssCache *timedCache
vmssVMCache *timedCache
availabilitySetNodesCache *timedCache
}
@ -77,6 +78,11 @@ func newScaleSet(az *Cloud) (VMSet, error) {
return nil, err
}
ss.vmssCache, err = ss.newVMSSCache()
if err != nil {
return nil, err
}
ss.vmssVMCache, err = ss.newVMSSVirtualMachinesCache()
if err != nil {
return nil, err
@ -85,6 +91,43 @@ func newScaleSet(az *Cloud) (VMSet, error) {
return ss, nil
}
func (ss *scaleSet) getVMSS(vmssName string, crt cacheReadType) (*compute.VirtualMachineScaleSet, error) {
getter := func(vmssName string) (*compute.VirtualMachineScaleSet, error) {
cached, err := ss.vmssCache.Get(vmssKey, crt)
if err != nil {
return nil, err
}
vmsses := cached.(*sync.Map)
if vmss, ok := vmsses.Load(vmssName); ok {
result := vmss.(*vmssEntry)
return result.vmss, nil
}
return nil, nil
}
vmss, err := getter(vmssName)
if err != nil {
return nil, err
}
if vmss != nil {
return vmss, nil
}
klog.V(3).Infof("Couldn't find VMSS with name %s, refreshing the cache", vmssName)
ss.vmssCache.Delete(vmssKey)
vmss, err = getter(vmssName)
if err != nil {
return nil, err
}
if vmss == nil {
return nil, cloudprovider.InstanceNotFound
}
return vmss, nil
}
// getVmssVM gets virtualMachineScaleSetVM by nodeName from cache.
// It returns cloudprovider.InstanceNotFound if node does not belong to any scale sets.
func (ss *scaleSet) getVmssVM(nodeName string, crt cacheReadType) (string, string, *compute.VirtualMachineScaleSetVM, error) {
@ -903,7 +946,7 @@ func (ss *scaleSet) ensureVMSSInPool(service *v1.Service, nodes []*v1.Node, back
}
for vmssName := range vmssNamesMap {
vmss, err := ss.GetScaleSetWithRetry(service, ss.ResourceGroup, vmssName)
vmss, err := ss.getVMSS(vmssName, cacheReadTypeDefault)
if err != nil {
return err
}
@ -1208,7 +1251,7 @@ func (ss *scaleSet) ensureBackendPoolDeletedFromVMSS(service *v1.Service, backen
}
for vmssName := range vmssNamesMap {
vmss, err := ss.GetScaleSetWithRetry(service, ss.ResourceGroup, vmssName)
vmss, err := ss.getVMSS(vmssName, cacheReadTypeDefault)
// When vmss is being deleted, CreateOrUpdate API would report "the vmss is being deleted" error.
// Since it is being deleted, we shouldn't send more CreateOrUpdate requests for it.

View File

@ -19,6 +19,7 @@ limitations under the License.
package azure
import (
"context"
"strings"
"sync"
"time"
@ -33,10 +34,12 @@ import (
var (
vmssNameSeparator = "_"
vmssKey = "k8svmssKey"
vmssVirtualMachinesKey = "k8svmssVirtualMachinesKey"
availabilitySetNodesKey = "k8sAvailabilitySetNodesKey"
availabilitySetNodesCacheTTL = 15 * time.Minute
vmssTTL = 10 * time.Minute
vmssVirtualMachinesTTL = 10 * time.Minute
)
@ -48,6 +51,45 @@ type vmssVirtualMachinesEntry struct {
lastUpdate time.Time
}
type vmssEntry struct {
vmss *compute.VirtualMachineScaleSet
lastUpdate time.Time
}
func (ss *scaleSet) newVMSSCache() (*timedCache, error) {
getter := func(key string) (interface{}, error) {
localCache := &sync.Map{} // [vmssName]*vmssEntry
allResourceGroups, err := ss.GetResourceGroups()
if err != nil {
return nil, err
}
for _, resourceGroup := range allResourceGroups.List() {
allScaleSets, err := ss.VirtualMachineScaleSetsClient.List(context.Background(), resourceGroup)
if err != nil {
klog.Errorf("VirtualMachineScaleSetsClient.List failed: %v", err)
return nil, err
}
for _, scaleSet := range allScaleSets {
if scaleSet.Name == nil || *scaleSet.Name == "" {
klog.Warning("failed to get the name of VMSS")
continue
}
localCache.Store(*scaleSet.Name, &vmssEntry{
vmss: &scaleSet,
lastUpdate: time.Now().UTC(),
})
}
}
return localCache, nil
}
return newTimedcache(vmssTTL, getter)
}
func extractVmssVMName(name string) (string, string, error) {
split := strings.SplitAfter(name, vmssNameSeparator)
if len(split) < 2 {