Skip to content

Commit 8a67466

Browse files
authored
Merge pull request #2769 from k8s-infra-cherrypick-robot/cherry-pick-2768-to-release-1.33
[release-1.33] fix: set default IOPS and throughput in v2 file share creation
2 parents 70093df + f0bf7c6 commit 8a67466

File tree

5 files changed

+266
-2
lines changed

5 files changed

+266
-2
lines changed

pkg/azurefile/azurefile.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ const (
209209
tagValueDelimiterField = "tagvaluedelimiter"
210210
// for data plane API
211211
oauth = "oauth"
212+
213+
standardv2 = "standardv2"
214+
premiumv2 = "premiumv2"
212215
)
213216

214217
var (

pkg/azurefile/controllerserver.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,14 @@ func (d *Driver) CreateVolume(ctx context.Context, req *csi.CreateVolumeRequest)
453453
// use v2 account kind for v2 sku
454454
if strings.Contains(strings.ToLower(sku), "v2") {
455455
accountKind = string(armstorage.KindFileStorage)
456+
if provisionedIops == nil {
457+
provisionedIops = getDefaultIOPS(fileShareSize, sku)
458+
klog.V(2).Infof("setting provisionedIops as %d", ptr.Deref(provisionedIops, 0))
459+
}
460+
if provisionedBandwidthMibps == nil {
461+
provisionedBandwidthMibps = getDefaultBandwidth(fileShareSize, sku)
462+
klog.V(2).Infof("setting provisionedBandwidthMibps as %d", ptr.Deref(provisionedBandwidthMibps, 0))
463+
}
456464
}
457465

458466
// replace pv/pvc name namespace metadata in fileShareName

pkg/azurefile/utils.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package azurefile
1919
import (
2020
"context"
2121
"fmt"
22+
"math"
2223
"os"
2324
"regexp"
2425
"strconv"
@@ -372,3 +373,45 @@ func removeOptionIfExists(options []string, removeOption string) ([]string, bool
372373
}
373374
return options, false
374375
}
376+
377+
// standardv2:
378+
//
379+
// MIN(MAX(1000 + CEILING(0.2 * ProvisionedStorageGiB), 500), 50000)
380+
//
381+
// premiumv2:
382+
//
383+
// MIN(MAX(3000 + CEILING(1 * ProvisionedStorageGiB), 3000), 102400)
384+
//
385+
// https://learn.microsoft.com/en-us/azure/storage/files/understanding-billing#provisioned-v2-provisioning-detail
386+
func getDefaultIOPS(requestGiB int, storageAccountType string) *int32 {
387+
var iops int32
388+
if strings.Contains(strings.ToLower(storageAccountType), standardv2) {
389+
iops = min(int32(math.Ceil(0.2*float64(requestGiB))+1000), 50000)
390+
} else if strings.Contains(strings.ToLower(storageAccountType), premiumv2) {
391+
iops = min(int32(requestGiB+3000), 102400)
392+
} else {
393+
return nil
394+
}
395+
return &iops
396+
}
397+
398+
// standardv2:
399+
//
400+
// MIN(MAX(60 + CEILING(0.02 * ProvisionedStorageGiB), 60), 5120)
401+
//
402+
// premiumv2:
403+
//
404+
// MIN(MAX(100 + CEILING(0.1 * ProvisionedStorageGiB), 100), 10340)
405+
//
406+
// https://learn.microsoft.com/en-us/azure/storage/files/understanding-billing#provisioned-v2-provisioning-detail
407+
func getDefaultBandwidth(requestGiB int, storageAccountType string) *int32 {
408+
var bandwidth int32
409+
if strings.Contains(strings.ToLower(storageAccountType), standardv2) {
410+
bandwidth = min(int32(math.Ceil(0.02*float64(requestGiB))+60), 5120)
411+
} else if strings.Contains(strings.ToLower(storageAccountType), premiumv2) {
412+
bandwidth = min(int32(math.Ceil(0.1*float64(requestGiB))+100), 10340)
413+
} else {
414+
return nil
415+
}
416+
return &bandwidth
417+
}

pkg/azurefile/utils_test.go

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,3 +1149,213 @@ func TestRemoveOptionIfExists(t *testing.T) {
11491149
}
11501150
}
11511151
}
1152+
1153+
func TestGetDefaultIOPS(t *testing.T) {
1154+
tests := []struct {
1155+
desc string
1156+
requestGiB int
1157+
storageAccountType string
1158+
expected *int32
1159+
}{
1160+
{
1161+
desc: "standardv2 with small storage",
1162+
requestGiB: 100,
1163+
storageAccountType: "StandardV2_LRS",
1164+
expected: int32Ptr(1020),
1165+
},
1166+
{
1167+
desc: "standardv2 with 1GiB storage",
1168+
requestGiB: 1,
1169+
storageAccountType: "StandardV2_LRS",
1170+
expected: int32Ptr(1001),
1171+
},
1172+
{
1173+
desc: "standardv2 with large storage hitting max",
1174+
requestGiB: 300000,
1175+
storageAccountType: "StandardV2_LRS",
1176+
expected: int32Ptr(50000),
1177+
},
1178+
{
1179+
desc: "standardv2 case insensitive",
1180+
requestGiB: 100,
1181+
storageAccountType: "STANDARDV2",
1182+
expected: int32Ptr(1020),
1183+
},
1184+
{
1185+
desc: "premiumv2 with small storage",
1186+
requestGiB: 100,
1187+
storageAccountType: "PremiumV2_LRS",
1188+
expected: int32Ptr(3100),
1189+
},
1190+
{
1191+
desc: "premiumv2 with 1GiB storage",
1192+
requestGiB: 1,
1193+
storageAccountType: "PremiumV2_LRS",
1194+
expected: int32Ptr(3001),
1195+
},
1196+
{
1197+
desc: "premiumv2 with large storage hitting max",
1198+
requestGiB: 200000,
1199+
storageAccountType: "PremiumV2_LRS",
1200+
expected: int32Ptr(102400),
1201+
},
1202+
{
1203+
desc: "premiumv2 case insensitive",
1204+
requestGiB: 100,
1205+
storageAccountType: "PREMIUMV2",
1206+
expected: int32Ptr(3100),
1207+
},
1208+
{
1209+
desc: "unsupported storage account type",
1210+
requestGiB: 100,
1211+
storageAccountType: "Standard_LRS",
1212+
expected: nil,
1213+
},
1214+
{
1215+
desc: "empty storage account type",
1216+
requestGiB: 100,
1217+
storageAccountType: "",
1218+
expected: nil,
1219+
},
1220+
{
1221+
desc: "standardv2 with zero storage",
1222+
requestGiB: 0,
1223+
storageAccountType: "StandardV2_LRS",
1224+
expected: int32Ptr(1000),
1225+
},
1226+
{
1227+
desc: "premiumv2 with zero storage",
1228+
requestGiB: 0,
1229+
storageAccountType: "PremiumV2_LRS",
1230+
expected: int32Ptr(3000),
1231+
},
1232+
}
1233+
1234+
for _, test := range tests {
1235+
result := getDefaultIOPS(test.requestGiB, test.storageAccountType)
1236+
if test.expected == nil {
1237+
if result != nil {
1238+
t.Errorf("test[%s]: unexpected output: %v, expected nil", test.desc, *result)
1239+
}
1240+
} else {
1241+
if result == nil {
1242+
t.Errorf("test[%s]: unexpected nil output, expected: %v", test.desc, *test.expected)
1243+
} else if *result != *test.expected {
1244+
t.Errorf("test[%s]: unexpected output: %v, expected: %v", test.desc, *result, *test.expected)
1245+
}
1246+
}
1247+
}
1248+
}
1249+
1250+
func TestGetDefaultBandwidth(t *testing.T) {
1251+
tests := []struct {
1252+
desc string
1253+
requestGiB int
1254+
storageAccountType string
1255+
expected *int32
1256+
}{
1257+
{
1258+
desc: "standardv2 with small storage",
1259+
requestGiB: 100,
1260+
storageAccountType: "StandardV2_LRS",
1261+
expected: int32Ptr(62),
1262+
},
1263+
{
1264+
desc: "standardv2 with 1GiB storage",
1265+
requestGiB: 1,
1266+
storageAccountType: "StandardV2_LRS",
1267+
expected: int32Ptr(61),
1268+
},
1269+
{
1270+
desc: "standardv2 with large storage hitting max",
1271+
requestGiB: 300000,
1272+
storageAccountType: "StandardV2_LRS_",
1273+
expected: int32Ptr(5120),
1274+
},
1275+
{
1276+
desc: "standardv2 case insensitive",
1277+
requestGiB: 100,
1278+
storageAccountType: "STANDARDV2",
1279+
expected: int32Ptr(62),
1280+
},
1281+
{
1282+
desc: "premiumv2 with small storage",
1283+
requestGiB: 100,
1284+
storageAccountType: "PremiumV2_LRS",
1285+
expected: int32Ptr(110),
1286+
},
1287+
{
1288+
desc: "premiumv2 with 1GiB storage",
1289+
requestGiB: 1,
1290+
storageAccountType: "PremiumV2_LRS",
1291+
expected: int32Ptr(101),
1292+
},
1293+
{
1294+
desc: "premiumv2 with large storage hitting max",
1295+
requestGiB: 200000,
1296+
storageAccountType: "PremiumV2_LRS",
1297+
expected: int32Ptr(10340),
1298+
},
1299+
{
1300+
desc: "premiumv2 case insensitive",
1301+
requestGiB: 100,
1302+
storageAccountType: "PREMIUMV2",
1303+
expected: int32Ptr(110),
1304+
},
1305+
{
1306+
desc: "unsupported storage account type",
1307+
requestGiB: 100,
1308+
storageAccountType: "Standard_LRS",
1309+
expected: nil,
1310+
},
1311+
{
1312+
desc: "empty storage account type",
1313+
requestGiB: 100,
1314+
storageAccountType: "",
1315+
expected: nil,
1316+
},
1317+
{
1318+
desc: "standardv2 with zero storage",
1319+
requestGiB: 0,
1320+
storageAccountType: "StandardV2_LRS",
1321+
expected: int32Ptr(60),
1322+
},
1323+
{
1324+
desc: "premiumv2 with zero storage",
1325+
requestGiB: 0,
1326+
storageAccountType: "PremiumV2_LRS",
1327+
expected: int32Ptr(100),
1328+
},
1329+
{
1330+
desc: "standardv2 with storage for exact calculation",
1331+
requestGiB: 2500,
1332+
storageAccountType: "StandardV2_LRS",
1333+
expected: int32Ptr(110),
1334+
},
1335+
{
1336+
desc: "premiumv2 with storage for exact calculation",
1337+
requestGiB: 1000,
1338+
storageAccountType: "PremiumV2_LRS",
1339+
expected: int32Ptr(200),
1340+
},
1341+
}
1342+
1343+
for _, test := range tests {
1344+
result := getDefaultBandwidth(test.requestGiB, test.storageAccountType)
1345+
if test.expected == nil {
1346+
if result != nil {
1347+
t.Errorf("test[%s]: unexpected output: %v, expected nil", test.desc, *result)
1348+
}
1349+
} else {
1350+
if result == nil {
1351+
t.Errorf("test[%s]: unexpected nil output, expected: %v", test.desc, *test.expected)
1352+
} else if *result != *test.expected {
1353+
t.Errorf("test[%s]: unexpected output: %v, expected: %v", test.desc, *result, *test.expected)
1354+
}
1355+
}
1356+
}
1357+
}
1358+
1359+
func int32Ptr(i int32) *int32 {
1360+
return &i
1361+
}

test/e2e/dynamic_provisioning_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,7 +1076,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
10761076
Cmd: convertToPowershellCommandIfNecessary("echo 'hello world' > /mnt/test-1/data && grep 'hello world' /mnt/test-1/data"),
10771077
Volumes: []testsuites.VolumeDetails{
10781078
{
1079-
ClaimSize: "10Gi",
1079+
ClaimSize: "40Gi",
10801080
MountOptions: []string{
10811081
"dir_mode=0777",
10821082
"file_mode=0777",
@@ -1099,7 +1099,7 @@ var _ = ginkgo.Describe("Dynamic Provisioning", func() {
10991099
}
11001100

11011101
scParameters := map[string]string{
1102-
"skuName": "Standard_LRS",
1102+
"skuName": "StandardV2_LRS",
11031103
"secretNamespace": "kube-system",
11041104
"createAccount": "true",
11051105
"useDataPlaneAPI": "true",

0 commit comments

Comments
 (0)