mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 21:47:07 +00:00
Implement resizing support for GCE
Fix GCE attacher test Update bazel files
This commit is contained in:
parent
2f2a643684
commit
7be94c4b06
@ -67,6 +67,7 @@ go_library(
|
|||||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||||
"//vendor/gopkg.in/gcfg.v1:go_default_library",
|
"//vendor/gopkg.in/gcfg.v1:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||||
@ -90,6 +91,9 @@ type diskServiceManager interface {
|
|||||||
instanceName string,
|
instanceName string,
|
||||||
devicePath string) (gceObject, error)
|
devicePath string) (gceObject, error)
|
||||||
|
|
||||||
|
ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error)
|
||||||
|
RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error)
|
||||||
|
|
||||||
// Gets the persistent disk from GCE with the given diskName.
|
// Gets the persistent disk from GCE with the given diskName.
|
||||||
GetDiskFromCloudProvider(zone string, diskName string) (*GCEDisk, error)
|
GetDiskFromCloudProvider(zone string, diskName string) (*GCEDisk, error)
|
||||||
|
|
||||||
@ -264,6 +268,7 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider(
|
|||||||
Name: diskAlpha.Name,
|
Name: diskAlpha.Name,
|
||||||
Kind: diskAlpha.Kind,
|
Kind: diskAlpha.Kind,
|
||||||
Type: diskAlpha.Type,
|
Type: diskAlpha.Type,
|
||||||
|
SizeGb: diskAlpha.SizeGb,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -289,6 +294,7 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider(
|
|||||||
Name: diskStable.Name,
|
Name: diskStable.Name,
|
||||||
Kind: diskStable.Kind,
|
Kind: diskStable.Kind,
|
||||||
Type: diskStable.Type,
|
Type: diskStable.Type,
|
||||||
|
SizeGb: diskStable.SizeGb,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -313,6 +319,7 @@ func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider(
|
|||||||
Name: diskAlpha.Name,
|
Name: diskAlpha.Name,
|
||||||
Kind: diskAlpha.Kind,
|
Kind: diskAlpha.Kind,
|
||||||
Type: diskAlpha.Type,
|
Type: diskAlpha.Type,
|
||||||
|
SizeGb: diskAlpha.SizeGb,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -469,6 +476,30 @@ func (manager *gceServiceManager) getRegionFromZone(zoneInfo zoneType) (string,
|
|||||||
return region, nil
|
return region, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error) {
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||||
|
resizeServiceRequest := &computealpha.DisksResizeRequest{
|
||||||
|
SizeGb: sizeGb,
|
||||||
|
}
|
||||||
|
return manager.gce.serviceAlpha.Disks.Resize(manager.gce.projectID, zone, disk.Name, resizeServiceRequest).Do()
|
||||||
|
|
||||||
|
}
|
||||||
|
resizeServiceRequest := &compute.DisksResizeRequest{
|
||||||
|
SizeGb: sizeGb,
|
||||||
|
}
|
||||||
|
return manager.gce.service.Disks.Resize(manager.gce.projectID, zone, disk.Name, resizeServiceRequest).Do()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *gceServiceManager) RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error) {
|
||||||
|
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||||
|
resizeServiceRequest := &computealpha.RegionDisksResizeRequest{
|
||||||
|
SizeGb: sizeGb,
|
||||||
|
}
|
||||||
|
return manager.gce.serviceAlpha.RegionDisks.Resize(manager.gce.projectID, disk.Region, disk.Name, resizeServiceRequest).Do()
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("RegionalResizeDiskOnCloudProvider is a regional PD feature and is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||||
|
}
|
||||||
|
|
||||||
// Disks is interface for manipulation with GCE PDs.
|
// Disks is interface for manipulation with GCE PDs.
|
||||||
type Disks interface {
|
type Disks interface {
|
||||||
// AttachDisk attaches given disk to the node with the specified NodeName.
|
// AttachDisk attaches given disk to the node with the specified NodeName.
|
||||||
@ -498,6 +529,9 @@ type Disks interface {
|
|||||||
// DeleteDisk deletes PD.
|
// DeleteDisk deletes PD.
|
||||||
DeleteDisk(diskToDelete string) error
|
DeleteDisk(diskToDelete string) error
|
||||||
|
|
||||||
|
// ResizeDisk resizes PD and returns new disk size
|
||||||
|
ResizeDisk(diskToResize string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error)
|
||||||
|
|
||||||
// GetAutoLabelsForPD returns labels to apply to PersistentVolume
|
// GetAutoLabelsForPD returns labels to apply to PersistentVolume
|
||||||
// representing this PD, namely failure domain and zone.
|
// representing this PD, namely failure domain and zone.
|
||||||
// zone can be provided to specify the zone for the PD,
|
// zone can be provided to specify the zone for the PD,
|
||||||
@ -517,6 +551,7 @@ type GCEDisk struct {
|
|||||||
Name string
|
Name string
|
||||||
Kind string
|
Kind string
|
||||||
Type string
|
Type string
|
||||||
|
SizeGb int64
|
||||||
}
|
}
|
||||||
|
|
||||||
type zoneType interface {
|
type zoneType interface {
|
||||||
@ -801,6 +836,57 @@ func (gce *GCECloud) DeleteDisk(diskToDelete string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResizeDisk expands given disk and returns new disk size
|
||||||
|
func (gce *GCECloud) ResizeDisk(diskToResize string, oldSize resource.Quantity, newSize resource.Quantity) (resource.Quantity, error) {
|
||||||
|
disk, err := gce.GetDiskByNameUnknownZone(diskToResize)
|
||||||
|
if err != nil {
|
||||||
|
return oldSize, err
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBytes := newSize.Value()
|
||||||
|
// GCE resizes in chunks of GBs (not GiB)
|
||||||
|
requestGB := volume.RoundUpSize(requestBytes, 1000*1000*1000)
|
||||||
|
newSizeQuant := resource.MustParse(fmt.Sprintf("%dG", requestGB))
|
||||||
|
|
||||||
|
// If disk is already of size equal or greater than requested size, we simply return
|
||||||
|
if disk.SizeGb >= requestGB {
|
||||||
|
return newSizeQuant, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var mc *metricContext
|
||||||
|
|
||||||
|
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||||
|
case singleZone:
|
||||||
|
mc = newDiskMetricContextZonal("resize", disk.Region, zoneInfo.zone)
|
||||||
|
resizeOp, err := gce.manager.ResizeDiskOnCloudProvider(disk, requestGB, zoneInfo.zone)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return oldSize, mc.Observe(err)
|
||||||
|
}
|
||||||
|
waitErr := gce.manager.WaitForZoneOp(resizeOp, zoneInfo.zone, mc)
|
||||||
|
if waitErr != nil {
|
||||||
|
return oldSize, waitErr
|
||||||
|
}
|
||||||
|
return newSizeQuant, nil
|
||||||
|
case multiZone:
|
||||||
|
mc = newDiskMetricContextRegional("resize", disk.Region)
|
||||||
|
resizeOp, err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGB)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return oldSize, mc.Observe(err)
|
||||||
|
}
|
||||||
|
waitErr := gce.manager.WaitForRegionalOp(resizeOp, mc)
|
||||||
|
if waitErr != nil {
|
||||||
|
return oldSize, waitErr
|
||||||
|
}
|
||||||
|
return newSizeQuant, nil
|
||||||
|
case nil:
|
||||||
|
return oldSize, fmt.Errorf("PD has nil ZoneInfo: %v", disk)
|
||||||
|
default:
|
||||||
|
return oldSize, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Builds the labels that should be automatically added to a PersistentVolume backed by a GCE PD
|
// Builds the labels that should be automatically added to a PersistentVolume backed by a GCE PD
|
||||||
// Specifically, this builds FailureDomain (zone) and Region labels.
|
// Specifically, this builds FailureDomain (zone) and Region labels.
|
||||||
// The PersistentVolumeLabel admission controller calls this and adds the labels when a PV is created.
|
// The PersistentVolumeLabel admission controller calls this and adds the labels when a PV is created.
|
||||||
|
@ -897,6 +897,19 @@ func (manager *FakeServiceManager) GetRegionalDiskFromCloudProvider(
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (manager *FakeServiceManager) ResizeDiskOnCloudProvider(
|
||||||
|
disk *GCEDisk,
|
||||||
|
size int64,
|
||||||
|
zone string) (gceObject, error) {
|
||||||
|
panic("Not implmented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (manager *FakeServiceManager) RegionalResizeDiskOnCloudProvider(
|
||||||
|
disk *GCEDisk,
|
||||||
|
size int64) (gceObject, error) {
|
||||||
|
panic("Not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disk info is removed from the FakeServiceManager.
|
* Disk info is removed from the FakeServiceManager.
|
||||||
*/
|
*/
|
||||||
|
@ -47,6 +47,7 @@ go_test(
|
|||||||
"//pkg/volume/testing:go_default_library",
|
"//pkg/volume/testing:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/api/core/v1"
|
"k8s.io/api/core/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||||
@ -373,3 +374,10 @@ func (testcase *testcase) DeleteDisk(diskToDelete string) error {
|
|||||||
func (testcase *testcase) GetAutoLabelsForPD(name string, zone string) (map[string]string, error) {
|
func (testcase *testcase) GetAutoLabelsForPD(name string, zone string) (map[string]string, error) {
|
||||||
return map[string]string{}, errors.New("Not implemented")
|
return map[string]string{}, errors.New("Not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (testcase *testcase) ResizeDisk(
|
||||||
|
diskName string,
|
||||||
|
oldSize resource.Quantity,
|
||||||
|
newSize resource.Quantity) (resource.Quantity, error) {
|
||||||
|
return oldSize, errors.New("Not implemented")
|
||||||
|
}
|
||||||
|
@ -47,6 +47,7 @@ var _ volume.VolumePlugin = &gcePersistentDiskPlugin{}
|
|||||||
var _ volume.PersistentVolumePlugin = &gcePersistentDiskPlugin{}
|
var _ volume.PersistentVolumePlugin = &gcePersistentDiskPlugin{}
|
||||||
var _ volume.DeletableVolumePlugin = &gcePersistentDiskPlugin{}
|
var _ volume.DeletableVolumePlugin = &gcePersistentDiskPlugin{}
|
||||||
var _ volume.ProvisionableVolumePlugin = &gcePersistentDiskPlugin{}
|
var _ volume.ProvisionableVolumePlugin = &gcePersistentDiskPlugin{}
|
||||||
|
var _ volume.ExpandableVolumePlugin = &gcePersistentDiskPlugin{}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gcePersistentDiskPluginName = "kubernetes.io/gce-pd"
|
gcePersistentDiskPluginName = "kubernetes.io/gce-pd"
|
||||||
@ -190,6 +191,28 @@ func (plugin *gcePersistentDiskPlugin) newProvisionerInternal(options volume.Vol
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (plugin *gcePersistentDiskPlugin) RequiresFSResize() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (plugin *gcePersistentDiskPlugin) ExpandVolumeDevice(
|
||||||
|
spec *volume.Spec,
|
||||||
|
newSize resource.Quantity,
|
||||||
|
oldSize resource.Quantity) (resource.Quantity, error) {
|
||||||
|
cloud, err := getCloudProvider(plugin.host.GetCloudProvider())
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return oldSize, err
|
||||||
|
}
|
||||||
|
pdName := spec.PersistentVolume.Spec.GCEPersistentDisk.PDName
|
||||||
|
updatedQuantity, err := cloud.ResizeDisk(pdName, oldSize, newSize)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return oldSize, err
|
||||||
|
}
|
||||||
|
return updatedQuantity, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (plugin *gcePersistentDiskPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
|
func (plugin *gcePersistentDiskPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) {
|
||||||
mounter := plugin.host.GetMounter(plugin.GetPluginName())
|
mounter := plugin.host.GetMounter(plugin.GetPluginName())
|
||||||
pluginDir := plugin.host.GetPluginDir(plugin.GetPluginName())
|
pluginDir := plugin.host.GetPluginDir(plugin.GetPluginName())
|
||||||
|
@ -454,8 +454,9 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
|||||||
|
|
||||||
glog.Infof(volumeToMount.GenerateMsgDetailed("MountVolume.WaitForAttach succeeded", fmt.Sprintf("DevicePath %q", devicePath)))
|
glog.Infof(volumeToMount.GenerateMsgDetailed("MountVolume.WaitForAttach succeeded", fmt.Sprintf("DevicePath %q", devicePath)))
|
||||||
|
|
||||||
mounter := og.volumePluginMgr.Host.GetMounter(volumePlugin.GetPluginName())
|
// resizeFileSystem will resize the file system if user has requested a resize of
|
||||||
resizeError := og.resizeFileSystem(volumeToMount, devicePath, mounter)
|
// underlying persistent volume and is allowed to do so.
|
||||||
|
resizeError := og.resizeFileSystem(volumeToMount, devicePath, volumePlugin.GetPluginName())
|
||||||
|
|
||||||
if resizeError != nil {
|
if resizeError != nil {
|
||||||
return volumeToMount.GenerateErrorDetailed("MountVolume.Resize failed", resizeError)
|
return volumeToMount.GenerateErrorDetailed("MountVolume.Resize failed", resizeError)
|
||||||
@ -538,12 +539,12 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
|||||||
}, volumePlugin.GetPluginName(), nil
|
}, volumePlugin.GetPluginName(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (og *operationGenerator) resizeFileSystem(volumeToMount VolumeToMount, devicePath string, mounter mount.Interface) error {
|
func (og *operationGenerator) resizeFileSystem(volumeToMount VolumeToMount, devicePath string, pluginName string) error {
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||||
glog.V(6).Infof("Resizing is not enabled for this volume %s", volumeToMount.VolumeName)
|
glog.V(6).Infof("Resizing is not enabled for this volume %s", volumeToMount.VolumeName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
mounter := og.volumePluginMgr.Host.GetMounter(pluginName)
|
||||||
// Get expander, if possible
|
// Get expander, if possible
|
||||||
expandableVolumePlugin, _ :=
|
expandableVolumePlugin, _ :=
|
||||||
og.volumePluginMgr.FindExpandablePluginBySpec(volumeToMount.VolumeSpec)
|
og.volumePluginMgr.FindExpandablePluginBySpec(volumeToMount.VolumeSpec)
|
||||||
|
@ -155,6 +155,10 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
|
|||||||
if pv.Spec.Cinder != nil {
|
if pv.Spec.Cinder != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pv.Spec.GCEPersistentDisk != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return false
|
return false
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user