Skip to content

Commit daa6fc3

Browse files
committed
Add Parallel Pod Management Policy to standalone pgadmin StatefulSet.
1 parent 3519235 commit daa6fc3

File tree

1 file changed

+32
-8
lines changed

1 file changed

+32
-8
lines changed

internal/controller/standalone_pgadmin/statefulset.go

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ import (
1919

2020
appsv1 "k8s.io/api/apps/v1"
2121
corev1 "k8s.io/api/core/v1"
22+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2223
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
24+
"sigs.k8s.io/controller-runtime/pkg/client"
2325

2426
"github.com/pkg/errors"
2527

@@ -34,6 +36,30 @@ func (r *PGAdminReconciler) reconcilePGAdminStatefulSet(
3436
configmap *corev1.ConfigMap, dataVolume *corev1.PersistentVolumeClaim,
3537
) error {
3638
sts := statefulset(r, pgadmin, configmap, dataVolume)
39+
40+
// Previous versions of PGO used a StatefulSet Pod Management Policy that could leave the Pod
41+
// in a failed state. When we see that it has the wrong policy, we will delete the StatefulSet
42+
// and then recreate it with the correct policy, as this is not a property that can be patched.
43+
// When we delete the StatefulSet, we will leave its Pods in place. They will be claimed by
44+
// the StatefulSet that gets created in the next reconcile.
45+
existing := &appsv1.StatefulSet{}
46+
if err := errors.WithStack(r.Client.Get(ctx, client.ObjectKeyFromObject(sts), existing)); err != nil {
47+
if !apierrors.IsNotFound(err) {
48+
return err
49+
}
50+
} else {
51+
if existing.Spec.PodManagementPolicy != sts.Spec.PodManagementPolicy {
52+
// We want to delete the STS without affecting the Pods, so we set the PropagationPolicy to Orphan.
53+
// The orphaned Pods will be claimed by the StatefulSet that will be created in the next reconcile.
54+
uid := existing.GetUID()
55+
version := existing.GetResourceVersion()
56+
exactly := client.Preconditions{UID: &uid, ResourceVersion: &version}
57+
propagate := client.PropagationPolicy(metav1.DeletePropagationOrphan)
58+
59+
return errors.WithStack(client.IgnoreNotFound(r.Client.Delete(ctx, existing, exactly, propagate)))
60+
}
61+
}
62+
3763
if err := errors.WithStack(r.setControllerReference(pgadmin, sts)); err != nil {
3864
return err
3965
}
@@ -70,15 +96,13 @@ func statefulset(
7096
// Don't clutter the namespace with extra ControllerRevisions.
7197
sts.Spec.RevisionHistoryLimit = initialize.Int32(0)
7298

73-
// Set the StatefulSet update strategy to "RollingUpdate", and the Partition size for the
74-
// update strategy to 0 (note that these are the defaults for a StatefulSet). This means
75-
// every pod of the StatefulSet will be deleted and recreated when the Pod template changes.
76-
// - https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#rolling-updates
77-
// - https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#forced-rollback
99+
// Use StatefulSet's "RollingUpdate" strategy and "Parallel" policy to roll
100+
// out changes to pods even when not Running or not Ready.
101+
// - https://docs.k8s.io/concepts/workloads/controllers/statefulset/#rolling-updates
102+
// - https://docs.k8s.io/concepts/workloads/controllers/statefulset/#forced-rollback
103+
// - https://kep.k8s.io/3541
104+
sts.Spec.PodManagementPolicy = appsv1.ParallelPodManagement
78105
sts.Spec.UpdateStrategy.Type = appsv1.RollingUpdateStatefulSetStrategyType
79-
sts.Spec.UpdateStrategy.RollingUpdate = &appsv1.RollingUpdateStatefulSetStrategy{
80-
Partition: initialize.Int32(0),
81-
}
82106

83107
// Use scheduling constraints from the cluster spec.
84108
sts.Spec.Template.Spec.Affinity = pgadmin.Spec.Affinity

0 commit comments

Comments
 (0)