-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Restore VolumeSnapshot, VolumeSnapshotcontent and dataupload associated with a PVC during a CSI Restore even if it is excluded from the restore due to label(s) selector #8796
Conversation
… associated VolumeSnapshot resource is missing (because it did not match the label selector), PVC Action fails because restore size is required from the VolumeSnapshot resources. To fix we now return the required VolumeSnapshot in additional items (only if not found). We annotate the PVC (if not already annotated) and return both the VolumeSnapshot and the PVC in additional items. This allows Velero to restore the VolumeSnapshot and retry the PVC action. If the VolumeSnapshot is missing and the PVC already has the annotation, the restore action will fail.
@amastbau Thanks for the contribution. However, I'm not very convinced why this should be part of the upstream.
Is this a case that always happens? Could you elaborate why? |
@reasonerjt This is to resolve an inconsistency in backup vs. restore behavior when using label selectors. On backup, when using a label selector to back up only certain workloads in a namespace, the created VolumeSnapshot will always be included in the backup because it's returned by the PVC BIA. On restore, however, if using a label selector to only restore certain workloads in a namespace, the VolumeSnapshot won't match the label, so it's excluded. Ordinarily, a straightforward additionalItem return would be all that's needed to pull the VS into the restore -- the problem is that it needs to have been restored before the PVC, so simply adding it to the PVC RIA doesn't help. This PR gets around that by adding the VS and the current PVC again. That being said, I'm not 100% clear why this is needed for the CSI only case but we don't have a similar problem with DataUpload inclusion in the datamover case. @amastbau Do datamover restores with label selector work fine for you without a similar change? |
@reasonerjt @amastbau We discussed this during the community meeting. The current approach of returning the current PVC as its own additional item (after the needed VolumeSnapshot) doesn't really work. What we actually need is to ensure that the VolumeSnapshot is restored before this pvc_action is run. The answer there is another RIA (maybe pvc_pre_action.go) that is registered to run before this one. That RIA will only return the VS as an additional item (for CSI only case), resulting in the restore workflow restoring the VS (will be a no-op if it's already restored, but is necessary if restore uses a label selector). Then when the next matching RIA is run (the existing csi pvc_action), the VS will already exist, so this RIA will run as-written. We need the same thing in this new to include the DataUpload for the PVC if we're using datamover for the volume. |
Converting PR to draft until the new fix is submitted. |
so, |
RegisterRestoreItemAction( | ||
constant.PluginCSIPVCVSDURestoreRIA, | ||
newPvcVSDVRestoreItemAction(f), | ||
). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this a few lines down to just before the call to newPvcRestoreItemAction(f)
at line 161 since they're related plugin actions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, I wrongly assumed that registering that plugin using the Fluent(?) Interface would be enough to set the order.
@@ -21,5 +21,6 @@ const ( | |||
ControllerRestoreFinalizer = "restore-finalizer" | |||
|
|||
PluginCSIPVCRestoreRIA = "velero.io/csi-pvc-restorer" | |||
PluginCSIPVCVSDURestoreRIA = "velero.io/csi-pvc-vs-dv-restorer" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The alignment is off on the =
-- also, we need this new plugin to be run before "velero.io/csi-pvc-restorer" so when the csi-pvc-restorer is run the VS, DU, etc. are already restored. Maybe change PluginCSIPVCRestoreRIA to "velero.io/csi-pvc-restorer2" and then set PluginCSIPVCVSDURestoreRIA to "velero.io/csi-pvc-restorer1"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git it ^ :) alphabetic order
// NewPvcVSDVRestoreItemAction returns a new instance of PVCVSDVRestoreItemAction. | ||
func NewPvcVSDVRestoreItemAction(f client.Factory) plugincommon.HandlerInitializer { | ||
return func(logger logrus.FieldLogger) (any, error) { | ||
crClient, err := f.KubebuilderClient() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like the plugin doesn't actually need crClient, so this can probably be avoided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is from when was trying the satisfy V2 interface with do nothing functions at 1st, i thought this was the requirement even if not needed.its not a requirement if we are are just pushing backup the additional Items, correct?
AdditionalItems: []velero.ResourceIdentifier{}, | ||
}, nil | ||
// Convert the updated VolumeSnapshot to an unstructured object. | ||
vsMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&vs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this new code is repeating the code from line 103-107. We already have vsMap. Is this a mere/rebase error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naa. was copying and pasting coede chunks.thakns
@sseago @shubham-pampattiwar |
@sseago |
} | ||
|
||
// Check for DataVolume annotation. | ||
if dvName, ok := pvc.Annotations[velerov1api.DataUploadNameAnnotation]; ok && dvName != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't need to do this for data mover case, as per #8796 (comment).
Sorry for jumping in late. Share my thoughts of this PR and the discussion here:
cc @reasonerjt |
I don't think the pre/post distinction in 1) is really relevant to the problem being solved here. All RIAs are pre -- they modify the resource before restore. If multiple RIAs match, then velero explicitly runs them in sorted order by the registered name. The issue here isn't pre/post -- but we have one action that must run before another. On the OpenShift side, we also have scenarios where we have two actions that must be run in a certain order, since the results of action1 are used in action2. That's exactly what we need here. So the change that does not require any infra-level changes is in this PR (since Velero sorts the actions by registered name, this is guaranteed to run in the desired order). It might be better long-term to avoid the sort-order dependence and provide an optional priority field to the But again, to be clear, we don't have explicit pre/post actions. We have two different RestoreItemActions that need to run in a specific order since the actions in RIA2 depend on RIA1 already having been run. Current velero code guarantees that actions are sorted by registered name -- but if we want, we can add a way to register a plugin with priority to do this in a slightly clearer way. |
Here are some more points, let's discuss in the community meeting:
|
@Lyndon-Li Yes, I would agree that this would be desirable. One possibility would be to label these items in the backup with something like "velero.io/must-restore=true" and then add (internally) add that to the "or" label selector when filtering by label on restore. |
@Lyndon-Li "Ordered BIA/RIA is still an infrastructure level requirement, relying on the alphabet order of the actions is not good enough, unless we are fixing a very critical problem temporarily." |
We used to introduce an annotation to bypass the filtering in backup process: velero/pkg/backup/item_backupper.go Line 415 in fcfb2fd
Maybe it's a low-hanging fruit for us to provide a "must-have" semantic to restore if we keep this annotation? |
So to summarize, I think there are two different general problems at work here, and one specific problem that is exposing this:
And specifically: When a restore is done with a label selector, VolumeSnapshots created by Velero will not have the label, so they will be omitted from the restore. Solution 1) above would solve this, or solution 2) above would enable this by allowing us to register a high priority RIA which returns the VS as an additional item. The challenge in 1) is knowing which additional items to return. For example, say I back up an entire namespace which includes Pod1/PVC1/VS1 where the pod is labeled with Label1, and Pod2/PVC2/VS2 where the pod is labeled with Label2. If I back up without label selectors, then restore with a selector that matches only Label1, currently I don't get VS1 -- and depending on what other RIAs run, I may not get PVC1 either. However, if we simply restore all additional item returns from backup, that will give us both PVC1/VS1 and PVC/VS2. How do we ensure that we only get PVC1/VS1 when the backup didn't specify label1? There may not be an easy way to do this generically, which may require us to add these explicitly as RIA additional items like we do for BIA. For Pod this is easy enough and won't require a new action, just add the PVCs to the existing pod action. For CSI PVC action, though, the VS must exist when the current CSI PVC action runs, so we'd need to use option 2) and register a plugin with high priority that returns the VS as an additional item, guaranteeing that this runs before the regular plugin. |
As for ordered BIA/RIA, I wish to suggest we clarify if there's really a concrete scenario -- even there is, is it possible to refactor the code to merge some plugins so that the code is ordered in one We allow different plugins to handle the same resource and I don't think we can completely avoid conflicts across plugins |
The problem is that it's not necessarily must-have if the restore is filtering on labels. For example, say I back up an entire namespace which includes Pod1/PVC1/VS1 where the pod is labeled with Label1, and Pod2/PVC2/VS2 where the pod is labeled with Label2. If I back up without label selectors, then restore with a selector that matches only Label1, currently I don't get VS1 -- and depending on what other RIAs run, I may not get PVC1 either. However, if all of these additional item returns added the must-restore annotation, that will give us both PVC1/VS1 and PVC/VS2. But we only want PVC1/VS1 -- since we're not restoring Pod2, we don't want that pod's PVC or VS. We may have to actually add these additional item returns explicitly to RIAs. |
@sseago Would it solve the case if the VS object was to inherit the labels from the PVC object ? We control the VS creation, so that seems doable. |
The problem is we can't always do it in one execute. The concrete example is the one we're trying to solve here. We need to return the VolumeSnapshot as an addiitonal item to restore, but the current CSI PVC action requires the VS to already exist. If we registered ria1 with an explicit priority (see suggestion above) to always run before ria2, then ria1 could return the VS to restore as an additional item, and when ria2 is called later, the VS will have been restored, so ria2's Execute func can access it. There is no conflict as long as we can predict the order that velero runs the actions in. Currently the code guarantees order via string sort (which as pointed out above, isn't really a great API for it), but if we added an explicit priority field to the Register funcs, then we would have a better API for ensuring order, allowing any scenario where we need multiple BIAs or RIAs to run in a particular order to work fine with no conflicts. Since the modified item metadata from the first action is passed on to the second action, we don't really need to worry about conflicts as long as plugin authors set priority properly in cases where the order matters -- in most cases it won't matter, such as the case today with the CSI PVC action and the non-CSI PVC action. They do different things, they don't conflict regardless of the order they run in. |
@shubham-pampattiwar |
@sseago Proposal As a result, we have to skip the resources at the first place and later we want to pull them back. And if visit back is inevitable, we would rather do it during restore collection, because it is much easier.
The only trade-off for this solution is that we don't have a generic way to make an abstract of telling the "pillar" object from any given object, so right now, we assume that there are two concrete ones vs and dataUpload. |
@Lyndon-Li I think that's mostly correct -- note that PVC itself is another resource with this issue. i.e. consider the use case where the pod has the label. so when processing VS, we need to go from VS to PVC to Pod to find the label, then when processing PVC, we need to go from PVC to Pod to find the label. |
@Lyndon-Li I'm closing this PR now, since we'll handle the short-term fix downstream, and the long-term fix is tracked in the new issue created today. |
Thank you for contributing to Velero!
Please add a summary of your change
Issue
During a CSI restore, if the VolumeSnapshot is missing for any reason, the PVC remains in a pending state with the error:
error getting snapshot your-snapshot-name from api server: volumesnapshots.snapshot.storage.k8s.io "your-snapshot-name" not found.
In Addition,
The CSI PVC Restore Action fails because restore size is required from the VolumeSnapshot resource to patch the PVC's request size if too small.
To handle cases , in which the volumesnapshot was initially excluded due to label(s) selector,
PVC Restore Action will now return the required VolumeSnapshot in additional items if not found. We annotate the PVC (if not already annotated) and return both the VolumeSnapshot and the PVC in additional items. This allows Velero to restore the VolumeSnapshot and retry the PVC action. If the VolumeSnapshot is missing and the PVC already has the annotation, the restore action will fail.
Note: this only handles cases where the VS is excluded sue to label(s) selector, other cases (like excluding by resource type) are not handled.
Does your change fix a particular issue?
Fixes #(issue)
Please indicate you've done the following:
make new-changelog
) or comment/kind changelog-not-required
on this PR.site/content/docs/main
.