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

support cleanPolicy for backup CR #3002

Merged
merged 16 commits into from
Jul 24, 2020
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions cmd/backup-manager/app/clean/clean.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"io"
"os/exec"
"strings"

"k8s.io/klog"

Expand Down Expand Up @@ -67,14 +68,14 @@ func (bo *Options) cleanRemoteBackupData(bucket string, opts []string) error {
destBucket := util.NormalizeBucketURI(bucket)
args := util.ConstructArgs(constants.RcloneConfigArg, opts, "deletefile", destBucket, "")
output, err := exec.Command("rclone", args...).CombinedOutput()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
if code := exitError.ExitCode(); code == 3 || code == 4 {
klog.Infof("cluster %s backup %s has already been deleted before", bo, bucket)
return nil
}
}
return fmt.Errorf("cluster %s, execute rclone deletefile command failed, output: %s, err: %v", bo, string(output), err)
if err != nil && !strings.Contains(string(output), "doesn't exist") {
return fmt.Errorf("cluster %s, execute rclone deletefile command to delete archive failed, output: %s, err: %v", bo, string(output), err)
Copy link
Contributor

Choose a reason for hiding this comment

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

why changing this back?

Copy link
Contributor Author

@lichunzhu lichunzhu Jul 24, 2020

Choose a reason for hiding this comment

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

Because according to test, this error code is not accurate. When rclone returns dir doesn't exist error the exit code is 1. May the last time I forgot to use hack/local-up-operator.sh to update operator.

Copy link
Contributor

@cofyc cofyc Jul 24, 2020

Choose a reason for hiding this comment

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

maybe rclone delete is a better command in this scenario

https://rclone.org/commands/rclone_delete/

in my testing, it succeeds if no file found at the specified path

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. It won't even return error. Should we use this command?
C.C. @DanielZhangQD

Copy link
Contributor

Choose a reason for hiding this comment

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

It's OK if the file can be removed if exist.

Copy link
Contributor Author

@lichunzhu lichunzhu Jul 24, 2020

Choose a reason for hiding this comment

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

Revise to rclone delete in 4e1d38f

}

args = util.ConstructArgs(constants.RcloneConfigArg, opts, "deletefile", fmt.Sprintf("%s.tmp", destBucket), "")
Copy link
Contributor

@cofyc cofyc Jul 24, 2020

Choose a reason for hiding this comment

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

when will this *.tmp file be created?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After file is archived and uploaded to S3.

  1. upload archive file to *.tgz.tmp
  2. move *.tgz.tmp to *.tgz

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

And this is for backup with dumpling only.

output, err = exec.Command("rclone", args...).CombinedOutput()
if err != nil && !strings.Contains(string(output), "doesn't exist") {
return fmt.Errorf("cluster %s, execute rclone deletefile command to delete tmp file failed, output: %s, err: %v", bo, string(output), err)
}

klog.Infof("cluster %s backup %s was deleted successfully", bo, bucket)
Expand Down
2 changes: 1 addition & 1 deletion cmd/backup-manager/app/export/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,7 @@ func (bm *BackupManager) performBackup(backup *v1alpha1.Backup, db *sql.DB) erro

