Skip to content

Commit 2970da8

Browse files
authored
Merge pull request #37625 from RomanBednar/retro-sc-assignment-blog
Feature blog for KEP-3333 Retroactive default StorageClass assignment
2 parents 037def8 + a957b8f commit 2970da8

File tree

1 file changed

+166
-0
lines changed

1 file changed

+166
-0
lines changed
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
---
2+
layout: blog
3+
title: "Kubernetes 1.26: Retroactive Default StorageClass"
4+
date: 2023-01-05
5+
slug: retroactive-default-storage-class
6+
---
7+
8+
**Author:** Roman Bednář (Red Hat)
9+
10+
The v1.25 release of Kubernetes introduced an alpha feature to change how a default StorageClass was assigned to a PersistentVolumeClaim (PVC).
11+
With the feature enabled, you no longer need to create a default StorageClass first and PVC second to assign the class. Additionally, any PVCs without a StorageClass assigned can be updated later.
12+
This feature was graduated to beta in Kubernetes 1.26.
13+
14+
You can read [retroactive default StorageClass assignment](/docs/concepts/storage/persistent-volumes/#retroactive-default-storageclass-assignment) in the Kubernetes documentation for more details about how to use that,
15+
or you can read on to learn about why the Kubernetes project is making this change.
16+
17+
## Why did StorageClass assignment need improvements
18+
19+
Users might already be familiar with a similar feature that assigns default StorageClasses to **new** PVCs at the time of creation. This is currently handled by the [admission controller](/docs/reference/access-authn-authz/admission-controllers/#defaultstorageclass).
20+
21+
But what if there wasn't a default StorageClass defined at the time of PVC creation?
22+
Users would end up with a PVC that would never be assigned a class.
23+
As a result, no storage would be provisioned, and the PVC would be somewhat "stuck" at this point.
24+
Generally, two main scenarios could result in "stuck" PVCs and cause problems later down the road.
25+
Let's take a closer look at each of them.
26+
27+
### Changing default StorageClass
28+
29+
With the alpha feature enabled, there were two options admins had when they wanted to change the default StorageClass:
30+
31+
1. Creating a new StorageClass as default before removing the old one associated with the PVC.
32+
This would result in having two defaults for a short period.
33+
At this point, if a user were to create a PersistentVolumeClaim with storageClassName set to <code>null</code> (implying default StorageClass), the newest default StorageClass would be chosen and assigned to this PVC.
34+
35+
2. Removing the old default first and creating a new default StorageClass.
36+
This would result in having no default for a short time.
37+
Subsequently, if a user were to create a PersistentVolumeClaim with storageClassName set to <code>null</code> (implying default StorageClass), the PVC would be in <code>Pending</code> state forever.
38+
The user would have to fix this by deleting the PVC and recreating it once the default StorageClass was available.
39+
40+
41+
### Resource ordering during cluster installation
42+
43+
If a cluster installation tool needed to create resources that required storage, for example, an image registry, it was difficult to get the ordering right.
44+
This is because any Pods that required storage would rely on the presence of a default StorageClass and would fail to be created if it wasn't defined.
45+
46+
## What changed
47+
48+
We've changed the PersistentVolume (PV) controller to assign a default StorageClass to any unbound PersistentVolumeClaim that has the storageClassName set to <code>null</code>.
49+
We've also modified the PersistentVolumeClaim admission within the API server to allow the change of values from an unset value to an actual StorageClass name.
50+
51+
### Null `storageClassName` versus `storageClassName: ""` - does it matter? { #null-vs-empty-string }
52+
53+
Before this feature was introduced, those values were equal in terms of behavior. Any PersistentVolumeClaim with the storageClassName set to <code>null</code> or <code>""</code> would bind to an existing PersistentVolume resource with storageClassName also set to <code>null</code> or <code>""</code>.
54+
55+
With this new feature enabled we wanted to maintain this behavior but also be able to update the StorageClass name.
56+
With these constraints in mind, the feature changes the semantics of <code>null</code>. If a default StorageClass is present, <code>null</code> would translate to "Give me a default" and <code>""</code> would mean "Give me PersistentVolume that also has <code>""</code> StorageClass name." In the absence of a StorageClass, the behavior would remain unchanged.
57+
58+
Summarizing the above, we've changed the semantics of <code>null</code> so that its behavior depends on the presence or absence of a definition of default StorageClass.
59+
60+
The tables below show all these cases to better describe when PVC binds and when its StorageClass gets updated.
61+
62+
<table>
63+
<caption>PVC binding behavior with Retroactive default StorageClass</caption>
64+
<thead>
65+
<tr>
66+
<th colspan="2"></th>
67+
<th>PVC <tt>storageClassName</tt> = <code>""</code></th>
68+
<th>PVC <tt>storageClassName</tt> = <code>null</code></th>
69+
</tr>
70+
</thead>
71+
<tbody>
72+
<tr>
73+
<td rowspan="2">Without default class</td>
74+
<td>PV <tt>storageClassName</tt> = <code>""</code></td>
75+
<td>binds</td>
76+
<td>binds</td>
77+
</tr>
78+
<tr>
79+
<td>PV without <tt>storageClassName</tt></td>
80+
<td>binds</td>
81+
<td>binds</td>
82+
</tr>
83+
<tr>
84+
<td rowspan="2">With default class</td>
85+
<td>PV <tt>storageClassName</tt> = <code>""</code></td>
86+
<td>binds</td>
87+
<td>class updates</td>
88+
</tr>
89+
<tr>
90+
<td>PV without <tt>storageClassName</tt></td>
91+
<td>binds</td>
92+
<td>class updates</td>
93+
</tr>
94+
</tbody>
95+
</table>
96+
97+
## How to use it
98+
99+
If you want to test the feature whilst it's alpha, you need to enable the relevant feature gate in the kube-controller-manager and the kube-apiserver. Use the `--feature-gates` command line argument:
100+
101+
```
102+
--feature-gates="...,RetroactiveDefaultStorageClass=true"
103+
```
104+
105+
### Test drive
106+
107+
If you would like to see the feature in action and verify it works fine in your cluster here's what you can try:
108+
109+
1. Define a basic PersistentVolumeClaim:
110+
```yaml
111+
apiVersion: v1
112+
kind: PersistentVolumeClaim
113+
metadata:
114+
name: pvc-1
115+
spec:
116+
accessModes:
117+
- ReadWriteOnce
118+
resources:
119+
requests:
120+
storage: 1Gi
121+
```
122+
123+
2. Create the PersistentVolumeClaim when there is no default StorageClass. The PVC won't provision or bind (unless there is an existing, suitable PV already present) and will remain in <code>Pending</code> state.
124+
```
125+
$ kc get pvc
126+
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
127+
pvc-1 Pending
128+
```
129+
130+
3. Configure one StorageClass as default.
131+
```
132+
$ kc patch sc -p '{"metadata":{"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
133+
storageclass.storage.k8s.io/my-storageclass patched
134+
```
135+
136+
4. Verify that PersistentVolumeClaims is now provisioned correctly and was updated retroactively with new default StorageClass.
137+
```
138+
$ kc get pvc
139+
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
140+
pvc-1 Bound pvc-06a964ca-f997-4780-8627-b5c3bf5a87d8 1Gi RWO my-storageclass 87m
141+
```
142+
143+
### New metrics
144+
145+
To help you see that the feature is working as expected we also introduced a new <code>retroactive_storageclass_total</code> metric to show how many times that the PV controller attempted to update PersistentVolumeClaim, and <code>retroactive_storageclass_errors_total</code> to show how many of those attempts failed.
146+
147+
## Getting involved
148+
149+
We always welcome new contributors so if you would like to get involved you can join our [Kubernetes Storage Special-Interest-Group](https://github.com/kubernetes/community/tree/master/sig-storage) (SIG).
150+
151+
If you would like to share feedback, you can do so on our [public Slack channel](https://app.slack.com/client/T09NY5SBT/C09QZFCE5).
152+
153+
Special thanks to all the contributors that provided great reviews, shared valuable insight and helped implement this feature (alphabetical order):
154+
155+
- Deep Debroy ([ddebroy](https://github.com/ddebroy))
156+
- Divya Mohan ([divya-mohan0209](https://github.com/divya-mohan0209))
157+
- Jan Šafránek ([jsafrane](https://github.com/jsafrane/))
158+
- Joe Betz ([jpbetz](https://github.com/jpbetz))
159+
- Jordan Liggitt ([liggitt](https://github.com/liggitt))
160+
- Michelle Au ([msau42](https://github.com/msau42))
161+
- Seokho Son ([seokho-son](https://github.com/seokho-son))
162+
- Shannon Kularathna ([shannonxtreme](https://github.com/shannonxtreme))
163+
- Tim Bannister ([sftim](https://github.com/sftim))
164+
- Tim Hockin ([thockin](https://github.com/thockin))
165+
- Wojciech Tyczynski ([wojtek-t](https://github.com/wojtek-t))
166+
- Xing Yang ([xing-yang](https://github.com/xing-yang))

0 commit comments

Comments
 (0)