Skip to content

Commit

Permalink
Clean instance templates for untracked migs.
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrqq committed Jan 15, 2025
1 parent 5cd491a commit 83d5340
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 1 deletion.
38 changes: 38 additions & 0 deletions cluster-autoscaler/cloudprovider/gce/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,25 @@ func (gc *GceCache) InvalidateAllMigInstanceTemplateNames() {
gc.instanceTemplateNameCache = map[GceRef]InstanceTemplateName{}
}

// InvalidateMigInstanceTemplateNamesNotFor clears the instance template
// name cache intended not for given MIGs
func (gc *GceCache) InvalidateMigInstanceTemplateNamesNotFor(migs []Mig) {
gc.cacheMutex.Lock()
defer gc.cacheMutex.Unlock()

requiredKeys := make(map[GceRef]struct{}, len(migs))
for _, mig := range migs {
requiredKeys[mig.GceRef()] = struct{}{}
}

klog.V(5).Infof("Instance template names cache partially invalidated")
for key := range gc.instanceTemplateNameCache {
if _, exists := requiredKeys[key]; !exists {
delete(gc.instanceTemplateNameCache, key)
}
}
}

// GetMigInstanceTemplate returns the cached gce.InstanceTemplate for a mig GceRef
func (gc *GceCache) GetMigInstanceTemplate(ref GceRef) (*gce.InstanceTemplate, bool) {
gc.cacheMutex.Lock()
Expand Down Expand Up @@ -432,6 +451,25 @@ func (gc *GceCache) InvalidateAllMigInstanceTemplates() {
gc.instanceTemplatesCache = map[GceRef]*gce.InstanceTemplate{}
}

// InvalidateMigInstanceTemplatesNotFor clears the instance template
// cache intended not for given MIGs
func (gc *GceCache) InvalidateMigInstanceTemplatesNotFor(migs []Mig) {
gc.cacheMutex.Lock()
defer gc.cacheMutex.Unlock()

requiredKeys := make(map[GceRef]struct{}, len(migs))
for _, mig := range migs {
requiredKeys[mig.GceRef()] = struct{}{}
}

klog.V(5).Infof("Instance template cache partially invalidated")
for key := range gc.instanceTemplatesCache {
if _, exists := requiredKeys[key]; !exists {
delete(gc.instanceTemplatesCache, key)
}
}
}

// GetMigKubeEnv returns the cached KubeEnv for a mig GceRef
func (gc *GceCache) GetMigKubeEnv(ref GceRef) (KubeEnv, bool) {
gc.cacheMutex.Lock()
Expand Down
5 changes: 4 additions & 1 deletion cluster-autoscaler/cloudprovider/gce/mig_info_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,14 @@ func (c *cachingMigInfoProvider) RegenerateMigInstancesCache() error {
c.cache.InvalidateAllMigInstances()
c.cache.InvalidateAllInstancesToMig()

migs := c.migLister.GetMigs()
c.cache.InvalidateMigInstanceTemplatesNotFor(migs)
c.cache.InvalidateMigInstanceTemplateNamesNotFor(migs)

if c.bulkGceMigInstancesListingEnabled {
return c.bulkListMigInstances()
}

migs := c.migLister.GetMigs()
errors := make([]error, len(migs))
workqueue.ParallelizeUntil(context.Background(), c.concurrentGceRefreshes, len(migs), func(piece int) {
errors[piece] = c.fillMigInstances(migs[piece].GceRef())
Expand Down
103 changes: 103 additions & 0 deletions cluster-autoscaler/cloudprovider/gce/mig_info_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,8 @@ func TestRegenerateMigInstancesCache(t *testing.T) {
expectedErr error
expectedMigInstances map[GceRef][]GceInstance
expectedInstancesToMig map[GceRef]GceRef
expectedInstanceTemplates map[GceRef]*gce.InstanceTemplate
expectedInstanceTemplateNames map[GceRef]InstanceTemplateName
}{
{
name: "fill empty cache for one mig",
Expand Down Expand Up @@ -698,6 +700,9 @@ func TestRegenerateMigInstancesCache(t *testing.T) {
mig1InstancesRefs[0]: mig1.GceRef(),
mig1InstancesRefs[1]: mig1.GceRef(),
},
expectedInstanceTemplateNames: map[GceRef]InstanceTemplateName{
mig1.GceRef(): InstanceTemplateName{Name: "", Regional: false},
},
},
{
name: "bulkGceMigInstancesListingEnabled - fill empty cache for one mig - number of instances are inconsistent in bulk listing result",
Expand All @@ -724,6 +729,9 @@ func TestRegenerateMigInstancesCache(t *testing.T) {
mig2InstancesRefs[0]: mig2.GceRef(),
mig2InstancesRefs[1]: mig2.GceRef(),
},
expectedInstanceTemplateNames: map[GceRef]InstanceTemplateName{
mig2.GceRef(): InstanceTemplateName{Name: "", Regional: false},
},
},
{
name: "bulkGceMigInstancesListingEnabled - fill empty cache for one mig - all instances in running state",
Expand All @@ -748,6 +756,99 @@ func TestRegenerateMigInstancesCache(t *testing.T) {
mig2InstancesRefs[0]: mig2.GceRef(),
mig2InstancesRefs[1]: mig2.GceRef(),
},
expectedInstanceTemplateNames: map[GceRef]InstanceTemplateName{
mig2.GceRef(): InstanceTemplateName{Name: "", Regional: false},
},
},
{
name: "clear instance template cache for untracked MIG",
cache: &GceCache{
migs: map[GceRef]Mig{
mig.GceRef(): mig,
},
instances: map[GceRef][]GceInstance{
mig.GceRef(): instances,
},
instancesToMig: map[GceRef]GceRef{
instancesRefs[0]: mig.GceRef(),
instancesRefs[1]: mig.GceRef(),
},
instanceTemplatesCache: map[GceRef]*gce.InstanceTemplate{
mig.GceRef(): {Name: "", Description: "mig instance template"},
otherMig.GceRef(): {Name: "", Description: "other mig instance template"},
},
instanceTemplateNameCache: map[GceRef]InstanceTemplateName{
mig.GceRef(): {Name: "", Regional: false},
otherMig.GceRef(): {Name: "", Regional: false},
},
},
fetchMigInstances: fetchMigInstancesMapping(map[GceRef][]GceInstance{
mig.GceRef(): instances,
otherMig.GceRef(): otherInstances,
}),
projectId: mig.GceRef().Project,
expectedMigInstances: map[GceRef][]GceInstance{
mig.GceRef(): instances,
},
expectedInstancesToMig: map[GceRef]GceRef{
instancesRefs[0]: mig.GceRef(),
instancesRefs[1]: mig.GceRef(),
},
expectedInstanceTemplates: map[GceRef]*gce.InstanceTemplate{
mig.GceRef(): {Name: "", Description: "mig instance template"},
},
expectedInstanceTemplateNames: map[GceRef]InstanceTemplateName{
mig.GceRef(): {Name: "", Regional: false},
},
},
{
name: "bulkGceMigInstancesListingEnabled - clear instance template cache for untracked MIG",
cache: &GceCache{
migs: map[GceRef]Mig{
mig1.GceRef(): mig1,
},
instances: map[GceRef][]GceInstance{
mig1.GceRef(): mig1Instances,
},
instancesToMig: map[GceRef]GceRef{
mig1InstancesRefs[0]: mig1.GceRef(),
mig1InstancesRefs[1]: mig1.GceRef(),
},
instanceTemplatesCache: map[GceRef]*gce.InstanceTemplate{
mig1.GceRef(): {Name: "", Description: "mig instance template"},
mig2.GceRef(): {Name: "", Description: "other mig instance template"},
},
instanceTemplateNameCache: map[GceRef]InstanceTemplateName{
mig1.GceRef(): {Name: "", Regional: false},
mig2.GceRef(): {Name: "", Regional: false},
},
},
bulkGceMigInstancesListingEnabled: true,
fetchMigs: fetchMigsConst([]*gce.InstanceGroupManager{mig1Igm}),
fetchMigInstances: fetchMigInstancesMapping(map[GceRef][]GceInstance{
mig1.GceRef(): mig1Instances,
mig2.GceRef(): mig2Instances,
}),
fetchAllInstances: fetchAllInstancesInZone(
map[string][]GceInstance{
mig1.GceRef().Zone: mig1Instances,
mig2.GceRef().Zone: mig2Instances,
},
),
projectId: mig.GceRef().Project,
expectedMigInstances: map[GceRef][]GceInstance{
mig1.GceRef(): mig1Instances,
},
expectedInstancesToMig: map[GceRef]GceRef{
mig1InstancesRefs[0]: mig1.GceRef(),
mig1InstancesRefs[1]: mig1.GceRef(),
},
expectedInstanceTemplates: map[GceRef]*gce.InstanceTemplate{
mig1.GceRef(): {Name: "", Description: "mig instance template"},
},
expectedInstanceTemplateNames: map[GceRef]InstanceTemplateName{
mig1.GceRef(): {Name: "", Regional: false},
},
},
}

Expand All @@ -766,6 +867,8 @@ func TestRegenerateMigInstancesCache(t *testing.T) {
if tc.expectedErr == nil {
assert.Equal(t, tc.expectedMigInstances, tc.cache.instances)
assert.Equal(t, tc.expectedInstancesToMig, tc.cache.instancesToMig)
assert.Equal(t, tc.expectedInstanceTemplates, tc.cache.instanceTemplatesCache)
assert.Equal(t, tc.expectedInstanceTemplateNames, tc.cache.instanceTemplateNameCache)
}
})
}
Expand Down

0 comments on commit 83d5340

Please sign in to comment.