remotePath := strings.TrimPrefix(archiveBackupPath, constants.BackupRootPath+"/")
bucketURI := bm.getDestBucketURI(remotePath)
backup.Status.BackupPath = bucketURI
err = bm.backupDataToRemote(archiveBackupPath, bucketURI, opts)
if err != nil {
errs = append(errs, err)
Expand All @@ -342,7 +343,6 @@ func (bm *BackupManager) performBackup(backup *v1alpha1.Backup, db *sql.DB) erro

finish := time.Now()

backup.Status.BackupPath = bucketURI
backup.Status.TimeStarted = metav1.Time{Time: started}
backup.Status.TimeCompleted = metav1.Time{Time: finish}
backup.Status.BackupSize = size
Expand Down
24 changes: 18 additions & 6 deletions docs/api-references/docs.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,13 +267,15 @@ string
</tr>
<tr>
<td>
<code>cleanData</code></br>
<code>cleanPolicy</code></br>
<em>
bool
<a href="#cleanpolicytype">
CleanPolicyType
</a>
</em>
</td>
<td>
<p>CleanData denotes whether to clean backup data before the object is deleted from the cluster</p>
<p>CleanPolicy denotes whether to clean backup data before the object is deleted from the cluster</p>
</td>
</tr>
</table>
Expand Down Expand Up @@ -2580,13 +2582,15 @@ string
</tr>
<tr>
<td>
<code>cleanData</code></br>
<code>cleanPolicy</code></br>
<em>
bool
<a href="#cleanpolicytype">
CleanPolicyType
</a>
</em>
</td>
<td>
<p>CleanData denotes whether to clean backup data before the object is deleted from the cluster</p>
<p>CleanPolicy denotes whether to clean backup data before the object is deleted from the cluster</p>
</td>
</tr>
</tbody>
Expand Down Expand Up @@ -2965,6 +2969,14 @@ Optional: Defaults to range</p>
</tr>
</tbody>
</table>
<h3 id="cleanpolicytype">CleanPolicyType</h3>
<p>
(<em>Appears on:</em>
<a href="#backupspec">BackupSpec</a>)
</p>
<p>
<p>CleanPolicyType represents the specific delete cloud data policy</p>
</p>
<h3 id="commonconfig">CommonConfig</h3>
<p>
(<em>Appears on:</em>
Expand Down
8 changes: 4 additions & 4 deletions manifests/crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11616,8 +11616,8 @@ spec:
required:
- cluster
type: object
cleanData:
type: boolean
cleanPolicy:
type: string
dumpling:
properties:
options:
Expand Down Expand Up @@ -12517,8 +12517,8 @@ spec:
required:
- cluster
type: object
cleanData:
type: boolean
cleanPolicy:
type: string
dumpling:
properties:
options:
Expand Down
6 changes: 3 additions & 3 deletions pkg/apis/pingcap/v1alpha1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 15 additions & 2 deletions pkg/apis/pingcap/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1111,6 +1111,19 @@ type TiDBAccessConfig struct {
TLSClientSecretName *string `json:"tlsClientSecretName,omitempty"`
}

// +k8s:openapi-gen=true
// CleanPolicyType represents the specific delete cloud data policy
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// CleanPolicyType represents the specific delete cloud data policy
// CleanPolicyType represents the clean policy of backup data in remote storage

type CleanPolicyType string

const (
// CleanPolicyTypeRetain represents the clean policy is retain
CleanPolicyTypeRetain CleanPolicyType = "Retain"
// CleanPolicyTypeOnFailure represents the clean policy is on failure
CleanPolicyTypeOnFailure CleanPolicyType = "OnFailure"
// CleanPolicyTypeIfFailed represents the clean policy is delete
CleanPolicyTypeDelete CleanPolicyType = "Delete"
Copy link
Contributor

Choose a reason for hiding this comment

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

Please describe the behavior clearly for each policy.

)

// +k8s:openapi-gen=true
// BackupSpec contains the backup specification for a tidb cluster.
type BackupSpec struct {
Expand Down Expand Up @@ -1148,8 +1161,8 @@ type BackupSpec struct {
UseKMS bool `json:"useKMS,omitempty"`
// Specify service account of backup
ServiceAccount string `json:"serviceAccount,omitempty"`
// CleanData denotes whether to clean backup data before the object is deleted from the cluster
CleanData bool `json:"cleanData,omitempty"`
// CleanPolicy denotes whether to clean backup data before the object is deleted from the cluster
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
// CleanPolicy denotes whether to clean backup data before the object is deleted from the cluster
// CleanPolicy denotes whether to clean backup data when the object is deleted from the cluster

Copy link
Contributor

Choose a reason for hiding this comment

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

What's the default behavior?

CleanPolicy CleanPolicyType `json:"cleanPolicy,omitempty"`
}

// +k8s:openapi-gen=true
Expand Down
14 changes: 12 additions & 2 deletions pkg/backup/backup/backup_cleaner.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ func NewBackupCleaner(
}

func (bc *backupCleaner) Clean(backup *v1alpha1.Backup) error {
if backup.DeletionTimestamp == nil || !backup.Spec.CleanData {
// The backup object has not been deleted,do nothing
if backup.DeletionTimestamp == nil ||
backup.Spec.CleanPolicy == v1alpha1.CleanPolicyTypeRetain || backup.Spec.CleanPolicy == "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

!shouldCleanData()?

// The backup object has not been deleted or we need to retain backup data,do nothing
return nil
}
ns := backup.GetNamespace()
Expand All @@ -80,6 +81,15 @@ func (bc *backupCleaner) Clean(backup *v1alpha1.Backup) error {
Status: corev1.ConditionTrue,
})
}

if backup.Spec.CleanPolicy == v1alpha1.CleanPolicyTypeOnFailure && !v1alpha1.IsBackupFailed(backup) {
Copy link
Contributor

Choose a reason for hiding this comment

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

This logic should be in L60 and we should not set BackupClean condition for this case as the data is not cleaned but retained for the successful backup.

Copy link
Contributor

Choose a reason for hiding this comment

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

The finalizer handling logic should also be updated accordingly.

// the backup policy is on failure but backup CR succeeds, skip clean-up.
return bc.statusUpdater.Update(backup, &v1alpha1.BackupCondition{
Type: v1alpha1.BackupClean,
Status: corev1.ConditionTrue,
})
}

// not found clean job, create it
job, reason, err := bc.makeCleanJob(backup)
if err != nil {
Expand Down
16 changes: 14 additions & 2 deletions pkg/controller/backup/backup_control.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,8 @@ func (bc *defaultBackupControl) removeProtectionFinalizer(backup *v1alpha1.Backu
ns := backup.GetNamespace()
name := backup.GetName()

if backup.Spec.CleanData && isDeletionCandidate(backup) && v1alpha1.IsBackupClean(backup) {
if backup.Spec.CleanPolicy != v1alpha1.CleanPolicyTypeRetain && backup.Spec.CleanPolicy != "" &&
Copy link
Contributor

Choose a reason for hiding this comment

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

v1alpha1.ShouldCleanData(backup)

isDeletionCandidate(backup) && v1alpha1.IsBackupClean(backup) {
backup.Finalizers = slice.RemoveString(backup.Finalizers, label.BackupProtectionFinalizer, nil)
_, err := bc.cli.PingcapV1alpha1().Backups(ns).Update(backup)
if err != nil {
Expand All @@ -98,7 +99,18 @@ func (bc *defaultBackupControl) removeProtectionFinalizer(backup *v1alpha1.Backu
}

func needToAddFinalizer(backup *v1alpha1.Backup) bool {
return backup.DeletionTimestamp == nil && backup.Spec.CleanData && !slice.ContainsString(backup.Finalizers, label.BackupProtectionFinalizer, nil)
return backup.DeletionTimestamp == nil && shouldCleanData(backup) && !slice.ContainsString(backup.Finalizers, label.BackupProtectionFinalizer, nil)
}

func shouldCleanData(backup *v1alpha1.Backup) bool {
switch backup.Spec.CleanPolicy {
case v1alpha1.CleanPolicyTypeDelete, v1alpha1.CleanPolicyTypeOnFailure:
return true
case v1alpha1.CleanPolicyTypeRetain:
return false
Copy link
Contributor

Choose a reason for hiding this comment

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

This can be removed?

default:
return false
}
}

func isDeletionCandidate(backup *v1alpha1.Backup) bool {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controller/backup/backup_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func newBackup() *v1alpha1.Backup {
},
StorageClassName: pointer.StringPtr("local-storage"),
StorageSize: "1Gi",
CleanData: true,
CleanPolicy: v1alpha1.CleanPolicyTypeDelete,
Copy link
Contributor

Choose a reason for hiding this comment

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

can we add tests for other values?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

will add tests later

},
}
}
2 changes: 1 addition & 1 deletion tests/pkg/fixture/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ func GetBackupCRDWithS3(tc *v1alpha1.TidbCluster, fromSecretName, brType string,
ClusterNamespace: tc.GetNamespace(),
SendCredToTikv: &sendCredToTikv,
},
CleanData: true,
CleanPolicy: v1alpha1.CleanPolicyTypeDelete,
},
}
if brType == DumperType {
Expand Down