diff --git a/docs/api-references/docs.md b/docs/api-references/docs.md index 789440c5fb1..09a34d1d0ba 100644 --- a/docs/api-references/docs.md +++ b/docs/api-references/docs.md @@ -1473,6 +1473,32 @@ For BR image, if it does not contain tag, Pod will use image ‘ToolImage:${ +warmup
+ + +RestoreWarmupMode + + + + +(Optional) +

Warmup represents whether to initialize TiKV volumes after volume snapshot restore

+ + + + +warmupImage
+ +string + + + +(Optional) +

WarmupImage represents using what image to initialize TiKV volumes

+ + + + podSecurityContext
@@ -13890,6 +13916,32 @@ For BR image, if it does not contain tag, Pod will use image ‘ToolImage:${ +warmup
+ +
+RestoreWarmupMode + + + + +(Optional) +

Warmup represents whether to initialize TiKV volumes after volume snapshot restore

+ + + + +warmupImage
+ +string + + + +(Optional) +

WarmupImage represents using what image to initialize TiKV volumes

+ + + + podSecurityContext
@@ -14008,6 +14060,14 @@ RestoreConditionType +

RestoreWarmupMode

+

+(Appears on: +RestoreSpec) +

+

+

RestoreWarmupMode represents when to initialize TiKV volumes

+

S3StorageProvider

(Appears on: diff --git a/docs/api-references/federation-docs.md b/docs/api-references/federation-docs.md index 3986c3e52c4..c73f81a7c7b 100644 --- a/docs/api-references/federation-docs.md +++ b/docs/api-references/federation-docs.md @@ -1235,6 +1235,30 @@ string

PriorityClassName of Restore Job Pods

+ + +warmup
+ +github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1.RestoreWarmupMode + + + +(Optional) +

Warmup represents whether to initialize TiKV volumes after volume snapshot restore

+ + + + +warmupImage
+ +string + + + +(Optional) +

WarmupImage represents using what image to initialize TiKV volumes

+ +

VolumeRestoreSpec

diff --git a/manifests/crd.yaml b/manifests/crd.yaml index 36c7bd0582c..5a03e6f6e3f 100644 --- a/manifests/crd.yaml +++ b/manifests/crd.yaml @@ -14305,6 +14305,10 @@ spec: type: boolean volumeAZ: type: string + warmup: + type: string + warmupImage: + type: string type: object status: properties: diff --git a/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml b/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml index a4bb653bc64..e57a6cc6b9c 100644 --- a/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml +++ b/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml @@ -945,6 +945,10 @@ spec: type: array toolImage: type: string + warmup: + type: string + warmupImage: + type: string type: object type: object status: diff --git a/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml index ebacb652f49..ac66d59207c 100644 --- a/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml +++ b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml @@ -945,6 +945,10 @@ spec: type: array toolImage: type: string + warmup: + type: string + warmupImage: + type: string type: object type: object status: diff --git a/manifests/crd/v1/pingcap.com_restores.yaml b/manifests/crd/v1/pingcap.com_restores.yaml index 30fa936697e..a06a96c2544 100644 --- a/manifests/crd/v1/pingcap.com_restores.yaml +++ b/manifests/crd/v1/pingcap.com_restores.yaml @@ -2083,6 +2083,10 @@ spec: type: boolean volumeAZ: type: string + warmup: + type: string + warmupImage: + type: string type: object status: properties: diff --git a/manifests/crd/v1beta1/pingcap.com_restores.yaml b/manifests/crd/v1beta1/pingcap.com_restores.yaml index 10ba4550ee3..8da27871d8c 100644 --- a/manifests/crd/v1beta1/pingcap.com_restores.yaml +++ b/manifests/crd/v1beta1/pingcap.com_restores.yaml @@ -2082,6 +2082,10 @@ spec: type: boolean volumeAZ: type: string + warmup: + type: string + warmupImage: + type: string type: object status: properties: diff --git a/manifests/crd_v1beta1.yaml b/manifests/crd_v1beta1.yaml index 5e571d724b3..aad8edde3da 100644 --- a/manifests/crd_v1beta1.yaml +++ b/manifests/crd_v1beta1.yaml @@ -14285,6 +14285,10 @@ spec: type: boolean volumeAZ: type: string + warmup: + type: string + warmupImage: + type: string type: object status: properties: diff --git a/manifests/federation-crd.yaml b/manifests/federation-crd.yaml index f9d1d557f99..7cea57c9c5e 100644 --- a/manifests/federation-crd.yaml +++ b/manifests/federation-crd.yaml @@ -2019,6 +2019,10 @@ spec: type: array toolImage: type: string + warmup: + type: string + warmupImage: + type: string type: object type: object status: diff --git a/manifests/federation-crd_v1beta1.yaml b/manifests/federation-crd_v1beta1.yaml index d5449d64733..0afaa58c97a 100644 --- a/manifests/federation-crd_v1beta1.yaml +++ b/manifests/federation-crd_v1beta1.yaml @@ -2023,6 +2023,10 @@ spec: type: array toolImage: type: string + warmup: + type: string + warmupImage: + type: string type: object type: object status: diff --git a/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go index 51c99cfd164..aa9a4d45041 100644 --- a/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go @@ -674,6 +674,20 @@ func schema_apis_federation_pingcap_v1alpha1_VolumeRestoreMemberSpec(ref common. Format: "", }, }, + "warmup": { + SchemaProps: spec.SchemaProps{ + Description: "Warmup represents whether to initialize TiKV volumes after volume snapshot restore", + Type: []string{"string"}, + Format: "", + }, + }, + "warmupImage": { + SchemaProps: spec.SchemaProps{ + Description: "WarmupImage represents using what image to initialize TiKV volumes", + Type: []string{"string"}, + Format: "", + }, + }, }, }, }, diff --git a/pkg/apis/federation/pingcap/v1alpha1/types.go b/pkg/apis/federation/pingcap/v1alpha1/types.go index e6b8500b3d5..44b6f7ebd49 100644 --- a/pkg/apis/federation/pingcap/v1alpha1/types.go +++ b/pkg/apis/federation/pingcap/v1alpha1/types.go @@ -327,6 +327,12 @@ type VolumeRestoreMemberSpec struct { ServiceAccount string `json:"serviceAccount,omitempty"` // PriorityClassName of Restore Job Pods PriorityClassName string `json:"priorityClassName,omitempty"` + // Warmup represents whether to initialize TiKV volumes after volume snapshot restore + // +optional + Warmup pingcapv1alpha1.RestoreWarmupMode `json:"warmup,omitempty"` + // WarmupImage represents using what image to initialize TiKV volumes + // +optional + WarmupImage string `json:"warmupImage,omitempty"` } type VolumeRestoreMemberBackupInfo struct { diff --git a/pkg/apis/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/pingcap/v1alpha1/openapi_generated.go index 67a2b3410f3..5bdbc7ee528 100644 --- a/pkg/apis/pingcap/v1alpha1/openapi_generated.go +++ b/pkg/apis/pingcap/v1alpha1/openapi_generated.go @@ -7546,6 +7546,20 @@ func schema_pkg_apis_pingcap_v1alpha1_RestoreSpec(ref common.ReferenceCallback) }, }, }, + "warmup": { + SchemaProps: spec.SchemaProps{ + Description: "Warmup represents whether to initialize TiKV volumes after volume snapshot restore", + Type: []string{"string"}, + Format: "", + }, + }, + "warmupImage": { + SchemaProps: spec.SchemaProps{ + Description: "WarmupImage represents using what image to initialize TiKV volumes", + Type: []string{"string"}, + Format: "", + }, + }, "podSecurityContext": { SchemaProps: spec.SchemaProps{ Description: "PodSecurityContext of the component", diff --git a/pkg/apis/pingcap/v1alpha1/types.go b/pkg/apis/pingcap/v1alpha1/types.go index 84429061b49..7b627245922 100644 --- a/pkg/apis/pingcap/v1alpha1/types.go +++ b/pkg/apis/pingcap/v1alpha1/types.go @@ -2433,12 +2433,12 @@ type RestoreSpec struct { ImagePullSecrets []corev1.LocalObjectReference `json:"imagePullSecrets,omitempty"` // TableFilter means Table filter expression for 'db.table' matching. BR supports this from v4.0.3. TableFilter []string `json:"tableFilter,omitempty"` - // ImagePullSecrets represents whether to initialize TiKV volumes after volume snapshot restore + // Warmup represents whether to initialize TiKV volumes after volume snapshot restore // +optional - WarmUp bool `json:"warmUp,omitempty"` - // ImagePullSecrets represents using what image to initialize TiKV volumes + Warmup RestoreWarmupMode `json:"warmup,omitempty"` + // WarmupImage represents using what image to initialize TiKV volumes // +optional - WarmUpImage string `json:"warmUpImage,omitempty"` + WarmupImage string `json:"warmupImage,omitempty"` // PodSecurityContext of the component // +optional @@ -2460,6 +2460,16 @@ const ( FederalVolumeRestoreFinish FederalVolumeRestorePhase = "restore-finish" ) +// RestoreWarmupMode represents when to initialize TiKV volumes +type RestoreWarmupMode string + +const ( + // RestoreWarmupModeSync means initialize TiKV volumes before TiKV starts + RestoreWarmupModeSync RestoreWarmupMode = "sync" + // RestoreWarmupModeASync means initialize TiKV volumes after restore complete + RestoreWarmupModeASync RestoreWarmupMode = "async" +) + // RestoreStatus represents the current status of a tidb cluster restore. type RestoreStatus struct { // TimeStarted is the time at which the restore was started. diff --git a/pkg/backup/restore/restore_manager.go b/pkg/backup/restore/restore_manager.go index 6ec5be82426..7ca7b28d0b7 100644 --- a/pkg/backup/restore/restore_manager.go +++ b/pkg/backup/restore/restore_manager.go @@ -64,6 +64,8 @@ const warmUpVolumeTemplate = `deviceName=$(lsblk -no NAME,MOUNTPOINT -r | awk -v echo "start warm up device $deviceName with mounted path %s" fio --rw=read --bs=256K --iodepth=128 --ioengine=libaio --name=initialize-%s --numjobs=32 --offset=0%% --offset_increment=3%% --size=3%% --thread=1 --filename=/dev/$deviceName` +const defaultWarmUpImage = "wangle1321/fio:juncen-2023062902" + type restoreManager struct { deps *controller.Dependencies statusUpdater controller.RestoreConditionUpdaterInterface @@ -157,17 +159,19 @@ func (rm *restoreManager) syncRestoreJob(restore *v1alpha1.Restore) error { return controller.RequeueErrorf("restore %s/%s: waiting for all PD members are ready in tidbcluster %s/%s", ns, name, tc.Namespace, tc.Name) } - if v1alpha1.IsRestoreVolumeComplete(restore) && !v1alpha1.IsRestoreWarmUpStarted(restore) { - return rm.warmUpTiKVVolumesAsync(restore, tc) - } - if v1alpha1.IsRestoreVolumeComplete(restore) && !v1alpha1.IsRestoreTiKVComplete(restore) { - /*if !v1alpha1.IsRestoreWarmUpStarted(restore) { - return rm.warmUpTiKVVolumesSync(restore, tc) + if isWarmUpSync(restore) { + if !v1alpha1.IsRestoreWarmUpStarted(restore) { + return rm.warmUpTiKVVolumesSync(restore, tc) + } + if !v1alpha1.IsRestoreWarmUpComplete(restore) { + return rm.waitWarmUpJobsFinished(restore) + } + } else if isWarmUpAsync(restore) { + if !v1alpha1.IsRestoreWarmUpStarted(restore) { + return rm.warmUpTiKVVolumesAsync(restore, tc) + } } - if !v1alpha1.IsRestoreWarmUpComplete(restore) { - return rm.waitWarmUpJobsFinished(restore) - }*/ if !tc.AllTiKVsAreAvailable() { return controller.RequeueErrorf("restore %s/%s: waiting for all TiKVs are available in tidbcluster %s/%s", ns, name, tc.Namespace, tc.Name) @@ -186,9 +190,13 @@ func (rm *restoreManager) syncRestoreJob(restore *v1alpha1.Restore) error { if restore.Spec.FederalVolumeRestorePhase == v1alpha1.FederalVolumeRestoreFinish { if !v1alpha1.IsRestoreComplete(restore) { return controller.RequeueErrorf("restore %s/%s: waiting for restore status complete in tidbcluster %s/%s", ns, name, tc.Namespace, tc.Name) - } else { - return nil } + if isWarmUpAsync(restore) { + if !v1alpha1.IsRestoreWarmUpComplete(restore) { + return rm.waitWarmUpJobsFinished(restore) + } + } + return nil } } @@ -463,20 +471,15 @@ func (rm *restoreManager) volumeSnapshotRestore(r *v1alpha1.Restore, tc *v1alpha if _, ok := tc.Annotations[label.AnnTiKVVolumesReadyKey]; ok { return "", nil } - /*if v1alpha1.IsRestoreWarmUpComplete(r) { - restoreMark := fmt.Sprintf("%s/%s", r.Namespace, r.Name) - if len(tc.GetAnnotations()) == 0 { - tc.Annotations = make(map[string]string) + + if isWarmUpSync(r) { + if v1alpha1.IsRestoreWarmUpComplete(r) { + return rm.startTiKV(r, tc) } - tc.Annotations[label.AnnTiKVVolumesReadyKey] = restoreMark - if _, err := rm.deps.TiDBClusterControl.Update(tc); err != nil { - return "AddTCAnnWaitTiKVFailed", err + if v1alpha1.IsRestoreWarmUpStarted(r) { + return "", nil } - return "", nil } - if v1alpha1.IsRestoreWarmUpStarted(r) { - return "", nil - }*/ s, reason, err := snapshotter.NewSnapshotterForRestore(r.Spec.Mode, rm.deps) if err != nil { @@ -492,21 +495,28 @@ func (rm *restoreManager) volumeSnapshotRestore(r *v1alpha1.Restore, tc *v1alpha if reason, err := s.PrepareRestoreMetadata(r, csb); err != nil { return reason, err } - - restoreMark := fmt.Sprintf("%s/%s", r.Namespace, r.Name) - if len(tc.GetAnnotations()) == 0 { - tc.Annotations = make(map[string]string) + klog.Infof("Restore %s/%s prepare restore metadata finished", r.Namespace, r.Name) + if !isWarmUpSync(r) { + return rm.startTiKV(r, tc) } - tc.Annotations[label.AnnTiKVVolumesReadyKey] = restoreMark - if _, err := rm.deps.TiDBClusterControl.Update(tc); err != nil { - return "AddTCAnnWaitTiKVFailed", err - } - return "", nil } return "", nil } +func (rm *restoreManager) startTiKV(r *v1alpha1.Restore, tc *v1alpha1.TidbCluster) (reason string, err error) { + restoreMark := fmt.Sprintf("%s/%s", r.Namespace, r.Name) + if len(tc.GetAnnotations()) == 0 { + tc.Annotations = make(map[string]string) + } + tc.Annotations[label.AnnTiKVVolumesReadyKey] = restoreMark + if _, err := rm.deps.TiDBClusterControl.Update(tc); err != nil { + return "AddTCAnnWaitTiKVFailed", err + } + klog.Infof("Restore %s/%s start TiKV", r.Namespace, r.Name) + return "", nil +} + func (rm *restoreManager) makeImportJob(restore *v1alpha1.Restore) (*batchv1.Job, string, error) { ns := restore.GetNamespace() name := restore.GetName() @@ -860,12 +870,17 @@ type pvcInfo struct { } func (rm *restoreManager) warmUpTiKVVolumesSync(r *v1alpha1.Restore, tc *v1alpha1.TidbCluster) error { - warmUpImage := "wangle1321/fio:alpine-20230626" + klog.Infof("Restore %s/%s start to warm up TiKV synchronously", r.Namespace, r.Name) + warmUpImage := defaultWarmUpImage + if r.Spec.WarmupImage != "" { + warmUpImage = r.Spec.WarmupImage + } + ns := tc.Namespace sel, err := label.New().Instance(tc.Name).TiKV().Selector() if err != nil { return err } - pvcs, err := rm.deps.PVCLister.List(sel) + pvcs, err := rm.deps.PVCLister.PersistentVolumeClaims(ns).List(sel) if err != nil { return err } @@ -890,10 +905,14 @@ func (rm *restoreManager) warmUpTiKVVolumesSync(r *v1alpha1.Restore, tc *v1alpha volumeName: volumeName, number: number, }) + klog.Infof("Restore %s/%s warmup get pvc %s/%s", r.Namespace, r.Name, pvc.Namespace, pvc.Name) } - ns := tc.Namespace + volumesCount := len(tc.Spec.TiKV.StorageVolumes) + 1 for number, podPVCs := range pvcInfoMap { + if len(podPVCs) != volumesCount { + return fmt.Errorf("expected pvc count %d, got pvc count %d, not equal", volumesCount, len(podPVCs)) + } warmUpJobName := fmt.Sprintf("%s-%d-warm-up", stsName, number) _, err := rm.deps.JobLister.Jobs(ns).Get(warmUpJobName) if err == nil { @@ -903,7 +922,7 @@ func (rm *restoreManager) warmUpTiKVVolumesSync(r *v1alpha1.Restore, tc *v1alpha return fmt.Errorf("get warm up job %s/%s error: %s", ns, warmUpJobName, err.Error()) } - warmUpJob, err := rm.makeWarmUpJob2(r, tc, podPVCs, warmUpJobName, warmUpImage) + warmUpJob, err := rm.makeSyncWarmUpJob(r, tc, podPVCs, warmUpJobName, warmUpImage) if err != nil { return err } @@ -919,14 +938,11 @@ func (rm *restoreManager) warmUpTiKVVolumesSync(r *v1alpha1.Restore, tc *v1alpha } func (rm *restoreManager) warmUpTiKVVolumesAsync(r *v1alpha1.Restore, tc *v1alpha1.TidbCluster) error { - warmUpImage := "wangle1321/fio:alpine-20230626" - // TODO: add codes below after test - /*if !r.Spec.WarmUp { - return nil + klog.Infof("Restore %s/%s start to warm up TiKV asynchronously", r.Namespace, r.Name) + warmUpImage := defaultWarmUpImage + if r.Spec.WarmupImage != "" { + warmUpImage = r.Spec.WarmupImage } - if r.Spec.WarmUpImage != "" { - warmUpImage = r.Spec.WarmUpImage - }*/ sel, err := label.New().Instance(tc.Name).TiKV().Selector() if err != nil { @@ -960,7 +976,7 @@ func (rm *restoreManager) warmUpTiKVVolumesAsync(r *v1alpha1.Restore, tc *v1alph return fmt.Errorf("get warm up job %s/%s of tikv pod %s/%s error: %s", ns, warmUpJobName, ns, podName, err.Error()) } - warmUpJob, err := rm.makeWarmUpJob(r, pod, tikvMountPaths, warmUpJobName, warmUpImage) + warmUpJob, err := rm.makeAsyncWarmUpJob(r, pod, tikvMountPaths, warmUpJobName, warmUpImage) if err != nil { return err } @@ -976,11 +992,9 @@ func (rm *restoreManager) warmUpTiKVVolumesAsync(r *v1alpha1.Restore, tc *v1alph }, nil) } -func (rm *restoreManager) makeWarmUpJob2(r *v1alpha1.Restore, tc *v1alpha1.TidbCluster, pvcs []*pvcInfo, warmUpJobName, warmUpImage string) (*batchv1.Job, error) { +func (rm *restoreManager) makeSyncWarmUpJob(r *v1alpha1.Restore, tc *v1alpha1.TidbCluster, pvcs []*pvcInfo, warmUpJobName, warmUpImage string) (*batchv1.Job, error) { podVolumes := make([]corev1.Volume, 0, len(pvcs)) podVolumeMounts := make([]corev1.VolumeMount, 0, len(pvcs)) - warmUpVolumeNames := make([]string, 0, len(pvcs)) - warmUpPaths := make([]string, 0, len(pvcs)) for _, pvc := range pvcs { podVolumes = append(podVolumes, corev1.Volume{ Name: pvc.volumeName, @@ -996,9 +1010,6 @@ func (rm *restoreManager) makeWarmUpJob2(r *v1alpha1.Restore, tc *v1alpha1.TidbC Name: pvc.volumeName, MountPath: mountPath, }) - - warmUpVolumeNames = append(warmUpVolumeNames, pvc.volumeName) - warmUpPaths = append(warmUpPaths, mountPath) } nodeSelector := make(map[string]string, len(tc.Spec.TiKV.NodeSelector)) @@ -1010,12 +1021,18 @@ func (rm *restoreManager) makeWarmUpJob2(r *v1alpha1.Restore, tc *v1alpha1.TidbC tolerations = append(tolerations, *toleration.DeepCopy()) } - fioCommands := make([]string, 0, len(warmUpPaths)) + /*fioCommands := make([]string, 0, len(warmUpPaths)) for i := range warmUpPaths { fioSubCommand := fmt.Sprintf(warmUpVolumeTemplate, warmUpPaths[i], warmUpPaths[i], warmUpVolumeNames[i]) fioCommands = append(fioCommands, strings.ReplaceAll(fioSubCommand, "\n", "; ")) } - fioCommand := strings.Join(fioCommands, "; ") + fioCommand := strings.Join(fioCommands, "; ")*/ + filesArg := fmt.Sprintf("--files=%s", filepath.Join(constants.TiKVDataVolumeMountPath, "db", "*")) + args := []string{ + filesArg, + "--workers=256", + "--direct", + } warmUpPod := &corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ @@ -1029,8 +1046,8 @@ func (rm *restoreManager) makeWarmUpJob2(r *v1alpha1.Restore, tc *v1alpha1.TidbC Name: "warm-up", Image: warmUpImage, ImagePullPolicy: corev1.PullIfNotPresent, - Command: []string{"/bin/sh", "-c"}, - Args: []string{fioCommand}, + Command: []string{"/warmup_steps"}, + Args: args, VolumeMounts: podVolumeMounts, SecurityContext: &corev1.SecurityContext{ Privileged: pointer.BoolPtr(true), @@ -1058,7 +1075,7 @@ func (rm *restoreManager) makeWarmUpJob2(r *v1alpha1.Restore, tc *v1alpha1.TidbC return warmUpJob, nil } -func (rm *restoreManager) makeWarmUpJob(r *v1alpha1.Restore, tikvPod *corev1.Pod, warmUpPaths []string, warmUpJobName, warmUpImage string) (*batchv1.Job, error) { +func (rm *restoreManager) makeAsyncWarmUpJob(r *v1alpha1.Restore, tikvPod *corev1.Pod, warmUpPaths []string, warmUpJobName, warmUpImage string) (*batchv1.Job, error) { ns, podName := tikvPod.Namespace, tikvPod.Name var tikvContainer *corev1.Container for _, container := range tikvPod.Spec.Containers { @@ -1091,20 +1108,26 @@ func (rm *restoreManager) makeWarmUpJob(r *v1alpha1.Restore, tikvPod *corev1.Pod } } - warmUpVolumeNames := make([]string, 0, len(warmUpVolumeMounts)) + /*warmUpVolumeNames := make([]string, 0, len(warmUpVolumeMounts)) for _, volumeMount := range warmUpVolumeMounts { warmUpVolumeNames = append(warmUpVolumeNames, volumeMount.Name) } if len(warmUpPaths) != len(warmUpVolumeNames) { return nil, fmt.Errorf("lengths of mounted paths %v and volumes %v in tikv pod %s/%s are not equal", warmUpPaths, warmUpVolumeNames, ns, podName) - } + }*/ - fioCommands := make([]string, 0, len(warmUpPaths)) + /*fioCommands := make([]string, 0, len(warmUpPaths)) for i := range warmUpPaths { fioSubCommand := fmt.Sprintf(warmUpVolumeTemplate, warmUpPaths[i], warmUpPaths[i], warmUpVolumeNames[i]) fioCommands = append(fioCommands, strings.ReplaceAll(fioSubCommand, "\n", "; ")) } - fioCommand := strings.Join(fioCommands, "; ") + fioCommand := strings.Join(fioCommands, "; ")*/ + filesArg := fmt.Sprintf("--files=%s", filepath.Join(constants.TiKVDataVolumeMountPath, "db", "*")) + args := []string{ + filesArg, + "--workers=256", + "--direct", + } warmUpPod := &corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ @@ -1116,8 +1139,8 @@ func (rm *restoreManager) makeWarmUpJob(r *v1alpha1.Restore, tikvPod *corev1.Pod Name: "warm-up", Image: warmUpImage, ImagePullPolicy: corev1.PullIfNotPresent, - Command: []string{"/bin/sh", "-c"}, - Args: []string{fioCommand}, + Command: []string{"/warmup_steps"}, + Args: args, VolumeMounts: warmUpVolumeMounts, SecurityContext: &corev1.SecurityContext{ Privileged: pointer.BoolPtr(true), @@ -1221,6 +1244,14 @@ func (rm *restoreManager) ensureRestorePVCExist(restore *v1alpha1.Restore) (stri return "", nil } +func isWarmUpSync(r *v1alpha1.Restore) bool { + return r.Spec.Warmup == v1alpha1.RestoreWarmupModeSync +} + +func isWarmUpAsync(r *v1alpha1.Restore) bool { + return r.Spec.Warmup == v1alpha1.RestoreWarmupModeASync +} + var _ backup.RestoreManager = &restoreManager{} type FakeRestoreManager struct { diff --git a/pkg/controller/restore/restore_controller.go b/pkg/controller/restore/restore_controller.go index 2059050a43f..1e5bb89b8ce 100644 --- a/pkg/controller/restore/restore_controller.go +++ b/pkg/controller/restore/restore_controller.go @@ -159,6 +159,13 @@ func (c *Controller) updateRestore(cur interface{}) { } if v1alpha1.IsRestoreComplete(newRestore) { + if newRestore.Spec.Warmup == v1alpha1.RestoreWarmupModeASync { + if !v1alpha1.IsRestoreWarmUpComplete(newRestore) { + c.enqueueRestore(newRestore) + return + } + } + klog.V(4).Infof("restore %s/%s is Complete, skipping.", ns, name) return } diff --git a/pkg/fedvolumebackup/restore/restore_manager.go b/pkg/fedvolumebackup/restore/restore_manager.go index 231289de686..78cee6a4309 100644 --- a/pkg/fedvolumebackup/restore/restore_manager.go +++ b/pkg/fedvolumebackup/restore/restore_manager.go @@ -420,6 +420,8 @@ func (rm *restoreManager) buildRestoreMember(volumeRestoreName string, memberClu ImagePullSecrets: template.ImagePullSecrets, ServiceAccount: template.ServiceAccount, PriorityClassName: template.PriorityClassName, + Warmup: template.Warmup, + WarmupImage: template.WarmupImage, }, } return restoreMember