0
# Storage Resources
1
2
The Storage API groups provide resources for dynamic volume provisioning, storage management, and Container Storage Interface (CSI) driver integration across multiple API versions.
3
4
## Package Import
5
6
```typescript { .api }
7
import { storage } from "@pulumi/kubernetes";
8
import * as k8s from "@pulumi/kubernetes";
9
10
// Direct storage imports
11
import { StorageClass, VolumeAttachment, CSIDriver } from "@pulumi/kubernetes/storage/v1";
12
```
13
14
## StorageClass (storage/v1)
15
16
StorageClass provides a way for administrators to describe the "classes" of storage they offer with dynamic provisioning.
17
18
```typescript { .api }
19
class StorageClass extends pulumi.CustomResource {
20
constructor(name: string, args?: StorageClassArgs, opts?: pulumi.CustomResourceOptions)
21
22
public static get(name: string, id: pulumi.Input<pulumi.ID>, opts?: pulumi.CustomResourceOptions): StorageClass
23
24
// Output properties
25
public readonly apiVersion!: pulumi.Output<"storage.k8s.io/v1">;
26
public readonly kind!: pulumi.Output<"StorageClass">;
27
public readonly metadata!: pulumi.Output<outputs.meta.v1.ObjectMeta>;
28
public readonly provisioner!: pulumi.Output<string>;
29
public readonly parameters!: pulumi.Output<{[key: string]: string}>;
30
public readonly reclaimPolicy!: pulumi.Output<string>;
31
public readonly allowVolumeExpansion!: pulumi.Output<boolean>;
32
public readonly volumeBindingMode!: pulumi.Output<string>;
33
public readonly allowedTopologies!: pulumi.Output<outputs.core.v1.TopologySelectorTerm[]>;
34
public readonly mountOptions!: pulumi.Output<string[]>;
35
}
36
37
interface StorageClassArgs {
38
apiVersion?: pulumi.Input<"storage.k8s.io/v1">;
39
kind?: pulumi.Input<"StorageClass">;
40
metadata?: pulumi.Input<inputs.meta.v1.ObjectMeta>;
41
provisioner: pulumi.Input<string>;
42
parameters?: pulumi.Input<{[key: string]: pulumi.Input<string>}>;
43
reclaimPolicy?: pulumi.Input<"Delete" | "Retain">;
44
allowVolumeExpansion?: pulumi.Input<boolean>;
45
volumeBindingMode?: pulumi.Input<"Immediate" | "WaitForFirstConsumer">;
46
allowedTopologies?: pulumi.Input<pulumi.Input<inputs.core.v1.TopologySelectorTerm>[]>;
47
mountOptions?: pulumi.Input<pulumi.Input<string>[]>;
48
}
49
```
50
51
### Volume Binding Modes
52
53
```typescript { .api }
54
// Volume binding mode types
55
type VolumeBindingMode =
56
| "Immediate" // Volume binding and provisioning happens immediately
57
| "WaitForFirstConsumer"; // Volume binding and provisioning delayed until Pod using PVC is created
58
59
// Reclaim policy types
60
type ReclaimPolicy =
61
| "Delete" // Volume will be deleted when PVC is deleted
62
| "Retain"; // Volume will be retained when PVC is deleted
63
```
64
65
### StorageClass Usage Examples
66
67
```typescript { .api }
68
// AWS EBS GP3 Storage Class
69
const ebsGp3StorageClass = new k8s.storage.v1.StorageClass("ebs-gp3", {
70
metadata: {
71
name: "ebs-gp3",
72
annotations: {
73
"storageclass.kubernetes.io/is-default-class": "true",
74
},
75
},
76
provisioner: "ebs.csi.aws.com",
77
parameters: {
78
type: "gp3",
79
iops: "3000",
80
throughput: "125",
81
encrypted: "true",
82
},
83
reclaimPolicy: "Delete",
84
allowVolumeExpansion: true,
85
volumeBindingMode: "WaitForFirstConsumer",
86
});
87
88
// High-performance SSD Storage Class
89
const fastSsdStorageClass = new k8s.storage.v1.StorageClass("fast-ssd", {
90
metadata: {
91
name: "fast-ssd",
92
},
93
provisioner: "ebs.csi.aws.com",
94
parameters: {
95
type: "io2",
96
iops: "10000",
97
encrypted: "true",
98
},
99
reclaimPolicy: "Delete",
100
allowVolumeExpansion: true,
101
volumeBindingMode: "Immediate",
102
allowedTopologies: [{
103
matchLabelExpressions: [{
104
key: "topology.ebs.csi.aws.com/zone",
105
values: ["us-west-2a", "us-west-2b"],
106
}],
107
}],
108
});
109
110
// Google Cloud Persistent Disk Storage Class
111
const gceStorageClass = new k8s.storage.v1.StorageClass("gce-ssd", {
112
metadata: {
113
name: "gce-ssd",
114
},
115
provisioner: "pd.csi.storage.gke.io",
116
parameters: {
117
type: "pd-ssd",
118
replication: "regional-pd",
119
},
120
reclaimPolicy: "Delete",
121
allowVolumeExpansion: true,
122
volumeBindingMode: "WaitForFirstConsumer",
123
});
124
125
// Azure Disk Storage Class
126
const azureDiskStorageClass = new k8s.storage.v1.StorageClass("azure-premium", {
127
metadata: {
128
name: "azure-premium",
129
},
130
provisioner: "disk.csi.azure.com",
131
parameters: {
132
skuName: "Premium_LRS",
133
cachingmode: "ReadOnly",
134
},
135
reclaimPolicy: "Delete",
136
allowVolumeExpansion: true,
137
volumeBindingMode: "WaitForFirstConsumer",
138
});
139
140
// Local Storage Class for high-performance workloads
141
const localStorageClass = new k8s.storage.v1.StorageClass("local-storage", {
142
metadata: {
143
name: "local-storage",
144
},
145
provisioner: "kubernetes.io/no-provisioner",
146
reclaimPolicy: "Delete",
147
volumeBindingMode: "WaitForFirstConsumer",
148
allowedTopologies: [{
149
matchLabelExpressions: [{
150
key: "kubernetes.io/hostname",
151
values: ["worker-1", "worker-2", "worker-3"],
152
}],
153
}],
154
});
155
```
156
157
## VolumeAttachment (storage/v1)
158
159
VolumeAttachment captures the intent to attach or detach the specified volume to/from the specified node.
160
161
```typescript { .api }
162
class VolumeAttachment extends pulumi.CustomResource {
163
constructor(name: string, args?: VolumeAttachmentArgs, opts?: pulumi.CustomResourceOptions)
164
165
public static get(name: string, id: pulumi.Input<pulumi.ID>, opts?: pulumi.CustomResourceOptions): VolumeAttachment
166
167
// Output properties
168
public readonly apiVersion!: pulumi.Output<"storage.k8s.io/v1">;
169
public readonly kind!: pulumi.Output<"VolumeAttachment">;
170
public readonly metadata!: pulumi.Output<outputs.meta.v1.ObjectMeta>;
171
public readonly spec!: pulumi.Output<outputs.storage.v1.VolumeAttachmentSpec>;
172
public readonly status!: pulumi.Output<outputs.storage.v1.VolumeAttachmentStatus>;
173
}
174
175
interface VolumeAttachmentArgs {
176
apiVersion?: pulumi.Input<"storage.k8s.io/v1">;
177
kind?: pulumi.Input<"VolumeAttachment">;
178
metadata?: pulumi.Input<inputs.meta.v1.ObjectMeta>;
179
spec: pulumi.Input<inputs.storage.v1.VolumeAttachmentSpec>;
180
}
181
```
182
183
## CSIDriver (storage/v1)
184
185
CSIDriver captures information about a Container Storage Interface (CSI) volume driver deployed on the cluster.
186
187
```typescript { .api }
188
class CSIDriver extends pulumi.CustomResource {
189
constructor(name: string, args?: CSIDriverArgs, opts?: pulumi.CustomResourceOptions)
190
191
public static get(name: string, id: pulumi.Input<pulumi.ID>, opts?: pulumi.CustomResourceOptions): CSIDriver
192
193
// Output properties
194
public readonly apiVersion!: pulumi.Output<"storage.k8s.io/v1">;
195
public readonly kind!: pulumi.Output<"CSIDriver">;
196
public readonly metadata!: pulumi.Output<outputs.meta.v1.ObjectMeta>;
197
public readonly spec!: pulumi.Output<outputs.storage.v1.CSIDriverSpec>;
198
}
199
200
interface CSIDriverArgs {
201
apiVersion?: pulumi.Input<"storage.k8s.io/v1">;
202
kind?: pulumi.Input<"CSIDriver">;
203
metadata?: pulumi.Input<inputs.meta.v1.ObjectMeta>;
204
spec?: pulumi.Input<inputs.storage.v1.CSIDriverSpec>;
205
}
206
```
207
208
### CSIDriver Usage Examples
209
210
```typescript { .api }
211
// AWS EBS CSI Driver
212
const ebsCSIDriver = new k8s.storage.v1.CSIDriver("ebs-csi-driver", {
213
metadata: {
214
name: "ebs.csi.aws.com",
215
},
216
spec: {
217
attachRequired: true,
218
podInfoOnMount: false,
219
volumeLifecycleModes: ["Persistent"],
220
storageCapacity: true,
221
fsGroupPolicy: "ReadWriteOnceWithFSType",
222
},
223
});
224
225
// Azure Disk CSI Driver
226
const azureDiskCSIDriver = new k8s.storage.v1.CSIDriver("azure-disk-csi", {
227
metadata: {
228
name: "disk.csi.azure.com",
229
},
230
spec: {
231
attachRequired: true,
232
podInfoOnMount: false,
233
volumeLifecycleModes: ["Persistent"],
234
storageCapacity: true,
235
},
236
});
237
238
// Custom CSI Driver
239
const customCSIDriver = new k8s.storage.v1.CSIDriver("custom-csi", {
240
metadata: {
241
name: "custom.csi.example.com",
242
},
243
spec: {
244
attachRequired: true,
245
podInfoOnMount: true,
246
volumeLifecycleModes: ["Persistent", "Ephemeral"],
247
storageCapacity: false,
248
fsGroupPolicy: "File",
249
tokenRequests: [{
250
audience: "custom-storage-service",
251
expirationSeconds: 3600,
252
}],
253
},
254
});
255
```
256
257
## CSINode (storage/v1)
258
259
CSINode holds information about all CSI drivers installed on a node.
260
261
```typescript { .api }
262
class CSINode extends pulumi.CustomResource {
263
constructor(name: string, args?: CSINodeArgs, opts?: pulumi.CustomResourceOptions)
264
265
public static get(name: string, id: pulumi.Input<pulumi.ID>, opts?: pulumi.CustomResourceOptions): CSINode
266
267
// Output properties
268
public readonly apiVersion!: pulumi.Output<"storage.k8s.io/v1">;
269
public readonly kind!: pulumi.Output<"CSINode">;
270
public readonly metadata!: pulumi.Output<outputs.meta.v1.ObjectMeta>;
271
public readonly spec!: pulumi.Output<outputs.storage.v1.CSINodeSpec>;
272
}
273
274
interface CSINodeArgs {
275
apiVersion?: pulumi.Input<"storage.k8s.io/v1">;
276
kind?: pulumi.Input<"CSINode">;
277
metadata?: pulumi.Input<inputs.meta.v1.ObjectMeta>;
278
spec: pulumi.Input<inputs.storage.v1.CSINodeSpec>;
279
}
280
```
281
282
## CSIStorageCapacity (storage/v1)
283
284
CSIStorageCapacity stores the result of one CSI GetCapacity call.
285
286
```typescript { .api }
287
class CSIStorageCapacity extends pulumi.CustomResource {
288
constructor(name: string, args?: CSIStorageCapacityArgs, opts?: pulumi.CustomResourceOptions)
289
290
public static get(name: string, id: pulumi.Input<pulumi.ID>, opts?: pulumi.CustomResourceOptions): CSIStorageCapacity
291
292
// Output properties
293
public readonly apiVersion!: pulumi.Output<"storage.k8s.io/v1">;
294
public readonly kind!: pulumi.Output<"CSIStorageCapacity">;
295
public readonly metadata!: pulumi.Output<outputs.meta.v1.ObjectMeta>;
296
public readonly nodeTopology!: pulumi.Output<outputs.meta.v1.LabelSelector>;
297
public readonly storageClassName!: pulumi.Output<string>;
298
public readonly capacity!: pulumi.Output<string>;
299
public readonly maximumVolumeSize!: pulumi.Output<string>;
300
}
301
302
interface CSIStorageCapacityArgs {
303
apiVersion?: pulumi.Input<"storage.k8s.io/v1">;
304
kind?: pulumi.Input<"CSIStorageCapacity">;
305
metadata?: pulumi.Input<inputs.meta.v1.ObjectMeta>;
306
nodeTopology?: pulumi.Input<inputs.meta.v1.LabelSelector>;
307
storageClassName?: pulumi.Input<string>;
308
capacity?: pulumi.Input<string>;
309
maximumVolumeSize?: pulumi.Input<string>;
310
}
311
```
312
313
## Alpha and Beta Storage Resources
314
315
### VolumeAttributesClass (storage/v1alpha1)
316
317
VolumeAttributesClass represents a specification of mutable volume attributes defined by the CSI driver.
318
319
```typescript { .api }
320
class VolumeAttributesClass extends pulumi.CustomResource {
321
constructor(name: string, args?: VolumeAttributesClassArgs, opts?: pulumi.CustomResourceOptions)
322
323
// Output properties
324
public readonly apiVersion!: pulumi.Output<"storage.k8s.io/v1alpha1">;
325
public readonly kind!: pulumi.Output<"VolumeAttributesClass">;
326
public readonly metadata!: pulumi.Output<outputs.meta.v1.ObjectMeta>;
327
public readonly driverName!: pulumi.Output<string>;
328
public readonly parameters!: pulumi.Output<{[key: string]: string}>;
329
}
330
```
331
332
## Complete Storage Setup Examples
333
334
### Database with Persistent Storage
335
336
```typescript { .api }
337
// Storage class for database workloads
338
const dbStorageClass = new k8s.storage.v1.StorageClass("db-storage", {
339
metadata: {
340
name: "database-ssd",
341
},
342
provisioner: "ebs.csi.aws.com",
343
parameters: {
344
type: "io2",
345
iops: "5000",
346
encrypted: "true",
347
fsType: "ext4",
348
},
349
reclaimPolicy: "Retain", // Don't delete data accidentally
350
allowVolumeExpansion: true,
351
volumeBindingMode: "WaitForFirstConsumer",
352
});
353
354
// PersistentVolumeClaim using the storage class
355
const dbPVC = new k8s.core.v1.PersistentVolumeClaim("postgres-data", {
356
spec: {
357
accessModes: ["ReadWriteOnce"],
358
storageClassName: "database-ssd",
359
resources: {
360
requests: {
361
storage: "100Gi",
362
},
363
},
364
},
365
});
366
367
// StatefulSet using the PVC
368
const postgresDB = new k8s.apps.v1.StatefulSet("postgres", {
369
spec: {
370
serviceName: "postgres",
371
replicas: 1,
372
selector: {
373
matchLabels: {
374
app: "postgres",
375
},
376
},
377
template: {
378
metadata: {
379
labels: {
380
app: "postgres",
381
},
382
},
383
spec: {
384
containers: [{
385
name: "postgres",
386
image: "postgres:14",
387
env: [{
388
name: "POSTGRES_PASSWORD",
389
valueFrom: {
390
secretKeyRef: {
391
name: "postgres-secret",
392
key: "password",
393
},
394
},
395
}],
396
volumeMounts: [{
397
name: "postgres-data",
398
mountPath: "/var/lib/postgresql/data",
399
}],
400
ports: [{
401
containerPort: 5432,
402
}],
403
}],
404
volumes: [{
405
name: "postgres-data",
406
persistentVolumeClaim: {
407
claimName: dbPVC.metadata.name,
408
},
409
}],
410
},
411
},
412
},
413
});
414
```
415
416
### Multi-Tier Storage Setup
417
418
```typescript { .api }
419
// Fast storage for cache layer
420
const cacheStorageClass = new k8s.storage.v1.StorageClass("cache-nvme", {
421
metadata: {
422
name: "cache-nvme",
423
},
424
provisioner: "ebs.csi.aws.com",
425
parameters: {
426
type: "gp3",
427
iops: "16000",
428
throughput: "1000",
429
},
430
reclaimPolicy: "Delete",
431
allowVolumeExpansion: true,
432
volumeBindingMode: "Immediate",
433
});
434
435
// Standard storage for application data
436
const standardStorageClass = new k8s.storage.v1.StorageClass("standard-ssd", {
437
metadata: {
438
name: "standard-ssd",
439
},
440
provisioner: "ebs.csi.aws.com",
441
parameters: {
442
type: "gp3",
443
iops: "3000",
444
},
445
reclaimPolicy: "Delete",
446
allowVolumeExpansion: true,
447
volumeBindingMode: "WaitForFirstConsumer",
448
});
449
450
// Archive storage for backups
451
const archiveStorageClass = new k8s.storage.v1.StorageClass("archive-storage", {
452
metadata: {
453
name: "archive-storage",
454
},
455
provisioner: "ebs.csi.aws.com",
456
parameters: {
457
type: "sc1", // Cold HDD
458
},
459
reclaimPolicy: "Retain",
460
allowVolumeExpansion: true,
461
volumeBindingMode: "WaitForFirstConsumer",
462
});
463
```
464
465
### CSI Driver Deployment
466
467
```typescript { .api }
468
// CSI Driver for custom storage solution
469
const customStorageCSIDriver = new k8s.storage.v1.CSIDriver("custom-storage", {
470
metadata: {
471
name: "storage.example.com",
472
},
473
spec: {
474
attachRequired: true,
475
podInfoOnMount: true,
476
volumeLifecycleModes: ["Persistent", "Ephemeral"],
477
storageCapacity: true,
478
fsGroupPolicy: "ReadWriteOnceWithFSType",
479
tokenRequests: [{
480
audience: "storage.example.com",
481
expirationSeconds: 3600,
482
}],
483
},
484
});
485
486
// Storage class using custom CSI driver
487
const customStorageClass = new k8s.storage.v1.StorageClass("custom-fast", {
488
metadata: {
489
name: "custom-fast",
490
},
491
provisioner: "storage.example.com",
492
parameters: {
493
tier: "premium",
494
encryption: "aes-256",
495
replication: "3",
496
},
497
reclaimPolicy: "Delete",
498
allowVolumeExpansion: true,
499
volumeBindingMode: "WaitForFirstConsumer",
500
});
501
```
502
503
## Storage Monitoring and Management
504
505
### Storage Capacity Tracking
506
507
```typescript { .api }
508
// CSI Storage Capacity for monitoring available storage
509
const storageCapacity = new k8s.storage.v1.CSIStorageCapacity("node1-capacity", {
510
metadata: {
511
name: "ebs-capacity-us-west-2a",
512
namespace: "kube-system",
513
},
514
nodeTopology: {
515
matchLabels: {
516
"topology.ebs.csi.aws.com/zone": "us-west-2a",
517
},
518
},
519
storageClassName: "ebs-gp3",
520
capacity: "1000Gi",
521
maximumVolumeSize: "16Ti",
522
});
523
```
524
525
## Resource Variants
526
527
All storage resources include the following variants:
528
529
### List Resources
530
- `StorageClassList`, `VolumeAttachmentList`, `CSIDriverList`, `CSINodeList`, `CSIStorageCapacityList`
531
532
### Patch Resources
533
- `StorageClassPatch`, `VolumeAttachmentPatch`, `CSIDriverPatch`, `CSINodePatch`, `CSIStorageCapacityPatch`
534
535
```typescript { .api }
536
// Example patch operation
537
const storageClassPatch = new k8s.storage.v1.StorageClassPatch("update-storage-class", {
538
metadata: {
539
name: "existing-storage-class",
540
},
541
allowVolumeExpansion: true, // Enable volume expansion
542
parameters: {
543
iops: "5000", // Update IOPS setting
544
},
545
});
546
```
547
548
## Best Practices
549
550
### StorageClass Best Practices
551
552
1. **Default Classes**: Mark appropriate storage class as default with annotation
553
2. **Reclaim Policy**: Use "Retain" for critical data, "Delete" for temporary data
554
3. **Volume Binding**: Use "WaitForFirstConsumer" for zone-aware provisioning
555
4. **Encryption**: Always enable encryption for sensitive data
556
5. **Performance Tuning**: Choose appropriate IOPS and throughput for workload requirements
557
558
### CSI Driver Best Practices
559
560
1. **Resource Limits**: Set appropriate resource limits for CSI driver pods
561
2. **Security**: Use service accounts and RBAC for proper permissions
562
3. **Monitoring**: Monitor CSI driver health and performance metrics
563
4. **Updates**: Keep CSI drivers updated for security and feature improvements
564
5. **Backup Strategy**: Implement proper backup and disaster recovery procedures
565
566
The Storage API groups provide comprehensive dynamic storage provisioning and management capabilities, enabling efficient and scalable storage solutions for containerized applications.