Skip to content

Commit

Permalink
db upgrage: upgrade postgres 15 to postgres 16
Browse files Browse the repository at this point in the history
The Postgres upgrade from 15 to 16 or any later versions can be done by adding the env variable named POSTGRES_UPGRADE = copy in the pg db pod.

More about upgrade process is here: https://www.postgresql.org/docs/current/pgupgrade.html

In our case, we achieve the upgrade by setting this env var in noobaa-db-pg STS.

Once after upgrade is done, we have to remove the POSTGRES_UPGRADE env from the STS. Otherwise pg db pod fails to come up because the db pod check PG directory version against upgrade image version and exits if there is no upgrade required and POSTGRES_UPGRADE is still provided.

To remove this env, we store the upgrade status in noobaa-core CR after the PG upgrade and refer the same status during db reconcile. If the upgrade is already done, we remove this env from desired sts status.

This will help to upgrade the db smoothly

Signed-off-by: Vinayak Hariharmath <[email protected]>
  • Loading branch information
vec-tr committed Nov 15, 2024
1 parent b62bb7e commit 318d96c
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 1 deletion.
2 changes: 1 addition & 1 deletion pkg/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ var NooBaaImage = ContainerImage

// DBImage is the default db image url
// it can be overridden for testing or different registry locations.
var DBImage = "quay.io/sclorg/postgresql-15-c9s"
var DBImage = "quay.io/sclorg/postgresql-16-c9s"

// Psql12Image is the default postgres12 db image url
// currently it can not be overridden.
Expand Down
103 changes: 103 additions & 0 deletions pkg/system/phase2_creating.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

const (
Expand Down Expand Up @@ -120,6 +121,9 @@ func (r *Reconciler) ReconcilePhaseCreatingForMainClusters() error {
return err
}

if err := r.UpgradeDb(); err != nil {
return err
}
// create the db only if postgres secret is not given
if r.NooBaa.Spec.ExternalPgSecret == nil {
if err := r.ReconcileDB(); err != nil {
Expand Down Expand Up @@ -152,6 +156,34 @@ func (r *Reconciler) ReconcilePhaseCreatingForMainClusters() error {
return nil
}

func (r *Reconciler) UpgradeDb() error {
var result controllerutil.OperationResult
var err error

if r.NooBaa.Status.PostgresUpdatePhase != nbv1.UpgradePhaseFinished {
result, err = controllerutil.CreateOrUpdate(
r.Ctx, r.Client, r.NooBaaPostgresDB, func() error {
r.setPGUpgradeEnvInSTS()
r.updateDBImageForUpgrade()
return nil
},
)

if result == controllerutil.OperationResultUpdated {
r.NooBaa.Status.PostgresUpdatePhase = nbv1.UpgradePhaseFinished
}
} else if r.NooBaa.Status.PostgresUpdatePhase == nbv1.UpgradePhaseFinished {
_, err = controllerutil.CreateOrUpdate(
r.Ctx, r.Client, r.NooBaaPostgresDB, func() error {
r.unSetPGUpgradeEnvInSTS()
return nil
},
)
}

return err
}

// SetDesiredServiceAccount updates the ServiceAccount as desired for reconciling
func (r *Reconciler) SetDesiredServiceAccount() error {
if r.ServiceAccount.Annotations == nil {
Expand Down Expand Up @@ -223,6 +255,68 @@ func (r *Reconciler) SetDesiredServiceDBForPostgres() error {
return nil
}

func (r *Reconciler) updateDBImageForUpgrade() {
var podSpec = &r.NooBaaPostgresDB.Spec.Template.Spec

for i := range podSpec.Containers {
c := &podSpec.Containers[i]
if c.Name == "db" {
// Fetch the DB image from options.go
c.Image = options.DBImage
if r.NooBaa.Spec.DBResources != nil {
c.Resources = *r.NooBaa.Spec.DBResources
}

c.Lifecycle = &corev1.Lifecycle{
PreStop: &corev1.LifecycleHandler{
Exec: &corev1.ExecAction{
Command: []string{"/bin/sh", "-c", "pg_ctl -D /var/lib/pgsql/data/userdata/ -w -t 60 -m fast stop"},
},
},
}

}
}
}

// Set env "POSTGRESQL_UPGRADE=copy" in PG sts to iniate the upgrade
func (r *Reconciler) setPGUpgradeEnvInSTS() {
for i, container := range r.NooBaaPostgresDB.Spec.Template.Spec.Containers {
if container.Name == "db" {
for _, env := range container.Env {
if env.Name == "POSTGRESQL_UPGRADE" {
return
}
}
envVars := container.Env
newEnvVar := corev1.EnvVar{
Name: "POSTGRESQL_UPGRADE",
Value: "copy",
}

envVars = append(envVars, newEnvVar)
r.NooBaaPostgresDB.Spec.Template.Spec.Containers[i].Env = envVars
return
}
}
}

// unSet env "POSTGRESQL_UPGRADE=copy" in PG sts after upgrade
func (r *Reconciler) unSetPGUpgradeEnvInSTS() {
for i, container := range r.NooBaaPostgresDB.Spec.Template.Spec.Containers {
if container.Name == "db" {
newEnvVars := []corev1.EnvVar{}
for _, env := range container.Env {
if env.Name != "POSTGRESQL_UPGRADE" {
newEnvVars = append(newEnvVars, env)
}
}
r.NooBaaPostgresDB.Spec.Template.Spec.Containers[i].Env = newEnvVars
return
}
}
}

// SetDesiredNooBaaDB updates the NooBaaDB as desired for reconciling
func (r *Reconciler) SetDesiredNooBaaDB() error {
var NooBaaDBTemplate *appsv1.StatefulSet = nil
Expand All @@ -239,6 +333,14 @@ func (r *Reconciler) SetDesiredNooBaaDB() error {
NooBaaDB.Spec.ServiceName = r.ServiceDbPg.Name
NooBaaDBTemplate = util.KubeObject(bundle.File_deploy_internal_statefulset_postgres_db_yaml).(*appsv1.StatefulSet)

// Make sure the POSTGRES_UPGRADE=copy flag is unset before reconcile.
// Not setting the flag soon after sts update in Upgrade_db() because
// removing the flag while db upgrade still in progress will create issue.
// So doing it here
if r.NooBaa.Status.PostgresUpdatePhase == nbv1.UpgradePhaseFinished {
r.unSetPGUpgradeEnvInSTS()
}

podSpec := &NooBaaDB.Spec.Template.Spec
podSpec.ServiceAccountName = "noobaa-db"
defaultUID := int64(10001)
Expand Down Expand Up @@ -1150,6 +1252,7 @@ func (r *Reconciler) ReconcileDB() error {
}

}

return nil
}

Expand Down

0 comments on commit 318d96c

Please sign in to comment.