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

PV remapClaimRefNS was being skipped when there was no snapshot #3708

Merged
merged 1 commit into from
Nov 10, 2021

Conversation

sseago
Copy link
Collaborator

@sseago sseago commented Apr 20, 2021

Signed-off-by: Scott Seago sseago@redhat.com

Thank you for contributing to Velero!

Please add a summary of your change

Previously (#3007 ) a fix was submitted which handles PV ClaimRef remapping and PV renaming when there is a snapshot, but it did not handle the default case of no snapshot, no restic, but still restoring the PV. This extends the same behavior to the default case (no snapshot, no restic, no delete reclaim policy): the ClaimRef gets its namespace remapped if necessary, and the PV gets renamed if necessary.

Tests included to confirm the fix.

Does your change fix a particular issue?

Fixes #3707

Please indicate you've done the following:

  • [ x] Accepted the DCO. Commits without the DCO will delay acceptance.
  • [ x] Created a changelog file or added /kind changelog-not-required.
  • Updated the corresponding documentation in site/content/docs/main.

Copy link
Contributor

@nrb nrb left a comment

Choose a reason for hiding this comment

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

I think it looks ok, but it's mostly a copy paste from what I can tell.

Is it possible to move the remap logic to a function that is shared?

@@ -1035,6 +1035,37 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
default:
ctx.log.Infof("Restoring persistent volume as-is because it doesn't have a snapshot and its reclaim policy is not Delete.")

shouldRenamePV, err := shouldRenamePV(ctx, obj, resourceClient)
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, since this is the same logic as the first case in the switch, I'm wondering if we should consolidate this into a function, or maybe do some of the logic before the switch.

The downside of moving it before is that it may be more work even in cases where there is no mapping to take place.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@nrb So I looked into this, but it looks like it would be difficult to drop all of the logic here into one function. Basically the logic added to the default case does 3 things:

  1. Check whether we should rename the PV
  2. Rename the PV if 1) is true
  3. Remap the namespace if we need to

So 1+2 and 3 are somewhat independent of each other. Currently 2) and 3) are done in a different order in the two code paths, but there's really no need for that. However, the part that makes putting all of this code into a func is the fact that in the hasSnapshot case, there is some logic required between 1) and 2) which is not there in the default case. One thing I could consolidate is the block of code inside the if shouldRenamePV block -- I could put that into a a new func renamePV(...) which would be called inside the if block in both cases, if that would be enough of an improvement in terms of avoiding duplication.

