Add logical backup (#442)

* Add k8s cron job to spawn logical backups

* Minor doc updates
This commit is contained in:
Sergey Dudoladov
2019-05-16 15:52:01 +02:00
committed by GitHub
parent 2c02b371e2
commit f3e1e80aaf
24 changed files with 526 additions and 55 deletions
+56 -2
View File
@@ -81,6 +81,7 @@ type Cluster struct {
currentProcess Process
processMu sync.RWMutex // protects the current operation for reporting, no need to hold the master mutex
specMu sync.RWMutex // protects the spec for reporting, no need to hold the master mutex
}
type compareStatefulsetResult struct {
@@ -298,6 +299,13 @@ func (c *Cluster) Create() error {
c.logger.Infof("databases have been successfully created")
}
if c.Postgresql.Spec.EnableLogicalBackup {
if err := c.createLogicalBackupJob(); err != nil {
return fmt.Errorf("could not create a k8s cron job for logical backups: %v", err)
}
c.logger.Info("a k8s cron job for logical backup has been successfully created")
}
if err := c.listResources(); err != nil {
c.logger.Errorf("could not list resources: %v", err)
}
@@ -481,8 +489,10 @@ func compareResoucesAssumeFirstNotNil(a *v1.ResourceRequirements, b *v1.Resource
}
// Update changes Kubernetes objects according to the new specification. Unlike the sync case, the missing object.
// (i.e. service) is treated as an error.
// Update changes Kubernetes objects according to the new specification. Unlike the sync case, the missing object
// (i.e. service) is treated as an error
// logical backup cron jobs are an exception: a user-initiated Update can enable a logical backup job
// for a cluster that had no such job before. In this case a missing job is not an error.
func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
updateFailed := false
@@ -569,6 +579,43 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
}
}()
// logical backup job
func() {
// create if it did not exist
if !oldSpec.Spec.EnableLogicalBackup && newSpec.Spec.EnableLogicalBackup {
c.logger.Debugf("creating backup cron job")
if err := c.createLogicalBackupJob(); err != nil {
c.logger.Errorf("could not create a k8s cron job for logical backups: %v", err)
updateFailed = true
return
}
}
// delete if no longer needed
if oldSpec.Spec.EnableLogicalBackup && !newSpec.Spec.EnableLogicalBackup {
c.logger.Debugf("deleting backup cron job")
if err := c.deleteLogicalBackupJob(); err != nil {
c.logger.Errorf("could not delete a k8s cron job for logical backups: %v", err)
updateFailed = true
return
}
}
// apply schedule changes
// this is the only parameter of logical backups a user can overwrite in the cluster manifest
if (oldSpec.Spec.EnableLogicalBackup && newSpec.Spec.EnableLogicalBackup) &&
(newSpec.Spec.LogicalBackupSchedule != oldSpec.Spec.LogicalBackupSchedule) {
c.logger.Debugf("updating schedule of the backup cron job")
if err := c.syncLogicalBackupJob(); err != nil {
c.logger.Errorf("could not sync logical backup jobs: %v", err)
updateFailed = true
}
}
}()
// Roles and Databases
if !(c.databaseAccessDisabled() || c.getNumberOfInstances(&c.Spec) <= 0) {
c.logger.Debugf("syncing roles")
@@ -597,6 +644,12 @@ func (c *Cluster) Delete() {
c.mu.Lock()
defer c.mu.Unlock()
// delete the backup job before the stateful set of the cluster to prevent connections to non-existing pods
// deleting the cron job also removes pods and batch jobs it created
if err := c.deleteLogicalBackupJob(); err != nil {
c.logger.Warningf("could not remove the logical backup k8s cron job; %v", err)
}
if err := c.deleteStatefulSet(); err != nil {
c.logger.Warningf("could not delete statefulset: %v", err)
}
@@ -629,6 +682,7 @@ func (c *Cluster) Delete() {
if err := c.deletePatroniClusterObjects(); err != nil {
c.logger.Warningf("could not remove leftover patroni objects; %v", err)
}
}
//NeedsRepair returns true if the cluster should be included in the repair scan (based on its in-memory status).