Merge pull request #57017 from andyzhangx/azurefile-growsize
Automatic merge from submit-queue. If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. add PV size grow feature for azure file **What this PR does / why we need it**: According to kubernetes/features#284, add size grow feature for azure file **Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*: Fixes #56462 **Special notes for your reviewer**: Since azure file is using SMB 3.0 protocal, there is no necessary to resize filesystem on agent side, the agent node will detect the changed size automatically. **Release note**: ``` add size grow feature for azure file ``` /sig azure @gnufied @rootfs @brendandburns
This commit is contained in:
commit
ffda1e2200
@ -102,6 +102,7 @@ func ProbeExpandableVolumePlugins(config componentconfig.VolumeConfiguration) []
|
||||
allPlugins = append(allPlugins, glusterfs.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, rbd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, azure_dd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, azure_file.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, photon_pd.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, scaleio.ProbeVolumePlugins()...)
|
||||
allPlugins = append(allPlugins, storageos.ProbeVolumePlugins()...)
|
||||
|
@ -930,7 +930,7 @@ func (fRTC *fakeRouteTablesClient) Get(resourceGroupName string, routeTableName
|
||||
type fakeFileClient struct {
|
||||
}
|
||||
|
||||
func (fFC *fakeFileClient) createFileShare(accountName, accountKey, name string, sizeGB int) error {
|
||||
func (fFC *fakeFileClient) createFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -938,6 +938,10 @@ func (fFC *fakeFileClient) deleteFileShare(accountName, accountKey, name string)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fFC *fakeFileClient) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type fakeStorageAccountClient struct {
|
||||
mutex *sync.Mutex
|
||||
FakeStore map[string]map[string]storage.Account
|
||||
|
@ -31,24 +31,29 @@ const (
|
||||
// FileClient is the interface for creating file shares, interface for test
|
||||
// injection.
|
||||
type FileClient interface {
|
||||
createFileShare(accountName, accountKey, name string, sizeGB int) error
|
||||
createFileShare(accountName, accountKey, name string, sizeGiB int) error
|
||||
deleteFileShare(accountName, accountKey, name string) error
|
||||
resizeFileShare(accountName, accountKey, name string, sizeGiB int) error
|
||||
}
|
||||
|
||||
// create file share
|
||||
func (az *Cloud) createFileShare(accountName, accountKey, name string, sizeGB int) error {
|
||||
return az.FileClient.createFileShare(accountName, accountKey, name, sizeGB)
|
||||
func (az *Cloud) createFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
return az.FileClient.createFileShare(accountName, accountKey, name, sizeGiB)
|
||||
}
|
||||
|
||||
func (az *Cloud) deleteFileShare(accountName, accountKey, name string) error {
|
||||
return az.FileClient.deleteFileShare(accountName, accountKey, name)
|
||||
}
|
||||
|
||||
func (az *Cloud) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
return az.FileClient.resizeFileShare(accountName, accountKey, name, sizeGiB)
|
||||
}
|
||||
|
||||
type azureFileClient struct {
|
||||
env azure.Environment
|
||||
}
|
||||
|
||||
func (f *azureFileClient) createFileShare(accountName, accountKey, name string, sizeGB int) error {
|
||||
func (f *azureFileClient) createFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
fileClient, err := f.getFileSvcClient(accountName, accountKey)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -62,7 +67,7 @@ func (f *azureFileClient) createFileShare(accountName, accountKey, name string,
|
||||
if err = share.Create(nil); err != nil {
|
||||
return fmt.Errorf("failed to create file share, err: %v", err)
|
||||
}
|
||||
share.Properties.Quota = sizeGB
|
||||
share.Properties.Quota = sizeGiB
|
||||
if err = share.SetProperties(nil); err != nil {
|
||||
if err := share.Delete(nil); err != nil {
|
||||
glog.Errorf("Error deleting share: %v", err)
|
||||
@ -81,6 +86,25 @@ func (f *azureFileClient) deleteFileShare(accountName, accountKey, name string)
|
||||
return fileClient.GetShareReference(name).Delete(nil)
|
||||
}
|
||||
|
||||
func (f *azureFileClient) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
fileClient, err := f.getFileSvcClient(accountName, accountKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
share := fileClient.GetShareReference(name)
|
||||
if share.Properties.Quota >= sizeGiB {
|
||||
glog.Warningf("file share size(%dGi) is already greater or equal than requested size(%dGi), accountName: %s, shareName: %s",
|
||||
share.Properties.Quota, sizeGiB, accountName, name)
|
||||
return nil
|
||||
}
|
||||
share.Properties.Quota = sizeGiB
|
||||
if err = share.SetProperties(nil); err != nil {
|
||||
return fmt.Errorf("failed to set quota on file share %s, err: %v", name, err)
|
||||
}
|
||||
glog.V(4).Infof("resize file share completed, accountName: %s, shareName: %s, sizeGiB: %d", accountName, name, sizeGiB)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *azureFileClient) getFileSvcClient(accountName, accountKey string) (*azs.FileServiceClient, error) {
|
||||
fileClient, err := azs.NewClient(accountName, accountKey, f.env.StorageEndpointSuffix, azs.DefaultAPIVersion, useHTTPS)
|
||||
if err != nil {
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
// CreateFileShare creates a file share, using a matching storage account
|
||||
func (az *Cloud) CreateFileShare(name, storageAccount, storageType, location string, requestGB int) (string, string, error) {
|
||||
func (az *Cloud) CreateFileShare(name, storageAccount, storageType, location string, requestGiB int) (string, string, error) {
|
||||
var errResult error
|
||||
accounts := []accountWithLocation{}
|
||||
if len(storageAccount) > 0 {
|
||||
@ -46,7 +46,7 @@ func (az *Cloud) CreateFileShare(name, storageAccount, storageType, location str
|
||||
continue
|
||||
}
|
||||
|
||||
if innerErr = az.createFileShare(account.Name, key, name, requestGB); innerErr != nil {
|
||||
if innerErr = az.createFileShare(account.Name, key, name, requestGiB); innerErr != nil {
|
||||
errResult = fmt.Errorf("failed to create share %s in account %s: %v", name, account.Name, innerErr)
|
||||
continue
|
||||
}
|
||||
@ -69,3 +69,8 @@ func (az *Cloud) DeleteFileShare(accountName, key, name string) error {
|
||||
glog.V(4).Infof("share %s deleted", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ResizeFileShare resizes a file share
|
||||
func (az *Cloud) ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error {
|
||||
return az.resizeFileShare(accountName, accountKey, name, sizeGiB)
|
||||
}
|
||||
|
@ -21,16 +21,16 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/azure"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
kstrings "k8s.io/kubernetes/pkg/util/strings"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/azure"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
||||
@ -45,6 +45,7 @@ type azureFilePlugin struct {
|
||||
|
||||
var _ volume.VolumePlugin = &azureFilePlugin{}
|
||||
var _ volume.PersistentVolumePlugin = &azureFilePlugin{}
|
||||
var _ volume.ExpandableVolumePlugin = &azureFilePlugin{}
|
||||
|
||||
const (
|
||||
azureFilePluginName = "kubernetes.io/azure-file"
|
||||
@ -139,6 +140,41 @@ func (plugin *azureFilePlugin) newUnmounterInternal(volName string, podUID types
|
||||
}}, nil
|
||||
}
|
||||
|
||||
func (plugin *azureFilePlugin) RequiresFSResize() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (plugin *azureFilePlugin) ExpandVolumeDevice(
|
||||
spec *volume.Spec,
|
||||
newSize resource.Quantity,
|
||||
oldSize resource.Quantity) (resource.Quantity, error) {
|
||||
|
||||
if spec.PersistentVolume != nil || spec.PersistentVolume.Spec.AzureFile == nil {
|
||||
return oldSize, fmt.Errorf("invalid PV spec")
|
||||
}
|
||||
shareName := spec.PersistentVolume.Spec.AzureFile.ShareName
|
||||
azure, err := getAzureCloudProvider(plugin.host.GetCloudProvider())
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
secretName, secretNamespace, err := getSecretNameAndNamespace(spec, spec.PersistentVolume.Spec.ClaimRef.Namespace)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
accountName, accountKey, err := (&azureSvc{}).GetAzureCredentials(plugin.host, secretNamespace, secretName)
|
||||
if err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
if err := azure.ResizeFileShare(accountName, accountKey, shareName, int(volume.RoundUpToGiB(newSize))); err != nil {
|
||||
return oldSize, err
|
||||
}
|
||||
|
||||
return newSize, nil
|
||||
}
|
||||
|
||||
func (plugin *azureFilePlugin) ConstructVolumeSpec(volName, mountPath string) (*volume.Spec, error) {
|
||||
azureVolume := &v1.Volume{
|
||||
Name: volName,
|
||||
|
@ -38,9 +38,11 @@ var _ volume.ProvisionableVolumePlugin = &azureFilePlugin{}
|
||||
// azure cloud provider should implement it
|
||||
type azureCloudProvider interface {
|
||||
// create a file share
|
||||
CreateFileShare(name, storageAccount, storageType, location string, requestGB int) (string, string, error)
|
||||
CreateFileShare(name, storageAccount, storageType, location string, requestGiB int) (string, string, error)
|
||||
// delete a file share
|
||||
DeleteFileShare(accountName, key, name string) error
|
||||
// resize a file share
|
||||
ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error
|
||||
}
|
||||
|
||||
type azureFileDeleter struct {
|
||||
@ -141,7 +143,7 @@ func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) {
|
||||
name = strings.Replace(name, "--", "-", -1)
|
||||
capacity := a.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)]
|
||||
requestBytes := capacity.Value()
|
||||
requestGB := int(volume.RoundUpSize(requestBytes, 1024*1024*1024))
|
||||
requestGiB := int(volume.RoundUpSize(requestBytes, 1024*1024*1024))
|
||||
secretNamespace := a.options.PVC.Namespace
|
||||
// Apply ProvisionerParameters (case-insensitive). We leave validation of
|
||||
// the values to the cloud provider.
|
||||
@ -164,7 +166,7 @@ func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) {
|
||||
return nil, fmt.Errorf("claim.Spec.Selector is not supported for dynamic provisioning on Azure file")
|
||||
}
|
||||
|
||||
account, key, err := a.azureProvider.CreateFileShare(name, account, sku, location, requestGB)
|
||||
account, key, err := a.azureProvider.CreateFileShare(name, account, sku, location, requestGiB)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -187,7 +189,7 @@ func (a *azureFileProvisioner) Provision() (*v1.PersistentVolume, error) {
|
||||
PersistentVolumeReclaimPolicy: a.options.PersistentVolumeReclaimPolicy,
|
||||
AccessModes: a.options.PVC.Spec.AccessModes,
|
||||
Capacity: v1.ResourceList{
|
||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", requestGB)),
|
||||
v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", requestGiB)),
|
||||
},
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{
|
||||
AzureFile: &v1.AzureFilePersistentVolumeSource{
|
||||
|
@ -161,5 +161,8 @@ func (pvcr *persistentVolumeClaimResize) checkVolumePlugin(pv *api.PersistentVol
|
||||
return true
|
||||
}
|
||||
|
||||
if pv.Spec.AzureFile != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user