diff --git a/pkg/volume/gce_pd/gce_pd.go b/pkg/volume/gce_pd/gce_pd.go index 418be2fddc..18e040433a 100644 --- a/pkg/volume/gce_pd/gce_pd.go +++ b/pkg/volume/gce_pd/gce_pd.go @@ -17,10 +17,12 @@ limitations under the License. package gce_pd import ( + "context" "fmt" "os" "path" "strconv" + "strings" "github.com/golang/glog" "k8s.io/api/core/v1" @@ -56,6 +58,18 @@ const ( gcePersistentDiskPluginName = "kubernetes.io/gce-pd" ) +// The constants are used to map from the machine type (number of CPUs) to the limit of +// persistent disks that can be attached to an instance. Please refer to gcloud doc +// https://cloud.google.com/compute/docs/disks/#increased_persistent_disk_limits +const ( + OneCPU = 1 + EightCPUs = 8 + VolumeLimit16 = 16 + VolumeLimit32 = 32 + VolumeLimit64 = 64 + VolumeLimit128 = 128 +) + func getPath(uid types.UID, volName string, host volume.VolumeHost) string { return host.GetPodVolumeDir(uid, kstrings.EscapeQualifiedNameForDisk(gcePersistentDiskPluginName), volName) } @@ -104,7 +118,7 @@ func (plugin *gcePersistentDiskPlugin) GetAccessModes() []v1.PersistentVolumeAcc func (plugin *gcePersistentDiskPlugin) GetVolumeLimits() (map[string]int64, error) { volumeLimits := map[string]int64{ - util.GCEVolumeLimitKey: 16, + util.GCEVolumeLimitKey: VolumeLimit16, } cloud := plugin.host.GetCloudProvider() @@ -120,6 +134,33 @@ func (plugin *gcePersistentDiskPlugin) GetVolumeLimits() (map[string]int64, erro return nil, fmt.Errorf("Expected gce cloud got %s", cloud.ProviderName()) } + instances, ok := cloud.Instances() + if !ok { + glog.Warning("Failed to get instances from cloud provider") + return volumeLimits, nil + } + + instanceType, err := instances.InstanceType(context.TODO(), plugin.host.GetNodeName()) + if err != nil { + glog.Errorf("Failed to get instance type from GCE cloud provider") + return volumeLimits, nil + } + if strings.HasPrefix(instanceType, "n1-") { + splits := strings.Split(instanceType, "-") + if len(splits) < 3 { + return volumeLimits, nil + } + last := splits[2] + if num, err := strconv.Atoi(last); err == nil { + if num == OneCPU { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit32 + } else if num < EightCPUs { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit64 + } else { + volumeLimits[util.GCEVolumeLimitKey] = VolumeLimit128 + } + } + } return volumeLimits, nil }