Skip to content

Commit

Permalink
Merge pull request #7409 from k8s-infra-cherrypick-robot/cherry-pick-…
Browse files Browse the repository at this point in the history
…7231-to-cluster-autoscaler-release-1.28

[cluster-autoscaler-release-1.28] Backporting support for Regional Instance Template GCE to 1.29
  • Loading branch information
k8s-ci-robot authored Oct 17, 2024
2 parents 90c78d4 + 3fed54f commit 6a3cf22
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 68 deletions.
27 changes: 19 additions & 8 deletions cluster-autoscaler/cloudprovider/gce/autoscaling_gce_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ type AutoscalingGceClient interface {
FetchMigTargetSize(GceRef) (int64, error)
FetchMigBasename(GceRef) (string, error)
FetchMigInstances(GceRef) ([]cloudprovider.Instance, error)
FetchMigTemplateName(migRef GceRef) (string, error)
FetchMigTemplate(migRef GceRef, templateName string) (*gce.InstanceTemplate, error)
FetchMigTemplateName(migRef GceRef) (InstanceTemplateName, error)
FetchMigTemplate(migRef GceRef, templateName string, regional bool) (*gce.InstanceTemplate, error)
FetchMigsWithName(zone string, filter *regexp.Regexp) ([]string, error)
FetchZones(region string) ([]string, error)
FetchAvailableCpuPlatforms() (map[string][]string, error)
Expand Down Expand Up @@ -509,26 +509,37 @@ func (client *autoscalingGceClientV1) FetchAvailableCpuPlatforms() (map[string][
return availableCpuPlatforms, nil
}

func (client *autoscalingGceClientV1) FetchMigTemplateName(migRef GceRef) (string, error) {
func (client *autoscalingGceClientV1) FetchMigTemplateName(migRef GceRef) (InstanceTemplateName, error) {
registerRequest("instance_group_managers", "get")
igm, err := client.gceService.InstanceGroupManagers.Get(migRef.Project, migRef.Zone, migRef.Name).Do()
if err != nil {
if err, ok := err.(*googleapi.Error); ok {
if err.Code == http.StatusNotFound {
return "", errors.NewAutoscalerError(errors.NodeGroupDoesNotExistError, "%s", err.Error())
return InstanceTemplateName{}, errors.NewAutoscalerError(errors.NodeGroupDoesNotExistError, "%s", err.Error())
}
}
return "", err
return InstanceTemplateName{}, err
}
templateUrl, err := url.Parse(igm.InstanceTemplate)
if err != nil {
return "", err
return InstanceTemplateName{}, err
}
regional, err := IsInstanceTemplateRegional(templateUrl.String())
if err != nil {
return InstanceTemplateName{}, err
}

_, templateName := path.Split(templateUrl.EscapedPath())
return templateName, nil
return InstanceTemplateName{templateName, regional}, nil
}

func (client *autoscalingGceClientV1) FetchMigTemplate(migRef GceRef, templateName string) (*gce.InstanceTemplate, error) {
func (client *autoscalingGceClientV1) FetchMigTemplate(migRef GceRef, templateName string, regional bool) (*gce.InstanceTemplate, error) {
if regional {
zoneHyphenIndex := strings.LastIndex(migRef.Zone, "-")
region := migRef.Zone[:zoneHyphenIndex]
registerRequest("region_instance_templates", "get")
return client.gceService.RegionInstanceTemplates.Get(migRef.Project, region, templateName).Do()
}
registerRequest("instance_templates", "get")
return client.gceService.InstanceTemplates.Get(migRef.Project, templateName).Do()
}
Expand Down
23 changes: 15 additions & 8 deletions cluster-autoscaler/cloudprovider/gce/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ type MachineTypeKey struct {
MachineTypeName string
}

// InstanceTemplateName is used to store the name, and
// whether or not the instance template is regional
type InstanceTemplateName struct {
Name string
Regional bool
}

// GceCache is used for caching cluster resources state.
//
// It is needed to:
Expand Down Expand Up @@ -66,7 +73,7 @@ type GceCache struct {
machinesCache map[MachineTypeKey]MachineType
migTargetSizeCache map[GceRef]int64
migBaseNameCache map[GceRef]string
instanceTemplateNameCache map[GceRef]string
instanceTemplateNameCache map[GceRef]InstanceTemplateName
instanceTemplatesCache map[GceRef]*gce.InstanceTemplate
}

Expand All @@ -82,7 +89,7 @@ func NewGceCache() *GceCache {
machinesCache: map[MachineTypeKey]MachineType{},
migTargetSizeCache: map[GceRef]int64{},
migBaseNameCache: map[GceRef]string{},
instanceTemplateNameCache: map[GceRef]string{},
instanceTemplateNameCache: map[GceRef]InstanceTemplateName{},
instanceTemplatesCache: map[GceRef]*gce.InstanceTemplate{},
}
}
Expand Down Expand Up @@ -330,23 +337,23 @@ func (gc *GceCache) InvalidateAllMigTargetSizes() {
}

// GetMigInstanceTemplateName returns the cached instance template ref for a mig GceRef
func (gc *GceCache) GetMigInstanceTemplateName(ref GceRef) (string, bool) {
func (gc *GceCache) GetMigInstanceTemplateName(ref GceRef) (InstanceTemplateName, bool) {
gc.cacheMutex.Lock()
defer gc.cacheMutex.Unlock()

templateName, found := gc.instanceTemplateNameCache[ref]
instanceTemplateName, found := gc.instanceTemplateNameCache[ref]
if found {
klog.V(5).Infof("Instance template names cache hit for %s", ref)
}
return templateName, found
return instanceTemplateName, found
}

// SetMigInstanceTemplateName sets instance template ref for a mig GceRef
func (gc *GceCache) SetMigInstanceTemplateName(ref GceRef, templateName string) {
func (gc *GceCache) SetMigInstanceTemplateName(ref GceRef, instanceTemplateName InstanceTemplateName) {
gc.cacheMutex.Lock()
defer gc.cacheMutex.Unlock()

gc.instanceTemplateNameCache[ref] = templateName
gc.instanceTemplateNameCache[ref] = instanceTemplateName
}

// InvalidateMigInstanceTemplateName clears the instance template ref cache for a mig GceRef
Expand All @@ -366,7 +373,7 @@ func (gc *GceCache) InvalidateAllMigInstanceTemplateNames() {
defer gc.cacheMutex.Unlock()

klog.V(5).Infof("Instance template names cache invalidated")
gc.instanceTemplateNameCache = map[GceRef]string{}
gc.instanceTemplateNameCache = map[GceRef]InstanceTemplateName{}
}

// GetMigInstanceTemplate returns the cached gce.InstanceTemplate for a mig GceRef
Expand Down
2 changes: 1 addition & 1 deletion cluster-autoscaler/cloudprovider/gce/gce_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,7 @@ func newTestGceManager(t *testing.T, testServerURL string, regional bool) *gceMa
{"us-central1-f", "n1-standard-1"}: {Name: "n1-standard-1", CPU: 1, Memory: 1},
},
migTargetSizeCache: map[GceRef]int64{},
instanceTemplateNameCache: map[GceRef]string{},
instanceTemplateNameCache: map[GceRef]InstanceTemplateName{},
instanceTemplatesCache: map[GceRef]*gce.InstanceTemplate{},
migBaseNameCache: map[GceRef]string{},
}
Expand Down
6 changes: 6 additions & 0 deletions cluster-autoscaler/cloudprovider/gce/gce_url.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package gce

import (
"fmt"
"regexp"
"strings"
)

Expand Down Expand Up @@ -73,6 +74,11 @@ func GenerateMigUrl(ref GceRef) string {
return fmt.Sprintf(migUrlTemplate, ref.Project, ref.Zone, ref.Name)
}

// IsInstanceTemplateRegional determines whether or not an instance template is regional based on the url
func IsInstanceTemplateRegional(templateUrl string) (bool, error) {
return regexp.MatchString("(/projects/.*[A-Za-z0-9]+.*/regions/)", templateUrl)
}

func parseGceUrl(url, expectedResource string) (project string, zone string, name string, err error) {
errMsg := fmt.Errorf("wrong url: expected format https://www.googleapis.com/compute/v1/projects/<project-id>/zones/<zone>/%s/<name>, got %s", expectedResource, url)
if !strings.Contains(url, gceDomainSuffix) {
Expand Down
31 changes: 31 additions & 0 deletions cluster-autoscaler/cloudprovider/gce/gce_url_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,34 @@ func TestParseUrl(t *testing.T) {
_, _, _, err = parseGceUrl("https://www.googleapis.com/compute/vabc/projects/mwielgus-proj/zones/us-central1-b/instanceGroups/kubernetes-minion-group", "instanceGroups")
assert.NotNil(t, err)
}

func TestIsInstanceTemplateRegional(t *testing.T) {
tests := []struct {
name string
templateUrl string
expectRegional bool
wantErr error
}{
{
name: "Has regional instance url",
templateUrl: "https://www.googleapis.com/compute/v1/projects/test-project/regions/us-central1/instanceTemplates/instance-template",
expectRegional: true,
},
{
name: "Has global instance url",
templateUrl: "https://www.googleapis.com/compute/v1/projects/test-project/global/instanceTemplates/instance-template",
expectRegional: false,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
regional, err := IsInstanceTemplateRegional(tt.templateUrl)
assert.Equal(t, tt.wantErr, err)
if tt.wantErr != nil {
return
}
assert.Equal(t, tt.expectRegional, regional)
})
}
}
35 changes: 20 additions & 15 deletions cluster-autoscaler/cloudprovider/gce/mig_info_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ type MigInfoProvider interface {
// GetMigBasename returns basename for given MIG ref
GetMigBasename(migRef GceRef) (string, error)
// GetMigInstanceTemplateName returns instance template name for given MIG ref
GetMigInstanceTemplateName(migRef GceRef) (string, error)
GetMigInstanceTemplateName(migRef GceRef) (InstanceTemplateName, error)
// GetMigInstanceTemplate returns instance template for given MIG ref
GetMigInstanceTemplate(migRef GceRef) (*gce.InstanceTemplate, error)
// GetMigMachineType returns machine type used by a MIG.
Expand Down Expand Up @@ -240,44 +240,44 @@ func (c *cachingMigInfoProvider) GetMigBasename(migRef GceRef) (string, error) {
return basename, nil
}

func (c *cachingMigInfoProvider) GetMigInstanceTemplateName(migRef GceRef) (string, error) {
func (c *cachingMigInfoProvider) GetMigInstanceTemplateName(migRef GceRef) (InstanceTemplateName, error) {
c.migInfoMutex.Lock()
defer c.migInfoMutex.Unlock()

templateName, found := c.cache.GetMigInstanceTemplateName(migRef)
instanceTemplateName, found := c.cache.GetMigInstanceTemplateName(migRef)
if found {
return templateName, nil
return instanceTemplateName, nil
}

err := c.fillMigInfoCache()
templateName, found = c.cache.GetMigInstanceTemplateName(migRef)
instanceTemplateName, found = c.cache.GetMigInstanceTemplateName(migRef)
if err == nil && found {
return templateName, nil
return instanceTemplateName, nil
}

// fallback to querying for single mig
templateName, err = c.gceClient.FetchMigTemplateName(migRef)
instanceTemplateName, err = c.gceClient.FetchMigTemplateName(migRef)
if err != nil {
c.migLister.HandleMigIssue(migRef, err)
return "", err
return InstanceTemplateName{}, err
}
c.cache.SetMigInstanceTemplateName(migRef, templateName)
return templateName, nil
c.cache.SetMigInstanceTemplateName(migRef, instanceTemplateName)
return instanceTemplateName, nil
}

func (c *cachingMigInfoProvider) GetMigInstanceTemplate(migRef GceRef) (*gce.InstanceTemplate, error) {
templateName, err := c.GetMigInstanceTemplateName(migRef)
instanceTemplateName, err := c.GetMigInstanceTemplateName(migRef)
if err != nil {
return nil, err
}

template, found := c.cache.GetMigInstanceTemplate(migRef)
if found && template.Name == templateName {
if found && template.Name == instanceTemplateName.Name {
return template, nil
}

klog.V(2).Infof("Instance template of mig %v changed to %v", migRef.Name, templateName)
template, err = c.gceClient.FetchMigTemplate(migRef, templateName)
klog.V(2).Infof("Instance template of mig %v changed to %v", migRef.Name, instanceTemplateName.Name)
template, err = c.gceClient.FetchMigTemplate(migRef, instanceTemplateName.Name, instanceTemplateName.Regional)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -336,7 +336,12 @@ func (c *cachingMigInfoProvider) fillMigInfoCache() error {
templateUrl, err := url.Parse(zoneMig.InstanceTemplate)
if err == nil {
_, templateName := path.Split(templateUrl.EscapedPath())
c.cache.SetMigInstanceTemplateName(zoneMigRef, templateName)
regional, err := IsInstanceTemplateRegional(templateUrl.String())
if err != nil {
klog.Errorf("Error parsing instance template url: %v; err=%v ", templateUrl.String(), err)
} else {
c.cache.SetMigInstanceTemplateName(zoneMigRef, InstanceTemplateName{templateName, regional})
}
}
}
}
Expand Down
Loading

0 comments on commit 6a3cf22

Please sign in to comment.