Skip to content

Commit 03c7c53

Browse files
committed
feat: create blob container using management api by default
fix: dataplane api issue fix fix swtich to cloud provider lib interface fix: retry if CreateContainer failed with container being deleted fix retry when create container failed enable cloud provider backoff by default support management api for delete and get container operations add more validation add useDataPlaneAPI e2e test add unit tests
1 parent 3b13760 commit 03c7c53

File tree

7 files changed

+261
-118
lines changed

7 files changed

+261
-118
lines changed

docs/driver-parameters.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ allowBlobPublicAccess | Allow or disallow public access to all blobs or containe
2020
storageEndpointSuffix | specify Azure storage endpoint suffix | `core.windows.net`, `core.chinacloudapi.cn`, etc | No | if empty, driver will use default storage endpoint suffix according to cloud environment
2121
tags | [tags](https://docs.microsoft.com/en-us/azure/azure-resource-manager/management/tag-resources) would be created in newly created storage account | tag format: 'foo=aaa,bar=bbb' | No | ""
2222
matchTags | whether matching tags when driver tries to find a suitable storage account | `true`,`false` | No | `false`
23+
useDataPlaneAPI | specify whether use data plane API for blob container create/delete, this could solve the SRP API throltting issue since data plane API has almost no limit, while it would fail when there is firewall or vnet setting on storage account | `true`,`false` | No | `false`
2324
--- | **Following parameters are only for blobfuse** | --- | --- |
2425
subscriptionID | specify Azure subscription ID in which blob storage directory will be created | Azure subscription ID | No | if not empty, `resourceGroup` must be provided
2526
storeAccountKey | whether store account key to k8s secret <br><br> Note: <br> `false` means driver would leverage kubelet identity to get account key | `true`,`false` | No | `true`

pkg/blob/azure.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func getCloudProvider(kubeconfig, nodeID, secretName, secretNamespace, userAgent
116116
}
117117
} else {
118118
config.UserAgent = userAgent
119+
config.CloudProviderBackoff = true
119120
if err = az.InitializeCloudFromConfig(config, fromSecret, false); err != nil {
120121
klog.Warningf("InitializeCloudFromConfig failed with error: %v", err)
121122
}

pkg/blob/blob.go

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,11 @@ import (
2323
"sync"
2424
"time"
2525

26-
"golang.org/x/net/context"
27-
26+
azstorage "github.com/Azure/azure-sdk-for-go/storage"
27+
az "github.com/Azure/go-autorest/autorest/azure"
2828
"github.com/container-storage-interface/spec/lib/go/csi"
2929
"github.com/pborman/uuid"
30+
"golang.org/x/net/context"
3031

3132
v1 "k8s.io/api/core/v1"
3233
"k8s.io/apimachinery/pkg/api/errors"
@@ -88,17 +89,19 @@ const (
8889
vnetNameField = "vnetname"
8990
subnetNameField = "subnetname"
9091
mountPermissionsField = "mountpermissions"
92+
useDataPlaneAPIField = "usedataplaneapi"
9193

9294
// See https://docs.microsoft.com/en-us/rest/api/storageservices/naming-and-referencing-containers--blobs--and-metadata#container-names
9395
containerNameMinLength = 3
9496
containerNameMaxLength = 63
9597

96-
accountNotProvisioned = "StorageAccountIsNotProvisioned"
97-
tooManyRequests = "TooManyRequests"
98-
clientThrottled = "client throttled"
99-
containerBeingDeleted = "ContainerBeingDeleted"
100-
statusCodeNotFound = "StatusCode=404"
101-
httpCodeNotFound = "HTTPStatusCode: 404"
98+
accountNotProvisioned = "StorageAccountIsNotProvisioned"
99+
tooManyRequests = "TooManyRequests"
100+
clientThrottled = "client throttled"
101+
containerBeingDeletedDataplaneAPIError = "ContainerBeingDeleted"
102+
containerBeingDeletedManagementAPIError = "container is being deleted"
103+
statusCodeNotFound = "StatusCode=404"
104+
httpCodeNotFound = "HTTPStatusCode: 404"
102105

103106
// containerMaxSize is the max size of the blob container. See https://docs.microsoft.com/en-us/azure/storage/blobs/scalability-targets#scale-targets-for-blob-storage
104107
containerMaxSize = 100 * util.TiB
@@ -116,7 +119,7 @@ const (
116119

117120
var (
118121
supportedProtocolList = []string{fuse, nfs}
119-
retriableErrors = []string{accountNotProvisioned, tooManyRequests, statusCodeNotFound, containerBeingDeleted, clientThrottled}
122+
retriableErrors = []string{accountNotProvisioned, tooManyRequests, statusCodeNotFound, containerBeingDeletedDataplaneAPIError, containerBeingDeletedManagementAPIError, clientThrottled}
120123
)
121124

122125
// DriverOptions defines driver parameters specified in driver deployment
@@ -166,6 +169,8 @@ type Driver struct {
166169
subnetLockMap *util.LockMap
167170
// a map storing all volumes created by this driver <volumeName, accountName>
168171
volMap sync.Map
172+
// a map storing all volumes using data plane API <volumeID, "">, <accountName, "">
173+
dataPlaneAPIVolMap sync.Map
169174
// a timed cache storing account search history (solve account list throttling issue)
170175
accountSearchCache *azcache.TimedCache
171176
}
@@ -625,6 +630,23 @@ func getStorageAccount(secrets map[string]string) (string, string, error) {
625630
return accountName, accountKey, nil
626631
}
627632

633+
func getContainerReference(containerName string, secrets map[string]string, env az.Environment) (*azstorage.Container, error) {
634+
accountName, accountKey, rerr := getStorageAccount(secrets)
635+
if rerr != nil {
636+
return nil, rerr
637+
}
638+
client, err := azstorage.NewBasicClientOnSovereignCloud(accountName, accountKey, env)
639+
if err != nil {
640+
return nil, err
641+
}
642+
blobClient := client.GetBlobService()
643+
container := blobClient.GetContainerReference(containerName)
644+
if container == nil {
645+
return nil, fmt.Errorf("ContainerReference of %s is nil", containerName)
646+
}
647+
return container, nil
648+
}
649+
628650
func setAzureCredentials(kubeClient kubernetes.Interface, accountName, accountKey, secretNamespace string) (string, error) {
629651
if kubeClient == nil {
630652
klog.Warningf("could not create secret: kubeClient is nil")
@@ -710,6 +732,14 @@ func (d *Driver) getSubnetResourceID() string {
710732
return fmt.Sprintf(subnetTemplate, subsID, rg, d.cloud.VnetName, d.cloud.SubnetName)
711733
}
712734

735+
func (d *Driver) useDataPlaneAPI(volumeID, accountName string) bool {
736+
_, useDataPlaneAPI := d.dataPlaneAPIVolMap.Load(volumeID)
737+
if !useDataPlaneAPI {
738+
_, useDataPlaneAPI = d.dataPlaneAPIVolMap.Load(accountName)
739+
}
740+
return useDataPlaneAPI
741+
}
742+
713743
// appendDefaultMountOptions return mount options combined with mountOptions and defaultMountOptions
714744
func appendDefaultMountOptions(mountOptions []string, tmpPath, containerName string) []string {
715745
var defaultMountOptions = map[string]string{
@@ -766,3 +796,10 @@ func chmodIfPermissionMismatch(targetPath string, mode os.FileMode) error {
766796
}
767797
return nil
768798
}
799+
800+
func createStorageAccountSecret(account, key string) map[string]string {
801+
secret := make(map[string]string)
802+
secret[defaultSecretAccountName] = account
803+
secret[defaultSecretAccountKey] = key
804+
return secret
805+
}

pkg/blob/blob_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -943,3 +943,10 @@ func getWorkDirPath(dir string) (string, error) {
943943
}
944944
return fmt.Sprintf("%s%c%s", path, os.PathSeparator, dir), nil
945945
}
946+
947+
func TestCreateStorageAccountSecret(t *testing.T) {
948+
result := createStorageAccountSecret("TestAccountName", "TestAccountKey")
949+
if result[defaultSecretAccountName] != "TestAccountName" || result[defaultSecretAccountKey] != "TestAccountKey" {
950+
t.Errorf("Expected account name(%s), Actual account name(%s); Expected account key(%s), Actual account key(%s)", "TestAccountName", result[defaultSecretAccountName], "TestAccountKey", result[defaultSecretAccountKey])
951+
}
952+
}

0 commit comments

Comments
 (0)