Skip to content

Commit 1a880a3

Browse files
egegunesgithub-actions[bot]hors
authored
K8SPXC-1341: Resize PVCs on user request (#1588)
* K8SPXC-1341: Resize PVCs on user request * Apply suggestions from code review Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Viacheslav Sarzhan <[email protected]>
1 parent 45f14c7 commit 1a880a3

File tree

5 files changed

+140
-0
lines changed

5 files changed

+140
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
100500

e2e-tests/pvc-resize/run

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
set -o errexit
4+
5+
test_dir=$(realpath $(dirname $0))
6+
. ${test_dir}/../functions
7+
8+
set_debug
9+
10+
create_infra ${namespace}
11+
12+
desc 'create first PXC cluster'
13+
cluster="some-name"
14+
spinup_pxc "${cluster}" "$conf_dir/$cluster.yml" "3" "10" "${conf_dir}/secrets.yml"
15+
16+
kubectl_bin patch pxc "$cluster" --type=merge --patch '{
17+
"spec": { "pxc": { "volumeSpec": { "persistentVolumeClaim": { "resources": { "requests": { "storage": "4Gi" } } } } } }
18+
}'
19+
wait_cluster_consistency "$cluster" 3 2
20+
21+
for pvc in $(kubectl_bin get pvc -l app.kubernetes.io/component=pxc -o name); do
22+
retry=0
23+
until [[ $(kubectl_bin get ${pvc} -o jsonpath={.status.capacity.storage}) == "4Gi" ]]; do
24+
if [[ $retry -ge 60 ]]; then
25+
echo "PVC ${pvc} was not resized, max retries exceeded"
26+
exit 1
27+
fi
28+
29+
echo "Waiting for PVC ${pvc} to be resized"
30+
sleep 5
31+
32+
retry=$((retry + 1))
33+
done
34+
echo "PVC ${pvc} was resized"
35+
done
36+
37+
destroy "${namespace}"
38+
desc "test passed"

e2e-tests/run-pr.csv

+2
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ upgrade-proxysql,8.0
3535
users,5.7
3636
users,8.0
3737
validation-hook,8.0
38+
pvc-resize,5.7
39+
pvc-resize,8.0

pkg/controller/pxc/controller.go

+4
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ func (r *ReconcilePerconaXtraDBCluster) Reconcile(ctx context.Context, request r
294294
log.Info("failed to ensure version, running with default", "error", err)
295295
}
296296
}
297+
err = r.reconcilePersistentVolumes(ctx, o)
298+
if err != nil {
299+
return reconcile.Result{}, errors.Wrap(err, "reconcile persistent volumes")
300+
}
297301

298302
err = r.deploy(ctx, o)
299303
if err != nil {

pkg/controller/pxc/volumes.go

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package pxc
2+
3+
import (
4+
"context"
5+
"strings"
6+
7+
"github.com/pkg/errors"
8+
corev1 "k8s.io/api/core/v1"
9+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
10+
"sigs.k8s.io/controller-runtime/pkg/client"
11+
logf "sigs.k8s.io/controller-runtime/pkg/log"
12+
13+
api "github.com/percona/percona-xtradb-cluster-operator/pkg/apis/pxc/v1"
14+
"github.com/percona/percona-xtradb-cluster-operator/pkg/pxc/app/statefulset"
15+
)
16+
17+
func (r *ReconcilePerconaXtraDBCluster) reconcilePersistentVolumes(ctx context.Context, cr *api.PerconaXtraDBCluster) error {
18+
log := logf.FromContext(ctx)
19+
20+
pxcSet := statefulset.NewNode(cr)
21+
sts := pxcSet.StatefulSet()
22+
23+
err := r.client.Get(ctx, client.ObjectKeyFromObject(sts), sts)
24+
if err != nil {
25+
if k8serrors.IsNotFound(err) {
26+
return nil
27+
}
28+
return errors.Wrapf(err, "get statefulset/%s", sts.Name)
29+
}
30+
31+
if cr.Spec.PXC.VolumeSpec.PersistentVolumeClaim == nil {
32+
return nil
33+
}
34+
35+
var volumeTemplate corev1.PersistentVolumeClaim
36+
for _, vct := range sts.Spec.VolumeClaimTemplates {
37+
if vct.Name == "datadir" {
38+
volumeTemplate = vct
39+
}
40+
}
41+
42+
requested := cr.Spec.PXC.VolumeSpec.PersistentVolumeClaim.Resources.Requests[corev1.ResourceStorage]
43+
actual := volumeTemplate.Spec.Resources.Requests[corev1.ResourceStorage]
44+
45+
if requested.Cmp(actual) < 0 {
46+
return errors.Wrap(err, "requested storage is less than actual")
47+
}
48+
49+
if requested.Cmp(actual) == 0 {
50+
return nil
51+
}
52+
53+
// Check storage class for allowVolumeExpansion field
54+
55+
labels := map[string]string{
56+
"app.kubernetes.io/component": "pxc",
57+
"app.kubernetes.io/instance": cr.Name,
58+
"app.kubernetes.io/managed-by": "percona-xtradb-cluster-operator",
59+
"app.kubernetes.io/name": "percona-xtradb-cluster",
60+
"app.kubernetes.io/part-of": "percona-xtradb-cluster",
61+
}
62+
63+
pvcList := corev1.PersistentVolumeClaimList{}
64+
if err := r.client.List(ctx, &pvcList, client.InNamespace(cr.Namespace), client.MatchingLabels(labels)); err != nil {
65+
return errors.Wrap(err, "list persistentvolumeclaims")
66+
}
67+
68+
pvcNames := make([]string, 0, len(pvcList.Items))
69+
for _, pvc := range pvcList.Items {
70+
pvcNames = append(pvcNames, pvc.Name)
71+
}
72+
73+
log.Info("Resizing PVCs", "requested", requested, "actual", actual, "pvcList", strings.Join(pvcNames, ","))
74+
75+
log.Info("Deleting statefulset", "name", sts.Name)
76+
77+
if err := r.client.Delete(ctx, sts, client.PropagationPolicy("Orphan")); err != nil {
78+
return errors.Wrapf(err, "delete statefulset/%s", sts.Name)
79+
}
80+
81+
for _, pvc := range pvcList.Items {
82+
if !strings.HasPrefix(pvc.Name, "datadir-"+sts.Name) {
83+
continue
84+
}
85+
86+
log.Info("Resizing PVC", "name", pvc.Name)
87+
pvc.Spec.Resources.Requests[corev1.ResourceStorage] = requested
88+
89+
if err := r.client.Update(ctx, &pvc); err != nil {
90+
return errors.Wrapf(err, "update persistentvolumeclaim/%s", pvc.Name)
91+
}
92+
}
93+
94+
return nil
95+
}

0 commit comments

Comments
 (0)