Skip to content
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

Support Elasticsearch volumes expansion #3752

Merged
merged 25 commits into from
Oct 2, 2020
Merged

Conversation

sebgl
Copy link
Contributor

@sebgl sebgl commented Sep 15, 2020

Add support for resizing Elasticsearch volumes, by simply editing the storage requests in the volumeClaimTemplates section of the spec.

Demo

assembled

Constraints

  • Volume size can only be increased, not decreased (k8s limitation, not likely to change anytime soon)
  • Only possible if the storage class specifies allowVolumeExpansion: true
  • Hot filesystem resize without re-creating the Pod is possible in many cases (GCE-PD, AWS-EBS, Azure, TopoLVM, etc.). If the storage driver does not allow it, it is necessary to manually delete the Pods. ECK does not do it.

Implementation overview

Resizing PVCs is not supported by the StatefulSet controller at this time. The volume section of the StatefulSet spec is immutable.
However, it is possible to work around the StatefulSet limitations this way:

  1. Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
  2. We now have resized volumes, but the StatefulSet still specifies the old volume size. Any new replica will end up with a smaller PVC, that in turn needs to be resized.
  3. Delete the StatefulSet (but not the Pods it owns), then recreate it with the new volume spec.
  4. Address the case where Pods may become orphans if something happens while the StatefulSet is getting recreated, by ensuring we always recreate deleted StatefulSets, and ensure we set a temporary ownerRef on the Pods while they are not owned by the deleted StatefulSet anymore.

Follow-up (in other PRs)

Relates #325.

@sebgl sebgl added >feature Adds or discusses adding a feature to the product release-highlight Candidate for the ECK release highlight summary v1.3.0 labels Sep 15, 2020
@sebgl sebgl mentioned this pull request Sep 15, 2020
...when setting the initial replicas values for statefulset re-creation.
Otherwise, if we're unlucky and one Pod is missing for some reasons (eg. pod-0),
using the Pod count could lead to removing the Pods with highest ordinals.
Copy link
Contributor

@david-kow david-kow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work @sebgl. I did some testing and left some comments, nothing major.

pkg/apis/elasticsearch/v1/validations.go Outdated Show resolved Hide resolved
pkg/apis/elasticsearch/v1/validations.go Show resolved Hide resolved
pkg/controller/elasticsearch/driver/upscale.go Outdated Show resolved Hide resolved
pkg/controller/elasticsearch/driver/pvc_expansion.go Outdated Show resolved Hide resolved
pkg/controller/elasticsearch/driver/pvc_expansion.go Outdated Show resolved Hide resolved
@sebgl
Copy link
Contributor Author

sebgl commented Sep 17, 2020

There's a concern that some users may not be allowed to deploy ECK if it needs read access to storage classes (cluster-wide) resource.
I'll update this PR to remove any storage class checks and restore a minimal validation webhook that allows resizing.
I created another issue to deal with the storage class thing specifically: #3767

@sebgl sebgl requested a review from david-kow September 17, 2020 16:42
@sebgl
Copy link
Contributor Author

sebgl commented Sep 18, 2020

Jenkins test this please.

@sebgl sebgl requested review from barkbay and david-kow September 29, 2020 16:59
Copy link
Contributor

@barkbay barkbay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still doing some tests but overall it looks good 👍
Also I just want to be sure we don't want to handle the case where the Elasticsearch resource is deleted before the statefulset is re-created, leaving some Pods orphaned ?

…ated

If the Elasticsearch resource is removed while the StatefulSet is being
recreated, orphan Pods will stay around forever.
To avoid that situation, we can set append a temporary owner ref to the Pods
before deleting their StatefulSet, so Pods don't stay orphans if Elasticsearch
is deleted.
We can then remove the temporary owner ref that was set after
the StatefulSet is recreated.
@sebgl
Copy link
Contributor Author

sebgl commented Sep 30, 2020

Also I just want to be sure we don't want to handle the case where the Elasticsearch resource is deleted before the statefulset is re-created, leaving some Pods orphaned ?

@barkbay thanks for pointing that particular case again!
I tried setting an ownerRef to the ES resource in the podTemplate but according to my tests it looks like the StatefulSet controller applies its own ownerRef (only) and discards ours.
So instead in f22af15 I decided to manually add the Pod ownerRef right before deleting the StatefulSet, then remove it right after the StatefulSet was recreated (before removing the annotation).
It seems to work well and address the orphan Pods problem when the ES resource is deleted in the middle of a StatefulSet re-creation.

Copy link
Contributor

@barkbay barkbay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I left some comments re. the unit tests, I think they are not complete.

Copy link
Contributor

@barkbay barkbay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍
Great work !

pkg/controller/elasticsearch/driver/pvc_expansion_test.go Outdated Show resolved Hide resolved
pkg/controller/elasticsearch/driver/upscale_state_test.go Outdated Show resolved Hide resolved
Copy link
Contributor

@david-kow david-kow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It worked well through all my attempts to break it :) nice work. Just one scenario I'm concerned about, the rest are nits.

if err != nil {
return results.WithError(fmt.Errorf("StatefulSet recreation: %w", err))
}
if recreations > 0 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that the spec provided in ES resource results in invalid statefulset? If yes, then I think, since we use the statefulset from the spec when annotating, we won't make progress past this point because the operator will keep trying to recreate the statefulset from annotation and keep failing.

If the above is valid then I'd be a little uncomfortable, because we could effectively get the operator stuck on wrong config. I think that would be first such case (e.g. changing resource won't work, because we process annotation first).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What we set in the annotation always matches an "actual StatefulSet", ie. a StatefulSet that exists in the apiserver, for which an update (or create) operation was successful in the past. We don't set the annotation based on the "expected StatefulSet".
I think in the case you mention where the StatefulSet cannot possibly be created, the update call would probably have failed beforehand? I don't know if there are some cases where a spec would lead to a successful update but an invalid creation. It seems weird.
WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was convinced that we set the expected sset in the annotation, which I see now isn't true. Yes, I think we can dismiss the case of successful update and failed create.

pkg/apis/elasticsearch/v1/validations.go Show resolved Hide resolved
pkg/apis/elasticsearch/v1/validations_test.go Show resolved Hide resolved
pkg/controller/elasticsearch/sset/getter.go Show resolved Hide resolved
pkg/apis/elasticsearch/v1/validations.go Show resolved Hide resolved
Copy link
Contributor

@david-kow david-kow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! 🚀

@sebgl sebgl merged commit bcbc61d into master Oct 2, 2020
sebgl added a commit to sebgl/cloud-on-k8s that referenced this pull request Oct 2, 2020
This commit modifies the existing documentation in order to account
for the volume expansion feature introduced in elastic#3752.

With those changes, it is now possible to resize storage requests if the storage size
allows it.
Every other change is forbidden.

The doc also mentions how Pods may need to be restarted if the volume driver
does not support online expansion.

I added lower-level titles to better structure the volume claim templates page.
sebgl added a commit that referenced this pull request Oct 5, 2020
* Document volume expansion and volume claim immutability

This commit modifies the existing documentation in order to account
for the volume expansion feature introduced in #3752.

With those changes, it is now possible to resize storage requests if the storage size
allows it.
Every other change is forbidden.

The doc also mentions how Pods may need to be restarted if the volume driver
does not support online expansion.

I added lower-level titles to better structure the volume claim templates page.

* Improvements from PR review
@david-kow david-kow deleted the resize-pvc-delete-ssets branch December 16, 2020 11:00
robbavey added a commit to robbavey/cloud-on-k8s that referenced this pull request Jan 23, 2024
This commit adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in elastic#3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This works in the same way as the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will
* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource

This PR moves some of the PVC-expansion code from Elasticsearch into a common area to avoid code duplication
robbavey added a commit to robbavey/cloud-on-k8s that referenced this pull request Jan 26, 2024
This commit adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in elastic#3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This works in the same way as the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will
* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource

This PR moves some of the PVC-expansion code from Elasticsearch into a common area to avoid code duplication
robbavey added a commit to robbavey/cloud-on-k8s that referenced this pull request Jan 29, 2024
This commit adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in elastic#3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This works in the same way as the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will
* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource

This PR moves some of the PVC-expansion code from Elasticsearch into a common area to avoid code duplication
robbavey added a commit to robbavey/cloud-on-k8s that referenced this pull request Jan 31, 2024
This commit adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in elastic#3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This is based on the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will

* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource
robbavey added a commit to robbavey/cloud-on-k8s that referenced this pull request Feb 1, 2024
This commit adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in elastic#3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This is based on the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will

* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource
robbavey added a commit to robbavey/cloud-on-k8s that referenced this pull request Feb 1, 2024
This commit adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in elastic#3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This is based on the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will

* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource
pebrc added a commit that referenced this pull request Feb 5, 2024
This adds support for expanding Logstash volumes by editing the storage requests
in spec.VolumeClaimTemplate, based on the existing implenentation in Elasticsearch
implemented in #3752.

The same constraints hold -

* Volume size can only be increased, not decreased
* Storage class must specify allowVolumeExpansion: true
* Filesystem resize without pod recreation is only possible if the storage driver allows it

This is based on the Elasticsearch implementation

An update of the storage request in the volumeClaimTemplate will

* Update the storage requests spec of all existing PVCs: they are immediately resized by the storage driver, if inline expansion is supported. Otherwise Pods need to be recreated.
* Delete the StatefulSet, but not the pod that it owns, storing recreation details in an annotation on the owning Logstash resource
* Recreate the StatefulSet with the new volumeClaimTemplate spec
* Remove the recreation annotation from the Logstash resource

This also reworks the webhook validation to validate that storage updates fulfill
the requirements (only increasing storage, using a valid storage class that allows
storage expansion).

This required moving the webhook validation into the controller package to allow use
of the k8sclient without a dependency cycle, and requires some rework in webhook
registration

---------

Co-authored-by: Karen Metts <35154725+karenzone@users.noreply.github.com>
Co-authored-by: Peter Brachwitz <peter.brachwitz@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>feature Adds or discusses adding a feature to the product release-highlight Candidate for the ECK release highlight summary v1.3.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants