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

Add Nebula scheduled backup CRD #416

Merged
merged 11 commits into from
Jan 27, 2024
66 changes: 42 additions & 24 deletions apis/apps/v1alpha1/backupschedule_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,54 +20,72 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// BackupConditionType represents a valid condition of a Backup.
type ScheduledBackupConditionType string

// +genclient
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName="bs"
// +kubebuilder:resource:shortName="nsb"
// +kubebuilder:printcolumn:name="Schedule",type=string,JSONPath=`.spec.schedule`,description="The current schedule set for the scheduled backup"
// +kubebuilder:printcolumn:name="Pause",type=string,JSONPath=`.spec.pause`,description="Whether or not the scheduled backup is paused"
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
// +kubebuilder:printcolumn:name="Last Triggered Backup",type=string,JSONPath=`.status.lastScheduledBackupTime`,description="The timestamp at which the last backup was triggered"
// +kubebuilder:printcolumn:name="Last Successful Backup",format=date-time,type=string,JSONPath=`.status.lastSuccessfulBackupTime`,description="The timestamp at which the last backup was successful completed"
// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp`

type BackupSchedule struct {
type NebulaScheduledBackup struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec BackupScheduleSpec `json:"spec,omitempty"`
Status BackupScheduleStatus `json:"status,omitempty"`
Spec ScheduledBackupSpec `json:"spec,omitempty"`
Status ScheduledBackupStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
// BackupScheduleList contains a list of BackupSchedule.
type BackupScheduleList struct {
// NebulaScheduledBackupList contains a list of NebulaScheduledBackup.
type NebulaScheduledBackupList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`

Items []BackupSchedule `json:"items"`
Items []NebulaScheduledBackup `json:"items"`
}

// BackupScheduleSpec contains the specification for a backupSchedule of a nebula cluster backupSchedule.
type BackupScheduleSpec struct {
// ScheduledBackupSpec contains the specification for a NebulaScheduledBackup of a nebula cluster NebulaScheduledBackup.
type ScheduledBackupSpec struct {
// Schedule specifies the cron string used for backup scheduling.
Schedule string `json:"schedule"`
// Pause means paused backupSchedule
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
Pause bool `json:"pause,omitempty"`
// MaxBackups is to specify how many backups we want to keep
// 0 is magic number to indicate un-limited backups.
// if MaxBackups and MaxReservedTime are set at the same time, MaxReservedTime is preferred
Pause *bool `json:"pause,omitempty"`
// MaxBackups specifies how many backups we want to keep in the remote storage bucket.
// 0 is the magic number to indicate unlimited backups.
// if both MaxBackups and MaxReservedTime are set at the same time, MaxReservedTime will be used
// and MaxBackups is ignored.
MaxBackups *int32 `json:"maxBackups,omitempty"`
// MaxReservedTime is to specify how long backups we want to keep.
MaxReservedTime *string `json:"maxReservedTime,omitempty"`
// BackupTemplate is the specification of the backup structure to get scheduled.
// MaxRetentionTime specifies how long we want the backups in the remote storage bucket to be kept for.
Comment on lines +63 to +66
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't it be the case that if either of these two parameters meets the condition, it should be deleted? Instead of setting both parameters and using only one as the basis for judgement.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The current design is to use MaxReservedTime if both are specified as this is simpler understand for the customer and easier to implement. Otherwise we don't know whether the customer means "delete a backup if there are more then MaxBackups and the backup is older than MaxReservedTime" or "delete a backup if there are more then MaxBackups or if the backup if older than MaxReservedTime".

We can definitely think about which version we want to support and change the design to accommodate both parameters in a future version if there's customer demand for this. What do you think @MegaByte875

Copy link
Contributor

Choose a reason for hiding this comment

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

Here's an example for a simple task: a log cleaning function. There are two settings: one for the maximum number of days to be retained, and one for the maximum storage to be kept. If a user configures both, how should we proceed?

I assume that the user wants to keep a certain number of days, but they also don't want to consume too much storage.

Returning to this issue, I think it's similar. By the way, if the user only wants to retain a certain number of days, why would they configure MaxBackups?

// +kubebuilder:validation:Pattern=`^([0-9]+(\.[0-9]+)?[a-zA-Z]+)+$`
MaxRetentionTime *string `json:"maxRetentionTime,omitempty"`
// BackupTemplate is the specification of the backup structure to schedule.
BackupTemplate BackupSpec `json:"backupTemplate"`
// LogBackupTemplate is the specification of the log backup structure to get scheduled.
// MaxSuccessfulNublaBackupJobs specifies the maximum number of successful backup jobs to keep
MaxSuccessfulNebulaBackupJobs *int32 `json:"maxSuccessfulNebulaBackupJobs,omitempty"`
// MaxFailedNebulaBackupJobs specifies the maximum number of failed backup jobs to keep
MaxFailedNebulaBackupJobs *int32 `json:"maxFailedNebulaBackupJobs,omitempty"`
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
}

// BackupScheduleStatus represents the current status of a nebula cluster backupSchedule.
type BackupScheduleStatus struct {
// LastBackup represents the last backup.
LastBackup string `json:"lastBackup,omitempty"`
// LastBackupTime represents the last time the backup was successfully created.
LastBackupTime *metav1.Time `json:"lastBackupTime,omitempty"`
// ScheduledBackupStatus represents the current status of a nebula cluster NebulaScheduledBackup.
type ScheduledBackupStatus struct {
// CurrPauseStatus represent the current pause status of the nebula scheduled backup
CurrPauseStatus *bool `json:"currPauseStatus,omitempty"`
// LastBackup represents the last backup. Used for scheduled incremental backups. Not supported for now.
//LastBackup string `json:"lastBackup,omitempty"`
// LastScheduledBackupTime represents the last time a backup job was successfully scheduled.
LastScheduledBackupTime *metav1.Time `json:"lastScheduledBackupTime,omitempty"`
// LastSuccessfulBackupTime represents the last time a backup was successfully created.
LastSuccessfulBackupTime *metav1.Time `json:"lastSuccessfulBackupTime,omitempty"`
// MostRecentJobFailed represents if the most recent backup job failed.
MostRecentJobFailed *bool `json:"mostRecentJobFailed,omitempty"`
}

func init() {
SchemeBuilder.Register(&BackupSchedule{}, &BackupScheduleList{})
SchemeBuilder.Register(&NebulaScheduledBackup{}, &NebulaScheduledBackupList{})
}
14 changes: 10 additions & 4 deletions apis/apps/v1alpha1/nebulabackup_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ limitations under the License.
package v1alpha1

import (
"time"

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -51,8 +53,6 @@ type NebulaBackupList struct {
type BackupConditionType string

const (
// BackupPending means the backup is pending, waiting for create backup job
BackupPending BackupConditionType = "Pending"
// BackupRunning means the backup is running.
BackupRunning BackupConditionType = "Running"
// BackupComplete means the backup has successfully executed and the
Expand Down Expand Up @@ -98,16 +98,22 @@ type BackupSpec struct {
NodeSelector map[string]string `json:"nodeSelector,omitempty"`

BR *BRConfig `json:"br,omitempty"`

// NumBackupsKeep is to specify how many backups we want to keep. Used for scheduled backups only.
NumBackupsKeep *int32 `json:"maxBackups,omitempty"`

// ReservedTimeEpoach is the epoach time for how long we want to keep the backups. Used for scheduled backups only.
ReservedTimeEpoch *time.Duration `json:"maxReservedTimeEpoch,omitempty"`
kevinliu24 marked this conversation as resolved.
Show resolved Hide resolved
}

// BackupStatus represents the current status of a nebula cluster backup.
type BackupStatus struct {
// TimeStarted is the time at which the backup was started.
// +nullable
TimeStarted metav1.Time `json:"timeStarted,omitempty"`
TimeStarted *metav1.Time `json:"timeStarted,omitempty"`
// TimeCompleted is the time at which the backup was completed.
// +nullable
TimeCompleted metav1.Time `json:"timeCompleted,omitempty"`
TimeCompleted *metav1.Time `json:"timeCompleted,omitempty"`
// Phase is a user readable state inferred from the underlying Backup conditions
Phase BackupConditionType `json:"phase,omitempty"`
// +nullable
Expand Down
Loading