Skip to content

Conversation

@tlrx
Copy link
Member

@tlrx tlrx commented Jan 22, 2025

Ensure that a write block cannot be removed on a read-only compatible index in version N-2, while allowing to change a read_only block into a write block if needed as well as closing/reopening such indices.

Requires #120647 to be merged on 8.x.

Relates ES-10320

@tlrx tlrx added >non-issue :Distributed Indexing/Recovery Anything around constructing a new shard, either from a local or a remote source. v9.0.0 labels Jan 22, 2025
@elasticsearchmachine elasticsearchmachine added the Team:Distributed Indexing Meta label for Distributed Indexing team label Jan 22, 2025
@elasticsearchmachine
Copy link
Collaborator

Pinging @elastic/es-distributed-indexing (Team:Distributed Indexing)

@tlrx tlrx requested a review from henningandersen January 22, 2025 17:54
Copy link
Contributor

@henningandersen henningandersen left a comment

Choose a reason for hiding this comment

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

Looks good though I hope we can support removing one of two write blocks too? See comment.

if (blocks.hasIndexBlock(index, block)) {
blocks.removeIndexBlock(index, block);
changed = true;
if (block.contains(ClusterBlockLevel.WRITE)) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is too harsh. In case the index has both the read-only and the write block, it should be allowed to remove either.

In particular, if the user applied read-only on 8.x, upgraded and then want to update some settings, they should be allowed to add the write block and remove the read-only block.

I recognize this is also a flaw in the original code in that it removes the verified setting.

I could be ok to let this go in if we follow-up with the additional detail. But would prefer we do it in one go if it is not too hard.

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is too harsh. In case the index has both the read-only and the write block, it should be allowed to remove either.

I agree, it makes sense.

In particular, if the user applied read-only on 8.x, upgraded and then want to update some settings, they should be allowed to add the write block and remove the read-only block.

I initially thought that updating both settings at once would not work because of the code allowing setting updates when there is a METADATA_WRITE block in place:

if (request.settings().size() == 1 && // we have to allow resetting these settings otherwise users can't unblock an index
IndexMetadata.INDEX_BLOCKS_METADATA_SETTING.exists(request.settings())
|| IndexMetadata.INDEX_READ_ONLY_SETTING.exists(request.settings())
|| IndexMetadata.INDEX_BLOCKS_READ_ONLY_ALLOW_DELETE_SETTING.exists(request.settings())) {
return null;

but it seems that request.settings().size() == 1 does not always apply since the great setting refactoring here.

It looks like this refactoring introduced a change in the parenthesis impacting the conditions to bypass the check. Which will serve us today.

@tlrx
Copy link
Member Author

tlrx commented Jan 27, 2025

Ok, so it took me a couple of days to get this working with the subtleties of blocks updates. Thanks for your patience on this @henningandersen.

I updated this PR (and #120647) to forbid the removal of the ClusterBlockLevel.WRITE on a read-only compatible index if at least one node of the cluster cannot write to it (see verifyReadOnlyIndices).

Since both index.blocks.read_only to index.blocks.write contains this ClusterBlockLevel.WRITE we can allow updating the index blocks setting to move from one type of block to the other. In the tests I included the use case you mentioned: updating from index.blocks.read_only to index.blocks.write.

I also changed the MetadataUpdateSettingsService#maybeUpdateClusterBlock so that the VERIFIED_READ_ONLY_SETTING remains as long as a ClusterBlockLevel.WRITE remains (required for blocks settings updates). It also allows to keep the VERIFIED_READ_ONLY_SETTING value when closing a verified read-only index, because closed indices have the INDEX_CLOSED_BLOCK that also contains the ClusterBlockLevel.WRITE block. When reopening, the INDEX_CLOSED_BLOCK is removed, removing the VERIFIED_READ_ONLY_SETTING if no other write block is in place and it will fail the reopening since the check in verifyReadOnlyIndices does not allow a read-only compatible index to have no ClusterBlockLevel.WRITE block (applying a write block before reopening will work).

I largely updated the integration tests to to have a bit more randomization around blocks and closing/opening during upgrades.

Note that there is still a bit missing for fully supporting closed indices (allowing a verified-before-close index to be upgraded without being marked as read-only first): I'll do this in follow ups.

Copy link
Contributor

@henningandersen henningandersen left a comment

Choose a reason for hiding this comment

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

LGTM.

private static void verifyReadOnlyIndices(@Nullable Set<Index> readOnlyIndices, ClusterBlocks blocks) {
if (readOnlyIndices != null) {
for (Index readOnlyIndex : readOnlyIndices) {
if (blocks.indexBlocked(ClusterBlockLevel.WRITE, readOnlyIndex.getName()) == false) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this use the new hasIndexBlockLevel method to avoid interaction from global blocks?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, I pushed de6a0bd.

closeIndex(restoredIndex);
ensureGreen(restoredIndex);

logger.debug("--> write API block can be removed on a closed index: INDEX_CLOSED_BLOCK already blocks writes");
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 also check that if an index has both read-only and write block then we can remove one of them for an N-2 index?

Copy link
Member Author

Choose a reason for hiding this comment

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

I reworked the testIndexUpgrade test to randomly add one or two of the blocks, and then remove one of them.

See 59e7acd

tlrx added a commit that referenced this pull request Jan 28, 2025
…ly (#120647)

Forbids on 8.x the removal/update of a write block if at least one node of the cluster cannot write the index.

Backport of #120648 for 8.18.

Relates ES-10320
@tlrx tlrx merged commit 0569fc7 into elastic:main Jan 28, 2025
16 checks passed
@tlrx
Copy link
Member Author

tlrx commented Jan 28, 2025

Thanks Henning

@tlrx tlrx deleted the 2025/01/22/forbid-write-block-removal branch January 28, 2025 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

:Distributed Indexing/Recovery Anything around constructing a new shard, either from a local or a remote source. >non-issue Team:Distributed Indexing Meta label for Distributed Indexing team v9.0.0

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants