mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 04:33:26 +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/gopkg.in/gcfg.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/fields:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
@ -90,6 +91,9 @@ type diskServiceManager interface {
|
||||
instanceName string,
|
||||
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.
|
||||
GetDiskFromCloudProvider(zone string, diskName string) (*GCEDisk, error)
|
||||
|
||||
@ -264,6 +268,7 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider(
|
||||
Name: diskAlpha.Name,
|
||||
Kind: diskAlpha.Kind,
|
||||
Type: diskAlpha.Type,
|
||||
SizeGb: diskAlpha.SizeGb,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -289,6 +294,7 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider(
|
||||
Name: diskStable.Name,
|
||||
Kind: diskStable.Kind,
|
||||
Type: diskStable.Type,
|
||||
SizeGb: diskStable.SizeGb,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -313,6 +319,7 @@ func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider(
|
||||
Name: diskAlpha.Name,
|
||||
Kind: diskAlpha.Kind,
|
||||
Type: diskAlpha.Type,
|
||||
SizeGb: diskAlpha.SizeGb,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@ -469,6 +476,30 @@ func (manager *gceServiceManager) getRegionFromZone(zoneInfo zoneType) (string,
|
||||
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.
|
||||
type Disks interface {
|
||||
// AttachDisk attaches given disk to the node with the specified NodeName.
|
||||
@ -498,6 +529,9 @@ type Disks interface {
|
||||
// DeleteDisk deletes PD.
|
||||
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
|
||||
// representing this PD, namely failure domain and zone.
|
||||
// zone can be provided to specify the zone for the PD,
|
||||
@ -517,6 +551,7 @@ type GCEDisk struct {
|
||||
Name string
|
||||
Kind string
|
||||
Type string
|
||||
SizeGb int64
|
||||
}
|
||||
|
||||
type zoneType interface {
|
||||
@ -801,6 +836,57 @@ func (gce *GCECloud) DeleteDisk(diskToDelete string) error {
|
||||
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
|
||||
// Specifically, this builds FailureDomain (zone) and Region labels.
|
||||
// The PersistentVolumeLabel admission controller calls this and adds the labels when a PV is created.
|
||||
|
@ -897,6 +897,19 @@ func (manager *FakeServiceManager) GetRegionalDiskFromCloudProvider(
|
||||
}, 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.
|
||||
*/
|
||||
|
@ -47,6 +47,7 @@ go_test(
|
||||
"//pkg/volume/testing:go_default_library",
|
||||
"//vendor/github.com/golang/glog: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/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
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) {
|
||||
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.DeletableVolumePlugin = &gcePersistentDiskPlugin{}
|
||||
var _ volume.ProvisionableVolumePlugin = &gcePersistentDiskPlugin{}
|
||||
var _ volume.ExpandableVolumePlugin = &gcePersistentDiskPlugin{}
|
||||
|
||||
const (
|
||||
gcePersistentDiskPluginName = "kubernetes.io/gce-pd"
|
||||
@ -190,6 +191,28 @@ func (plugin *gcePersistentDiskPlugin) newProvisionerInternal(options volume.Vol
|
||||
}, 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) {
|
||||
mounter := plugin.host.GetMounter(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)))
|
||||
|
||||
mounter := og.volumePluginMgr.Host.GetMounter(volumePlugin.GetPluginName())
|
||||
resizeError := og.resizeFileSystem(volumeToMount, devicePath, mounter)
|
||||
// resizeFileSystem will resize the file system if user has requested a resize of
|
||||
// underlying persistent volume and is allowed to do so.
|
||||
resizeError := og.resizeFileSystem(volumeToMount, devicePath, volumePlugin.GetPluginName())
|
||||
|
||||
if resizeError != nil {
|
||||
return volumeToMount.GenerateErrorDetailed("MountVolume.Resize failed", resizeError)
|
||||
@ -538,12 +539,12 @@ func (og *operationGenerator) GenerateMountVolumeFunc(
|
||||
}, 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) {
|
||||
glog.V(6).Infof("Resizing is not enabled for this volume %s", volumeToMount.VolumeName)
|
||||
return nil
|
||||
}
|
||||
|
||||
mounter := og.volumePluginMgr.Host.GetMounter(pluginName)
|
||||
// Get expander, if possible
|
||||
expandableVolumePlugin, _ :=
|
||||
og.volumePluginMgr.FindExpandablePluginBySpec(volumeToMount.VolumeSpec)
|
||||
|
@ -155,6 +155,10 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
|
||||
if pv.Spec.Cinder != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
if pv.Spec.GCEPersistentDisk != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user