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

Only run retention lease actions on active primary #40386

Conversation

jasontedor
Copy link
Member

@jasontedor jasontedor commented Mar 22, 2019

In some cases, a request to perform a retention lease action can arrive on a primary shard before it is active. In this case, the primary shard would not yet be in primary mode, tripping an assertion in the replication tracker. Instead, we should not attempt to perform such actions on an initializing shard. This commit addresses this by not returning the primary shard in the single shard iterator if the primary shard is not yet active.

Closes #40089
Closes #40373

In some cases, a request to perform a retention lease action can arrive
on a primary shard before it is active. In this case, the primary shard
would not yet be in primary mode, tripping an assertion in the
replication tracker. Instead, we should not attempt to perform such
actions on an initializing shard. This commit addresses this by not
returning the primary shard in the single shard iterator if the primary
shard is not yet active.
@jasontedor jasontedor added >test Issues or PRs that are addressing/adding tests v7.0.0 :Distributed/CCR Issues around the Cross Cluster State Replication features v8.0.0 v7.2.0 v6.7.1 labels Mar 22, 2019
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-distributed

@jasontedor
Copy link
Member Author

Another option that I considered is rejecting this when acquiring the permit on a shard that is not yet active, but this approach seems preferable to me (note that we manually handle inactive shards elsewhere, such as in the reroute phase of a replication action).

Copy link
Member

@dnhatn dnhatn left a comment

Choose a reason for hiding this comment

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

LGTM.

@jasontedor
Copy link
Member Author

@elasticmachine test this please

@jasontedor jasontedor added >bug and removed >test Issues or PRs that are addressing/adding tests labels Mar 23, 2019
@jasontedor
Copy link
Member Author

@elasticmachine run elasticsearch-ci/1