Velero 1.7.0 automation moved this from In progress to Review in progress May 17, 2021
Velero Sprint 05-17-2021 automation moved this from In progress to Review in progress May 17, 2021
@zubron zubron requested review from zubron and removed request for carlisia June 3, 2021 14:11
@dsu-igeek dsu-igeek removed this from Review in progress in Velero Sprint 05-17-2021 Jul 12, 2021
@dsu-igeek dsu-igeek added this to In progress in Velero v1.8 Sprint 7 (12-Jan-2022) via automation Jul 12, 2021
@zubron zubron requested a review from dsu-igeek July 12, 2021 21:16
errs.Add(namespace, err)
return warnings, errs
}
if shouldRenamePV {
Copy link
Contributor

Choose a reason for hiding this comment

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

While reviewing this change with others on the team, @dsu-igeek pointed out that although we are renaming the PV, remapping the ClaimRef namespace, and resetting the volume binding info, this doesn't clear the PV source, which means that the new renamed PV will still be pointing to the original backing storage currently in use by the original PV.

I experimented with this locally and saw that there doesn't seem to be anything to prevent multiple PVs from using the same backing storage (if they are on the same node). This means that data can be written by a pod in the original namespace and this can be read by a pod in the remapped namespace (as well as being able to perform other destructive operations).

I don't think it's possible to "clear" the source, as it is necessary to reference a volume type. Should we be provisioning a new PV in this case to go with the remapped namespace and PVC?

Copy link
Contributor

Choose a reason for hiding this comment

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

Without this do we get an error or do we get the PVC mapped to the original PV? I like the "principle of least surprise". To me, when I do a restore, I expect that I will get my original data back. In the case where we are restoring from a snapshot we get that. If we reconnect to the existing volume then we get that. Those are our existing cases. If we reconnect to the same volume but it's also in use somewhere else, that seems like a recipe for trouble when it works and a weird error when it doesn't (Bridget told me that she initially tested with the pods being on the same worker node and in that case the restore pod/PVC/PV was connected to the same directory as described above but if the pods wound up on different nodes, the restored pod would get an error that it couldn't attach to the storage). If we make a new empty volume that's probably not what is expected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@dsu-igeek So without this, the following was the observed behavior (from the issue filed):

What steps did you take and what happened:
Restored a PV (without a snapshot) and the PVC it's bound to into a different namespace. The PVC was restored but "pending", with an error that the PV was bound to another claim. The reason for this is that the ClaimRef was not updated to the new namespace. The ClaimRef remapping is only currently done in restore/restore.go when there's a snapshot. It's also needed in the non-snapshot case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So basically the PVC post-restore was not usable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was bound "to another claim" because its claimRef was different than the PVC that was restored with it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@zubron Regarding the "not clearing the PV source", how is that different from a normal restore (without a namespace change) where the PV and PVC are restored. Since we're not using restic, a new PV isn't provisioned. Doesn't the "no namespace change" use case also result in the same scenario around two PVs using the same backing storage?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The particular use case where we hit this actually relies on the PV not changing its backing store data. We have a "Move PV/PVC" use case where in a migration, we do a backup of PV and PVC without restic or snapshots. Then after shutting down the application using the volume on the source cluster, we restore the backup to the destination cluster, and the transferred PV/PVC definitions allow the destination cluster to access the original (NFS) source volume. This works just fine in the "no namespace change" use case. The bug fixed by this PR was preventing it from working in the namespace change on restore scenario.

Copy link
Contributor

Choose a reason for hiding this comment

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

@sseago If we're restoring into the same namespace then the assumption would be that the PVC in that namespace had been removed or was still there (and we wouldn't overwrite it) and we wouldn't wind up sharing. I think it's still kind of dangerous and we should figure out these scenarios properly. Let's discuss in community meeting how to handle your case.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@dsu-igeek Sounds like a plan. So here are the two scenarios that we're dealing with (one works without this fix, one does not):

  1. Backup namespace with PVCs and PVs in one cluster, no restic or snapshot copy; shut down applications using volumes; restore to different cluster. PV/PVC pair in new cluster points to same underlying storage as old cluster, effectively the PVC was "moved", so no data copy was needed. new cluster points to same (external) NFS share as the old cluster was using.
  2. Same as 1) but change namespace on restore. With this fix, everything works just as in 1). Without this fix, the PVC remains "pending" forever. I suspect that the danger that's being discussed with this fix is still there in the same-namespace case, so I'm not certain that any new danger is introduced with this fix, but we can discuss it on the call next week.

@sseago
Copy link
Collaborator Author

sseago commented Sep 10, 2021

@dsu-igeek @zubron I've updated the PR to remove the PV rename, so we're just fixing the pv/pvc mapping to handle namespace remapping. Unit tests updated accordingly, and we're also looking for the expected restore warning in the case where the PV already exists (since velero will discard it).

Signed-off-by: Scott Seago <sseago@redhat.com>
@sseago sseago changed the title PV rename/remapClaimRefNS were being skipped when there was no snapshot PV remapClaimRefNS was being skipped when there was no snapshot Sep 10, 2021
@dsu-igeek dsu-igeek removed this from Review in progress in Velero 1.7.0 Sep 22, 2021
@dsu-igeek dsu-igeek modified the milestones: v1.7.0, v1.8.0 Sep 22, 2021
@dsu-igeek dsu-igeek removed this from In progress in Velero v1.8 Sprint 7 (12-Jan-2022) Oct 20, 2021
@dsu-igeek dsu-igeek added this to To Do in v1.8.0 Oct 20, 2021
Copy link
Contributor

@dsu-igeek dsu-igeek left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@zubron zubron left a comment

Choose a reason for hiding this comment

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

Thanks, @sseago!

v1.8.0 automation moved this from To Do to In Progress Nov 10, 2021
@zubron zubron merged commit 9834890 into vmware-tanzu:main Nov 10, 2021
@yanji09 yanji09 moved this from In Progress to Done in v1.8.0 Jan 17, 2022
danfengliu pushed a commit to danfengliu/velero that referenced this pull request Jan 25, 2022
gyaozhou pushed a commit to gyaozhou/velero-read that referenced this pull request May 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

Successfully merging this pull request may close these issues.

When remapping namespaces, PVs without snapshots don't get their ClaimRefs remapped.
4 participants