-
Notifications
You must be signed in to change notification settings - Fork 373
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
GetCapacityResponse: add maximum_volume_size #470
GetCapacityResponse: add maximum_volume_size #470
Conversation
As discussed in the community meeting on 2021-02-03, the semantic of For issue #432, adding this new field and letting a CO use it when available is sufficient. |
@bswartz : perhaps you can have a first look whether this reflects what we discussed? |
csi.proto
Outdated
@@ -947,6 +947,26 @@ message GetCapacityResponse { | |||
// storage. This field is REQUIRED. | |||
// The value of this field MUST NOT be negative. | |||
int64 available_capacity = 1; | |||
|
|||
// The largest size that could have been used in a CreateVolume call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reword: The largest size that may used in a CreateVolume call
csi.proto
Outdated
// This field is OPTIONAL. If a Plugin has no restrictions for the | ||
// size of volumes (for example, linear storage with no fragmentation | ||
// issues and no technical limitation for individual volumes), then | ||
// can leave this field unset and only return available_capacity. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we've defined available_capacity very vaguely, and a CO will probably ignore that field, I think a better recommendation here would be to not leave the field blank, but the return the full available capacity, even if that means both fields of this struct have the same value.
Since we don't have a capability bit to go with this feature, I think the presence/absence of this field tells the CO if the SP supports this feature, and therefore we never want to leave it blank, unless the SP doesn't support the feature at all.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that we've defined available_capacity very vaguely, and a CO will probably ignore that field,
No, Kubernetes won't ignore it if that's only field that is set. Some vague value is still better than none.
I think a better recommendation here would be to not leave the field blank, but the return the full available capacity,
But then we need to define what "full capacity" is, right?
We can say "return the same vague value as in available_capacity
", but benefit does that provide given that a CO must be prepared to fall back to using available_capacity
when maximum_volume_size
is unset?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No I think we just document that this field should always be the largest possible volume size, and it should never be blank, unless the SP don't support the feature. If the largest possible volume size and the available capacity are the same, that's fine. This allows COs that are only interested in whether a given volume will fit on a given node to answer that question by looking at a single field. The value of the other field could be for sorting the list of possible candidate nodes, if the CO was trying to spread out space consumption, for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps I should just leave out the sentence with "If a Plugin has no..."? That the field can be unset is already covered by "is OPTIONAL".
We could say "A Plugin SHOULD set this value to the available capacity if it has no additional limitations (for example, fragmentation) that lead to a smaller maximum volume size."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I say keep it simple and stick to what the field means and how it will be interpreted by COs. We should not speculate about the reasons why volume size might be limited to a value smaller than the available capacity in the spec. Just say it means the largest volume size which should be successfully created. COs MAY use this value to make decisions about where to schedule volumes,.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Updated.
This new field has a more precisely defined semantic than the existing available_capacity. It is intended for checking in advance in which topology a CreateVolume call might succeed. Checking that based on available_capacity is less precise, for example because fragmentation might prevent creating a single volume that uses all available capacity. The new value has to be returned in a message to allow the caller to determine whether the value was provided.
b842b28
to
e09188b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
/assign @saad-ali These commands don't do anything here, though, do they? 😅 |
Oh IDK what our review process is in this repo. I just do both methods to cover my bases |
spec.md
Outdated
@@ -1593,6 +1593,24 @@ message GetCapacityResponse { | |||
// storage. This field is REQUIRED. | |||
// The value of this field MUST NOT be negative. | |||
int64 available_capacity = 1; | |||
|
|||
// The largest size that may be used in a CreateVolume call |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems to be communicating constraints related to the size of a "contiguous segment" of storage (terms vary across backends, of course) that may be used in a create volume call. Nice idea, and it seems very applicable to a plugin managing e.g. GPT partitions on a block device. I wonder if it could be taken further w/ respect to minimum size requirements -- e.g. perhaps it's not possible to create a storage volume of 1 byte on some backend.
Instead of capturing just the max requirement of such storage segments here, perhaps we should reuse the CapacityRange type to express both min and max requirements. This also would allow the plugin to express that it only has the ability to create volumes of a certain fixed/static size (given the requested parameters, of course), which also might be interesting for some use cases.
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure about the exact use case where the minimum size is useful because CreateVolume is allowed to create a larger volume than requested, so in contrast to the maximum size it is a "softer" constraint.
But I think it is worthwhile adding nonetheless to minimize churn in the spec and CSI drivers if this turns out to be useful later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added another commit which changes Capacity maximum_volume_size
into CapacityRange volume_size
. The naming of the CapacityRange
is not a perfect fit (required_bytes
, limit_bytes
), but it is close enough to make sense. I like it slightly better than before, but don't care too much.
@bswartz can you take another look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree that CreateVolume is allowed to create larger volumes than requested. There is a size range, and the upper limit may be larger than the lower limit, or it may be zero (unlimited). If the upper limit is set, though, it would be a spec violation to return a larger size volume. Kubernetes never sets the upper limit, so it's not a problem we frequently notice.
I can see the value of reporting a size range for supported volume size. If a plugin were to report minimum of 1 GiB, and I requested a volume with a max size of 100 MiB, then I could reasonably expect a failure. I also don't like the field names for the exiting CapacityRange structure, and I'm also not sure what to do about it. My best idea is to not attempt to reuse that structure but instead to define two simple Capacity fields. One for max, and one for min. This way we can name them appropriately and the functionality is equivalent to one CapacityRange field.
It's probably worth calling out specifically what we expect to see from the minimum. In some cases it could be a single block (such as 4K). In other cases it might be the minimum the system will allow, which is often hardcoded into the filesystem. And in the case @jdef mentioned it might be the smallest size pre-provisioned chunk of space that's sitting on the shelf.
COs should take care never to set the maximum volume size for CreateVolume() to a size smaller than the minimum. For Kubernetes this will never be an issue because the maximum is always infinity, but for other COs I can see it mattering.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't agree that CreateVolume is allowed to create larger volumes than requested. There is a size range, and the upper limit may be larger than the lower limit, or it may be zero (unlimited). If the upper limit is set, though, it would be a spec violation to return a larger size volume. Kubernetes never sets the upper limit, so it's not a problem we frequently notice.
Indeed, I was thinking only of how Kubernetes uses this. I agree, other COs may do things differently.
It's probably worth calling out specifically what we expect to see from the minimum.
Hmm, isn't it the same abstract rule as for maximum size? "If your CreateVolume call uses a required size smaller than the maximum volume size and a limit larger than the mimimum volume size, then a volume can be created". We decided against mentioning fragmentation as something that affects maximum volume size. Following the same logic we also shouldn't describe in the spec why a driver might report a non-zero minimum size.
My best idea is to not attempt to reuse that structure but instead to define two simple Capacity fields. One for max, and one for min. This way we can name them appropriately and the functionality is equivalent to one CapacityRange field.
Besides naming, an additional benefit is that a driver can leave the minimum size unspecified which may be more natural than "zero" when it has no (known?) minimum size.
I've added YAC (yet another commit 😁 ) with that third alternative. I used the opportunity to explicitly mention the CreateVolumeRequest.capacity_range
field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I didn't mean to include in the spec the reasons why a minimum might exist, just be specific about how the minimum should be interpreted and perhaps offer examples of valid values. In particular, we should explain if zero is a valid value, because zero has special meaning for the maximum. I might expect that values less than 1 are not okay, and even a 1 byte volume seems strange to me, but perhaps some provider can support it.
These are nitpicks though, I'm actually okay merging the change as-is, if others agree.
The minimum volume size may also be relevant. Another advantage is that the existing CapacityRange type can be used.
@@ -947,6 +947,39 @@ message GetCapacityResponse { | |||
// storage. This field is REQUIRED. | |||
// The value of this field MUST NOT be negative. | |||
int64 available_capacity = 1; | |||
|
|||
// The largest size that may be used in a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For volume plugins that don't need to deal with fragmentation issues, I think defining a stricter available_capacity would be beneficial to help us do batch processing of multiple volumes. Right now, we're limited to processing a single volume at a time, which is a major issue for supporting a single workload that requests multiple volumes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Improving the definition of available_capacity
was intentionally left out because it seemed to need further discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant should we define a new available_capacity field that has a more strict definition?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, probably. But not in this PR 😅
What you want is tracked in #301
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite. So we said available_capacity could be interpreted 2 ways: 1) available capacity to provision a single volume and 2) total available capacity as reported by the storage system. Why do we only want to clarify one of the methods that this could be interpreted?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the last CSI community meeting we talked about whether available_capacity
should be clarified and concluded that the wording should be left as-is until there is a specific use-case that needs a stricter definition than the one that is currently in the spec. See (or rather, listen): https://www.youtube.com/watch?list=PLypWp79Fch09Sv7Vo-mHgEo20cGU7oNBc&t=1917&v=ZB0Y05jo7-M&feature=youtu.be
That link points to my summary of the discussion; both @bswartz and @saad-ali confirmed it.
@jdef is this now ready to be merged? When is the CSI 1.4.0 release going to be created? This API change is something that I'd like to use in Kubernetes 1.21, which has a code freeze on Tuesday, March 9th. |
@@ -947,6 +947,39 @@ message GetCapacityResponse { | |||
// storage. This field is REQUIRED. | |||
// The value of this field MUST NOT be negative. | |||
int64 available_capacity = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that we have added the new capacity fields for max/min volume size, can we also add comments to this existing field to explain how CO should be using this field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is not clear yet. If you have a proposal, then please put it into a PR and we can discuss it.
/lgtm @jdef Please speak up soon if you have any objections. I want to merge this and cut 1.4 by EOD. |
// | ||
// If `volume_capabilities` or `parameters` is | ||
// specified in the request, the Plugin SHALL take those into | ||
// consideration when calculating the maximum volume size of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s/maximum/minimum/ ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually correct here and wrong for maximum_volume_size
: the requested minimum volume size must be <= maximum_volume_size
and the requested maximum volume size (this case here, aka capacity_range.limit_bytes
) >= minimum_volume_size
.
I fixed the maximum_volume_size
comment.
Nit: I'm not crazy about a message type that wraps a single int value. There are WKT messages for this. Otherwise lgtm |
17acd3c
to
66b486d
Compare
CapacityRange volume_size = 2 [(alpha_field) = true]; | ||
// where to create volumes. MUST NOT be negative. | ||
google.protobuf.Int64Value maximum_volume_size = 2 | ||
[(alpha_field) = true]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The line break is necessary here to pass the length > 72
check.
// | ||
// If `volume_capabilities` or `parameters` is | ||
// specified in the request, the Plugin SHALL take those into | ||
// consideration when calculating the maximum volume size of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's actually correct here and wrong for maximum_volume_size
: the requested minimum volume size must be <= maximum_volume_size
and the requested maximum volume size (this case here, aka capacity_range.limit_bytes
) >= minimum_volume_size
.
I fixed the maximum_volume_size
comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: I'm not crazy about a message type that wraps a single int value. There are WKT messages for this. Otherwise lgtm
Done.
@saad-ali please take another look and merge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks!
So I was about to merge this, and I realized that we probably don't even need a WKT here. Can't the default value of 0 for either of these new fields translate to "this is field is unset"? We do that elsewhere in the spec, why not here? Or maybe I'm missing something? I'd prefer the simpler form if possible, but if there's a good reason to keep the WKT then OK |
It's more obvious for |
Makes sense. Can you add wording to the spec that describes this intent,
phrased as a recommendation (i.e. MAY, SHOULD)?
…On Thu, Mar 4, 2021, 7:05 AM Patrick Ohly ***@***.***> wrote:
We do that elsewhere in the spec, why not here?
minimum_volume_size = 0 might be a valid value when the CSI driver has no
size restriction. It's probably not a very useful volume if it cannot store
data, but still...
It's more obvious for maximum_volume_size = 0: that indicates that the
CSI driver completely ran out of capacity, which has to be different from
"CSI driver did not provide the information".
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#470 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAR5KLHEYYGCPAFDHWZHZY3TB5ZQHANCNFSM4XC2ZFRQ>
.
|
Using CapacityRange in GetCapacityResponse is not a good fit because the names of its fields is a bit awkward. By adding two fields in GetCapacityResponse we support the same functionality, plus they can be left unset separately from each other.
66b486d
to
7a2fcdd
Compare
We already had a comment about "COs MAY...". I added "The Plugin SHOULD..." so now it reads:
|
Thanks. |
This new field has a more precisely defined semantic than the existing
available_capacity. It is intended for checking in advance in which
topology a CreateVolume call might succeed. Checking that based
on available_capacity is less precise, for example because
fragmentation might prevent creating a single volume that uses
all available capacity.
The new value has to be returned in a message to allow the caller to
determine whether the value was provided.
Fixes: #432