Add workaround for missing shard gen blob#112337
Add workaround for missing shard gen blob#112337elasticsearchmachine merged 20 commits intoelastic:mainfrom
Conversation
It is currently very painful to recover from a bug which incorrectly removes a shard-level `index-UUID` blob from the repository. This commit introduces a fallback mechanism that attempts to reconstruct the missing data from other blobs in the repository. It's still a bug to need this mechanism for sure, but in many cases this mechanism will allow the repository to keep working without any need for manual surgery on its contents.
|
Pinging @elastic/es-distributed (Team:Distributed) |
|
Hi @DaveCTurner, I've created a changelog YAML for you. |
henningandersen
left a comment
There was a problem hiding this comment.
Looks good. I wonder if we can add more testing though - also to demonstrate that it does not lead to further corruption.
| for (final var shardSnapshotBlobName : shardSnapshotBlobs.keySet()) { | ||
| if (shardSnapshotBlobName.startsWith("snap-") | ||
| && shardSnapshotBlobName.endsWith(".dat") | ||
| && shardSnapshotBlobName.length() == "snap-".length() + 22 + ".dat".length()) { |
There was a problem hiding this comment.
Can we make 22 a named constant?
| return new ElasticsearchException("create-snapshot failed as expected"); | ||
| })); | ||
| }); | ||
| } else { |
There was a problem hiding this comment.
I wonder if validating following is relevant:
- That we can restore without the missing file?
- That taking a new snapshot that includes changes to the shard repairs the situation (I think it would?) for new snapshots, i.e., we no longer need the fallback reading?
There was a problem hiding this comment.
Yeah actually we already have a test for the behaviour when this file is corrupt, see testSnapshotWithCorruptedShardIndexFile. So in c13297f I reverted back to having this test delete the file again, and made it try more interesting combinations of snapshot creations and restores to make sure it still works as we expect.
There was a problem hiding this comment.
IIUC, both cloning and deleting snapshot should also write a new shard generation file and fix the issue. Should we randomly test for them as well?
There was a problem hiding this comment.
Curious now why this works for restore - but I suppose we somehow avoid reading that file? (ahh, it is in the code comment, thanks for answering my question before I posted it)
There was a problem hiding this comment.
both cloning and deleting snapshot should also write a new shard generation file and fix the issue
++ see b6434df
|
This change is much simpler than I expected. Looking great! I have two high level questions:
|
I considered this and decided I prefer the implicit behaviour proposed here. Although rare, this kind of bug leads to a potentially pageable situation, but there is no sense in paging someone just to execute an API.
In practice this kind of bug affects no existing snapshots anyway, it only blocks creation of new snapshots of the affected shard. Existing snapshots should all be ok. But if there were a missing |
| if (shardSnapshotBlobName.startsWith("snap-") | ||
| && shardSnapshotBlobName.endsWith(".dat") | ||
| && shardSnapshotBlobName.length() == "snap-".length() + UUIDs.RANDOM_BASED_UUID_STRING_LENGTH + ".dat" | ||
| .length()) { | ||
| final var shardSnapshot = INDEX_SHARD_SNAPSHOT_FORMAT.read( | ||
| metadata.name(), | ||
| shardContainer, | ||
| shardSnapshotBlobName.substring("snap-".length(), "snap-".length() + UUIDs.RANDOM_BASED_UUID_STRING_LENGTH), | ||
| namedXContentRegistry |
There was a problem hiding this comment.
Nit: we can replace "snap-" with BlobStoreRepository.SNAPSHOT_PREFIX and maybe extract "snap-".length() as a variable.
There was a problem hiding this comment.
We're really bad at this today. I opened #112653 to clean this area up more thoroughly.
| final var message = Strings.format( | ||
| "shard generation [%s] in [%s][%s] not found - falling back to reading all shard snapshots", | ||
| generation, | ||
| metadata.name(), | ||
| shardContainer.path() | ||
| ); |
There was a problem hiding this comment.
I think it would be helpful if we can log the index name in the cluster so that it is easier to understand which shard is affected. But unfortunately we don't have the context here. Passing it from all the callsites seems to lead cascading changes that are not really worthwhile just for a logging in edge cases.
There was a problem hiding this comment.
++ makes sense and not too hard I think, see aef8e7c.
| "--> restoring the snapshot, the repository should not have lost any shard data despite deleting index-N, " | ||
| + "because it uses snap-*.data files and not the index-N to determine what files to restore" |
There was a problem hiding this comment.
Nit: can we not use index-N for shard generation files? I find it better to reseve it for the root blob. So maybe index-UUID? Old snapshots do use numeric but that is not the case in this test.
| createSnapshotResponse.getSnapshotInfo().totalShards(), | ||
| createSnapshotResponse.getSnapshotInfo().successfulShards() | ||
| ); | ||
| mockLog.assertAllExpectationsMatched(); |
There was a problem hiding this comment.
Should we also check that a new shard generation file is written?
| return new ElasticsearchException("create-snapshot failed as expected"); | ||
| })); | ||
| }); | ||
| } else { |
There was a problem hiding this comment.
IIUC, both cloning and deleting snapshot should also write a new shard generation file and fix the issue. Should we randomly test for them as well?
...src/internalClusterTest/java/org/elasticsearch/snapshots/CorruptedBlobStoreRepositoryIT.java
Show resolved
Hide resolved
Since elastic#112337, missing shard gen files are automatically reconstructed based on the existing shard snapshot files. If the list of shard snapshot files are completed, it means the repository is effectively not corrupted. This PR updates the test to account for this situation. Resolves: elastic#112769
Since elastic#112337, missing shard gen files are automatically reconstructed based on the existing shard snapshot files. If the list of shard snapshot files is complete, it means the repository is effectively not corrupted. This PR updates the test to account for this situation. Resolves: elastic#112769 (cherry picked from commit e1f7814) # Conflicts: # muted-tests.yml
Since #112337, missing shard gen files are automatically reconstructed based on the existing shard snapshot files. If the list of shard snapshot files is complete, it means the repository is effectively not corrupted. This PR updates the test to account for this situation. Resolves: #112769 (cherry picked from commit e1f7814) # Conflicts: # muted-tests.yml
… file (elastic#112979) It is expected that the old master may attempt to read a shardGen file that is deleted by the new master. This PR checks the latest repo data before applying the workaround (or throwing AssertionError) for missing shardGen files. Relates: elastic#112337 Resolves: elastic#112811 (cherry picked from commit 99b5ed8) # Conflicts: # muted-tests.yml
… file (#112979) (#113155) It is expected that the old master may attempt to read a shardGen file that is deleted by the new master. This PR checks the latest repo data before applying the workaround (or throwing AssertionError) for missing shardGen files. Relates: #112337 Resolves: #112811 (cherry picked from commit 99b5ed8) # Conflicts: # muted-tests.yml
It is currently very painful to recover from a bug which incorrectly
removes a shard-level
index-UUIDblob from the repository. This commitintroduces a fallback mechanism that attempts to reconstruct the missing
data from other blobs in the repository. It's still a bug to need this
mechanism for sure, but in many cases this mechanism will allow the
repository to keep working without any need for manual surgery on its
contents.