@jasontedor jasontedor merged commit d193f29 into elastic:master Mar 23, 2019
jasontedor added a commit that referenced this pull request Mar 23, 2019
In some cases, a request to perform a retention lease action can arrive
on a primary shard before it is active. In this case, the primary shard
would not yet be in primary mode, tripping an assertion in the
replication tracker. Instead, we should not attempt to perform such
actions on an initializing shard. This commit addresses this by not
returning the primary shard in the single shard iterator if the primary
shard is not yet active.
jasontedor added a commit that referenced this pull request Mar 23, 2019
In some cases, a request to perform a retention lease action can arrive
on a primary shard before it is active. In this case, the primary shard
would not yet be in primary mode, tripping an assertion in the
replication tracker. Instead, we should not attempt to perform such
actions on an initializing shard. This commit addresses this by not
returning the primary shard in the single shard iterator if the primary
shard is not yet active.
jasontedor added a commit that referenced this pull request Mar 23, 2019
In some cases, a request to perform a retention lease action can arrive
on a primary shard before it is active. In this case, the primary shard
would not yet be in primary mode, tripping an assertion in the
replication tracker. Instead, we should not attempt to perform such
actions on an initializing shard. This commit addresses this by not
returning the primary shard in the single shard iterator if the primary
shard is not yet active.
@jasontedor jasontedor deleted the acquire-primary-permit-initializing-shard branch March 23, 2019 13:41
pgomulka pushed a commit to pgomulka/elasticsearch that referenced this pull request Mar 25, 2019
In some cases, a request to perform a retention lease action can arrive
on a primary shard before it is active. In this case, the primary shard
would not yet be in primary mode, tripping an assertion in the
replication tracker. Instead, we should not attempt to perform such
actions on an initializing shard. This commit addresses this by not
returning the primary shard in the single shard iterator if the primary
shard is not yet active.
.shardRoutingTable(request.concreteIndex(), request.request().getShardId().id())
.primaryShardIt();
.shardRoutingTable(request.concreteIndex(), request.request().getShardId().id());
if (shardRoutingTable.primaryShard().active()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

TransportSingleShardAction doesn't do our usual "chase the shard" pattern where we re-resolve shards on each node until we find a place where the shard is locally available. This means that if the coordinating node thinks the shard is active but the node with the shard didn't yet process the shard activation cluster state, I think this still goes wrong (i.e., the primary would not be in primary mode, which is activated when the cluster state is processed). I hope I'm wrong and please let me know what I'm missing.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch. In this case, I think that we should use the other approach that I considered. I can not think of any situations where we would want to acquire a permit on a non-active primary?

Copy link
Contributor

Choose a reason for hiding this comment

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

That was actually why I went looking - my instinct was that this should be done under permit and that the permit shouldn't be given under a non-initialized primary. We currently don't do that so that requires a much bigger change/vision. We can also have a targeted-check in asyncShardOperation that the shard is active before performing the operation. @ywelsch any thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

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

RetentionLeaseActions and TransportForgetFollowerAction can also possibly violate the assertion in acquirePrimaryOperationPermit that the shard is actually a primary (by the time the request arrives, the primary could have failed and a replica allocated instead). Ensuring this was previously left to the caller of this method.

We can explore changing acquirePrimaryOperationPermit and acquireAllPrimaryOperationsPermits to throw appropriate exceptions if the shard is not in primary mode (e.g. replica or initializing/relocated primary). TRA can then react to an IndexShardRelocatedException to delegate to the relocation target.

Copy link
Contributor

Choose a reason for hiding this comment

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

That takes it one level higher - ensuring that the primary is actually an active primary (rather than just an active shard). SGTM.

@jasontedor
Copy link
Member Author

I thought about the targeted check there but I realized earlier there is another operation prone to this problem: forget follower which is not a single shard action. That’s why I now lean towards a global approach.

@dnhatn
Copy link
Member

dnhatn commented May 20, 2019

A failure relating to this: https://elasticsearch-ci.elastic.co/job/elastic+elasticsearch+6.8+bwc-tests/60/console.

[2019-05-20T02:35:56,265][ERROR][o.e.b.ElasticsearchUncaughtExceptionHandler] [upgraded-node-leader-0] fatal error in thread [Thread-4], exiting
|    java.lang.AssertionError: shard [leader_index3][0], node[K_dcaDtcTlSLJ76pP0Wz8g], [P], recovery_source[existing store recovery; bootstrap_history_uuid=false], s[INITIALIZING], a[id=Ebf14YQsQkaXCWdL38NFKQ], unassigned_info[[reason=NODE_LEFT], at[2019-05-20T02:35:36.628Z], delayed=true, details[node_left [K_dcaDtcTlSLJ76pP0Wz8g]], allocation_status[fetching_shard_data]] is not a primary shard in primary mode
|        at org.elasticsearch.index.shard.IndexShard.assertPrimaryMode(IndexShard.java:1632) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.shard.IndexShard.renewRetentionLease(IndexShard.java:2030) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.seqno.RetentionLeaseActions$Renew$TransportAction.doRetentionLeaseAction(RetentionLeaseActions.java:248) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.seqno.RetentionLeaseActions$Renew$TransportAction.doRetentionLeaseAction(RetentionLeaseActions.java:222) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.seqno.RetentionLeaseActions$TransportRetentionLeaseAction$1.onResponse(RetentionLeaseActions.java:115) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.seqno.RetentionLeaseActions$TransportRetentionLeaseAction$1.onResponse(RetentionLeaseActions.java:110) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.shard.IndexShardOperationPermits.acquire(IndexShardOperationPermits.java:273) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.shard.IndexShardOperationPermits.acquire(IndexShardOperationPermits.java:240) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.shard.IndexShard.acquirePrimaryOperationPermit(IndexShard.java:2561) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.seqno.RetentionLeaseActions$TransportRetentionLeaseAction.asyncShardOperation(RetentionLeaseActions.java:109) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.index.seqno.RetentionLeaseActions$TransportRetentionLeaseAction.asyncShardOperation(RetentionLeaseActions.java:65) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$ShardTransportHandler.messageReceived(TransportSingleShardAction.java:296) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]
|        at org.elasticsearch.action.support.single.shard.TransportSingleShardAction$ShardTransportHandler.messageReceived(TransportSingleShardAction.java:289) ~[elasticsearch-6.8.0-SNAPSHOT.jar:6.8.0-SNAPSHOT]

@jasontedor @ywelsch I think we need to act on this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
>bug :Distributed/CCR Issues around the Cross Cluster State Replication features v6.7.1 v7.0.0-rc1 v7.2.0 v8.0.0-alpha1
Projects
None yet
7 participants