Skip to content

Commit bd02f91

Browse files
authored
[7.x] Deprecate Auto-Follow system indices (#73237)
This commits deprecates Auto-Follow of system indices Relates #72815
1 parent d64a72c commit bd02f91

File tree

22 files changed

+550
-70
lines changed

22 files changed

+550
-70
lines changed

docs/reference/migration/migrate_7_14.asciidoc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,23 @@ Configuring a realm name with a leading underscore is deprecated. In a future re
132132
it will result in an error on startup if any user configured realm has a name
133133
with a leading underscore.
134134
====
135+
136+
[discrete]
137+
[[breaking_714_ccr_changes]]
138+
==== CCR deprecations
139+
140+
[[system-indices-auto-follow-deprecation]]
141+
.Auto-follow remote system indices is deprecated.
142+
[%collapsible]
143+
====
144+
*Details* +
145+
Currently, remote system indices matching an <<ccr-auto-follow,auto-follow pattern>>
146+
are configured as a follower index automatically, this behavior is deprecated.
147+
148+
*Impact* +
149+
In 8.0.0, remote system indices matching an <<ccr-auto-follow,auto-follow pattern>>
150+
won't be configured as a follower index automatically. In order to adapt to this new
151+
behaviour it is advised to exclude patterns matching system indices such as `.tasks` and
152+
`kibana-*`.
153+
====
135154
// end::notable-breaking-changes[]

x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/AutoFollowIT.java

Lines changed: 121 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,31 +11,42 @@
1111
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
1212
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
1313
import org.elasticsearch.action.admin.indices.exists.indices.IndicesExistsRequest;
14+
import org.elasticsearch.action.get.GetResponse;
15+
import org.elasticsearch.action.index.IndexRequest;
16+
import org.elasticsearch.action.support.PlainActionFuture;
1417
import org.elasticsearch.client.Client;
1518
import org.elasticsearch.cluster.metadata.IndexMetadata;
1619
import org.elasticsearch.cluster.metadata.Metadata;
17-
import org.elasticsearch.core.CheckedRunnable;
20+
import org.elasticsearch.cluster.service.ClusterService;
1821
import org.elasticsearch.common.Strings;
1922
import org.elasticsearch.common.regex.Regex;
2023
import org.elasticsearch.common.settings.Settings;
2124
import org.elasticsearch.common.unit.ByteSizeUnit;
2225
import org.elasticsearch.common.unit.ByteSizeValue;
26+
import org.elasticsearch.core.CheckedRunnable;
2327
import org.elasticsearch.core.TimeValue;
2428
import org.elasticsearch.index.IndexNotFoundException;
2529
import org.elasticsearch.index.IndexSettings;
30+
import org.elasticsearch.indices.SystemIndexDescriptor;
31+
import org.elasticsearch.plugins.Plugin;
32+
import org.elasticsearch.plugins.SystemIndexPlugin;
2633
import org.elasticsearch.xpack.CcrIntegTestCase;
2734
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata;
2835
import org.elasticsearch.xpack.core.ccr.AutoFollowStats;
36+
import org.elasticsearch.xpack.core.ccr.CcrAutoFollowInfoFetcher;
37+
import org.elasticsearch.xpack.core.ccr.CcrConstants;
2938
import org.elasticsearch.xpack.core.ccr.action.ActivateAutoFollowPatternAction;
3039
import org.elasticsearch.xpack.core.ccr.action.CcrStatsAction;
3140
import org.elasticsearch.xpack.core.ccr.action.DeleteAutoFollowPatternAction;
3241
import org.elasticsearch.xpack.core.ccr.action.FollowInfoAction;
3342
import org.elasticsearch.xpack.core.ccr.action.FollowInfoAction.Response.FollowerInfo;
3443
import org.elasticsearch.xpack.core.ccr.action.FollowParameters;
3544
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction;
45+
import org.elasticsearch.xpack.core.ccr.action.PauseFollowAction;
3646
import org.elasticsearch.xpack.core.ccr.action.PutAutoFollowPatternAction;
3747

3848
import java.util.Arrays;
49+
import java.util.Collection;
3950
import java.util.Collections;
4051
import java.util.List;
4152
import java.util.Locale;
@@ -46,6 +57,7 @@
4657
import java.util.stream.Collectors;
4758

4859
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
60+
import static org.hamcrest.Matchers.empty;
4961
import static org.hamcrest.Matchers.equalTo;
5062
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
5163
import static org.hamcrest.Matchers.hasSize;
@@ -60,6 +72,49 @@ protected boolean reuseClusters() {
6072
return false;
6173
}
6274

75+
@Override
76+
protected Collection<Class<? extends Plugin>> nodePlugins() {
77+
return org.elasticsearch.core.List.of(FakeSystemIndexPlugin.class, SecondFakeSystemIndexPlugin.class);
78+
}
79+
80+
public static class FakeSystemIndexPlugin extends Plugin implements SystemIndexPlugin {
81+
public static final String SYSTEM_INDEX_NAME = ".test-system-idx";
82+
83+
@Override
84+
public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings settings) {
85+
return Collections.singletonList(new SystemIndexDescriptor(SYSTEM_INDEX_NAME, "test"));
86+
}
87+
88+
@Override
89+
public String getFeatureName() {
90+
return "FakeSystemIndexPlugin";
91+
}
92+
93+
@Override
94+
public String getFeatureDescription() {
95+
return "FakeSystemIndexPlugin";
96+
}
97+
}
98+
99+
public static class SecondFakeSystemIndexPlugin extends Plugin implements SystemIndexPlugin {
100+
public static final String SYSTEM_INDEX_NAME = ".another-test-system-idx";
101+
102+
@Override
103+
public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings settings) {
104+
return Collections.singletonList(new SystemIndexDescriptor(SYSTEM_INDEX_NAME, "test"));
105+
}
106+
107+
@Override
108+
public String getFeatureName() {
109+
return "SecondFakeSystemIndexPlugin";
110+
}
111+
112+
@Override
113+
public String getFeatureDescription() {
114+
return "Fake system index";
115+
}
116+
}
117+
63118
public void testAutoFollow() throws Exception {
64119
Settings leaderIndexSettings = Settings.builder()
65120
.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true)
@@ -117,8 +172,8 @@ public void testCleanFollowedLeaderIndexUUIDs() throws Exception {
117172

118173
Metadata metadata = getFollowerCluster().clusterService().state().metadata();
119174
String leaderIndexUUID = metadata.index("copy-logs-201901")
120-
.getCustomData(Ccr.CCR_CUSTOM_METADATA_KEY)
121-
.get(Ccr.CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY);
175+
.getCustomData(CcrConstants.CCR_CUSTOM_METADATA_KEY)
176+
.get(CcrConstants.CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY);
122177
AutoFollowMetadata autoFollowMetadata = metadata.custom(AutoFollowMetadata.TYPE);
123178
assertThat(autoFollowMetadata, notNullValue());
124179
List<String> followedLeaderIndixUUIDs = autoFollowMetadata.getFollowedLeaderIndexUUIDs().get("my-pattern");
@@ -573,7 +628,6 @@ public void testAutoFollowExclusion() throws Exception {
573628
.put(IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), 1)
574629
.put(IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 0)
575630
.build();
576-
577631
putAutoFollowPatterns("my-pattern1", new String[] {"logs-*"}, Collections.singletonList("logs-2018*"));
578632

579633
createLeaderIndex("logs-201801", leaderIndexSettings);
@@ -594,6 +648,69 @@ public void testAutoFollowExclusion() throws Exception {
594648
assertFalse(indexExists("copy-logs-201801", followerClient()));
595649
}
596650

651+
public void testGetAutoFollowedSystemIndices() throws Exception {
652+
assertThat(getFollowerAutoFollowedSystemIndices(), is(empty()));
653+
654+
// This index is created before the auto-follow pattern therefore it won't be auto-followed
655+
// but it's in the followedLeaderIndexUUIDs list anyway.
656+
createLeaderSystemIndex(FakeSystemIndexPlugin.SYSTEM_INDEX_NAME);
657+
658+
putAutoFollowPatterns("my-pattern", new String[]{".*", "logs-*"});
659+
660+
assertLongBusy(() -> {
661+
final AutoFollowStats autoFollowStats = getAutoFollowStats();
662+
assertThat(autoFollowStats.getAutoFollowedClusters().size(), equalTo(1));
663+
assertThat(autoFollowStats.getNumberOfSuccessfulFollowIndices(), equalTo(0L));
664+
});
665+
666+
assertThat(getFollowerAutoFollowedSystemIndices(), is(empty()));
667+
668+
Settings leaderIndexSettings = Settings.builder()
669+
.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true)
670+
.put(IndexMetadata.INDEX_NUMBER_OF_SHARDS_SETTING.getKey(), 1)
671+
.put(IndexMetadata.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey(), 0)
672+
.build();
673+
createLeaderIndex("logs-202101", leaderIndexSettings);
674+
createLeaderSystemIndex(SecondFakeSystemIndexPlugin.SYSTEM_INDEX_NAME);
675+
676+
final String followerSystemIndexName = "copy-" + SecondFakeSystemIndexPlugin.SYSTEM_INDEX_NAME;
677+
678+
ensureFollowerGreen(followerSystemIndexName);
679+
ensureFollowerGreen("copy-logs-202101");
680+
681+
assertLongBusy(() -> {
682+
final AutoFollowStats autoFollowStats = getAutoFollowStats();
683+
assertThat(autoFollowStats.getNumberOfSuccessfulFollowIndices(), equalTo(2L));
684+
685+
// Ensure that the operations have been replicated
686+
final GetResponse response = followerClient().prepareGet(followerSystemIndexName, "_doc", "1").execute().actionGet();
687+
assertThat(response.isExists(), equalTo(true));
688+
});
689+
690+
final List<String> autoFollowedIndices = getFollowerAutoFollowedSystemIndices();
691+
assertThat(autoFollowedIndices.size(), is(equalTo(1)));
692+
assertThat(autoFollowedIndices.get(0), is(equalTo(followerSystemIndexName)));
693+
694+
followerClient().execute(PauseFollowAction.INSTANCE, new PauseFollowAction.Request(followerSystemIndexName)).actionGet();
695+
696+
assertLongBusy(() -> {
697+
assertThat(getFollowerAutoFollowedSystemIndices(), is(empty()));
698+
});
699+
}
700+
701+
private void createLeaderSystemIndex(String indexName) {
702+
leaderClient().index(new IndexRequest(indexName).id("1").source("completed", true)).actionGet();
703+
final GetResponse getResponse = leaderClient().prepareGet(indexName, "_doc", "1").execute().actionGet();
704+
assertThat(getResponse.isExists(), equalTo(true));
705+
}
706+
707+
private List<String> getFollowerAutoFollowedSystemIndices() {
708+
final ClusterService followerClusterService = getFollowerCluster().getMasterNodeInstance(ClusterService.class);
709+
PlainActionFuture<List<String>> future = PlainActionFuture.newFuture();
710+
CcrAutoFollowInfoFetcher.getAutoFollowedSystemIndices(followerClient(), followerClusterService.state(), future);
711+
return future.actionGet();
712+
}
713+
597714
private boolean indexExists(String index, Client client) {
598715
return client.admin().indices().exists(new IndicesExistsRequest(index)).actionGet().isExists();
599716
}

x-pack/plugin/ccr/src/internalClusterTest/java/org/elasticsearch/xpack/ccr/CcrRepositoryIT.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
import org.elasticsearch.xpack.ccr.action.repositories.PutCcrRestoreSessionAction;
6060
import org.elasticsearch.xpack.ccr.repository.CcrRepository;
6161
import org.elasticsearch.xpack.ccr.repository.CcrRestoreSourceService;
62+
import org.elasticsearch.xpack.core.ccr.CcrConstants;
6263
import org.elasticsearch.xpack.core.ccr.action.PutFollowAction;
6364

6465
import java.io.IOException;
@@ -185,10 +186,10 @@ public void testThatRepositoryRecoversEmptyIndexBasedOnLeaderSettings() throws I
185186
IndexMetadata leaderMetadata = leaderState.getState().metadata().index(leaderIndex);
186187
IndexMetadata followerMetadata = followerState.getState().metadata().index(followerIndex);
187188
assertEquals(leaderMetadata.getNumberOfShards(), followerMetadata.getNumberOfShards());
188-
Map<String, String> ccrMetadata = followerMetadata.getCustomData(Ccr.CCR_CUSTOM_METADATA_KEY);
189-
assertEquals(leaderIndex, ccrMetadata.get(Ccr.CCR_CUSTOM_METADATA_LEADER_INDEX_NAME_KEY));
190-
assertEquals(leaderMetadata.getIndexUUID(), ccrMetadata.get(Ccr.CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY));
191-
assertEquals("leader_cluster", ccrMetadata.get(Ccr.CCR_CUSTOM_METADATA_REMOTE_CLUSTER_NAME_KEY));
189+
Map<String, String> ccrMetadata = followerMetadata.getCustomData(CcrConstants.CCR_CUSTOM_METADATA_KEY);
190+
assertEquals(leaderIndex, ccrMetadata.get(CcrConstants.CCR_CUSTOM_METADATA_LEADER_INDEX_NAME_KEY));
191+
assertEquals(leaderMetadata.getIndexUUID(), ccrMetadata.get(CcrConstants.CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY));
192+
assertEquals("leader_cluster", ccrMetadata.get(CcrConstants.CCR_CUSTOM_METADATA_REMOTE_CLUSTER_NAME_KEY));
192193
assertEquals(followerIndex, followerMetadata.getSettings().get(IndexMetadata.SETTING_INDEX_PROVIDED_NAME));
193194

194195
// UUID is changed so that we can follow indexes on same cluster

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/Ccr.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -132,11 +132,7 @@
132132
public class Ccr extends Plugin implements ActionPlugin, PersistentTaskPlugin, EnginePlugin, RepositoryPlugin, ClusterPlugin {
133133

134134
public static final String CCR_THREAD_POOL_NAME = "ccr";
135-
public static final String CCR_CUSTOM_METADATA_KEY = "ccr";
136-
public static final String CCR_CUSTOM_METADATA_LEADER_INDEX_SHARD_HISTORY_UUIDS = "leader_index_shard_history_uuids";
137-
public static final String CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY = "leader_index_uuid";
138-
public static final String CCR_CUSTOM_METADATA_LEADER_INDEX_NAME_KEY = "leader_index_name";
139-
public static final String CCR_CUSTOM_METADATA_REMOTE_CLUSTER_NAME_KEY = "remote_cluster_name";
135+
// Constants have been moved into CcrConstants
140136

141137
public static final String REQUESTED_OPS_MISSING_METADATA_KEY = "es.requested_operations_missing";
142138

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/AutoFollowCoordinator.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.elasticsearch.core.Tuple;
3131
import org.elasticsearch.common.component.AbstractLifecycleComponent;
3232
import org.elasticsearch.common.component.Lifecycle;
33+
import org.elasticsearch.common.logging.DeprecationCategory;
34+
import org.elasticsearch.common.logging.DeprecationLogger;
3335
import org.elasticsearch.common.settings.Settings;
3436
import org.elasticsearch.core.TimeValue;
3537
import org.elasticsearch.common.util.concurrent.AtomicArray;
@@ -38,12 +40,12 @@
3840
import org.elasticsearch.index.IndexSettings;
3941
import org.elasticsearch.license.LicenseUtils;
4042
import org.elasticsearch.transport.NoSuchRemoteClusterException;
41-
import org.elasticsearch.xpack.ccr.Ccr;
4243
import org.elasticsearch.xpack.ccr.CcrLicenseChecker;
4344
import org.elasticsearch.xpack.ccr.CcrSettings;
4445
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata;
4546
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
4647
import org.elasticsearch.xpack.core.ccr.AutoFollowStats;
48+
import org.elasticsearch.xpack.core.ccr.CcrConstants;
4749
import org.elasticsearch.xpack.core.ccr.action.PutFollowAction;
4850
import org.elasticsearch.xpack.core.searchablesnapshots.SearchableSnapshotsConstants;
4951

@@ -75,6 +77,8 @@
7577
public class AutoFollowCoordinator extends AbstractLifecycleComponent implements ClusterStateListener {
7678

7779
private static final Logger LOGGER = LogManager.getLogger(AutoFollowCoordinator.class);
80+
public static final DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(AutoFollowCoordinator.class);
81+
7882
private static final int MAX_AUTO_FOLLOW_ERRORS = 256;
7983

8084
private final Client client;
@@ -538,6 +542,14 @@ private void checkAutoFollowPattern(String autoFollowPattenName,
538542
updateAutoFollowMetadata(recordLeaderIndexAsFollowFunction(autoFollowPattenName, indexToFollow),
539543
error -> groupedListener.onResponse(new Tuple<>(indexToFollow, error)));
540544
} else {
545+
if (indexAbstraction.isSystem()) {
546+
deprecationLogger.deprecate(DeprecationCategory.INDICES,
547+
"ccr_auto_follow_system_indices",
548+
"Auto following a leader system index " + indexToFollow.getName() +
549+
" will not work in the next major version"
550+
);
551+
}
552+
541553
followLeaderIndex(autoFollowPattenName, remoteCluster, indexToFollow, autoFollowPattern, headers,
542554
error -> groupedListener.onResponse(new Tuple<>(indexToFollow, error)));
543555
}
@@ -555,9 +567,9 @@ private static boolean leaderIndexAlreadyFollowed(AutoFollowPattern autoFollowPa
555567
// we should let the auto follower attempt to auto follow it, so it can fail later and
556568
// it is then visible in the auto follow stats. For example a cluster can just happen to have
557569
// an index with the same name as the new follower index.
558-
Map<String, String> customData = indexMetadata.getCustomData(Ccr.CCR_CUSTOM_METADATA_KEY);
570+
Map<String, String> customData = indexMetadata.getCustomData(CcrConstants.CCR_CUSTOM_METADATA_KEY);
559571
if (customData != null) {
560-
String recordedLeaderIndexUUID = customData.get(Ccr.CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY);
572+
String recordedLeaderIndexUUID = customData.get(CcrConstants.CCR_CUSTOM_METADATA_LEADER_INDEX_UUID_KEY);
561573
return leaderIndex.getUUID().equals(recordedLeaderIndexUUID);
562574
}
563575
}

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/ShardFollowTasksExecutor.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
import org.elasticsearch.xpack.ccr.action.bulk.BulkShardOperationsAction;
7272
import org.elasticsearch.xpack.ccr.action.bulk.BulkShardOperationsRequest;
7373
import org.elasticsearch.xpack.ccr.action.bulk.BulkShardOperationsResponse;
74+
import org.elasticsearch.xpack.core.ccr.CcrConstants;
7475
import org.elasticsearch.xpack.core.ccr.action.ShardFollowTask;
7576

7677
import java.util.ArrayList;
@@ -521,7 +522,7 @@ private void logRetentionLeaseFailure(final String retentionLeaseId, final Throw
521522

522523
private String getLeaderShardHistoryUUID(ShardFollowTask params) {
523524
IndexMetadata followIndexMetadata = clusterService.state().metadata().index(params.getFollowShardId().getIndex());
524-
Map<String, String> ccrIndexMetadata = followIndexMetadata.getCustomData(Ccr.CCR_CUSTOM_METADATA_KEY);
525+
Map<String, String> ccrIndexMetadata = followIndexMetadata.getCustomData(CcrConstants.CCR_CUSTOM_METADATA_KEY);
525526
String[] recordedLeaderShardHistoryUUIDs = extractLeaderShardHistoryUUIDs(ccrIndexMetadata);
526527
return recordedLeaderShardHistoryUUIDs[params.getLeaderShardId().id()];
527528
}

x-pack/plugin/ccr/src/main/java/org/elasticsearch/xpack/ccr/action/TransportFollowInfoAction.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import org.elasticsearch.persistent.PersistentTasksCustomMetadata;
2121
import org.elasticsearch.threadpool.ThreadPool;
2222
import org.elasticsearch.transport.TransportService;
23-
import org.elasticsearch.xpack.ccr.Ccr;
23+
import org.elasticsearch.xpack.core.ccr.CcrConstants;
2424
import org.elasticsearch.xpack.core.ccr.action.FollowInfoAction;
2525
import org.elasticsearch.xpack.core.ccr.action.FollowInfoAction.Response.FollowerInfo;
2626
import org.elasticsearch.xpack.core.ccr.action.FollowInfoAction.Response.Status;
@@ -65,7 +65,7 @@ static List<FollowerInfo> getFollowInfos(List<String> concreteFollowerIndices, C
6565

6666
for (String index : concreteFollowerIndices) {
6767
IndexMetadata indexMetadata = state.metadata().index(index);
68-
Map<String, String> ccrCustomData = indexMetadata.getCustomData(Ccr.CCR_CUSTOM_METADATA_KEY);
68+
Map<String, String> ccrCustomData = indexMetadata.getCustomData(CcrConstants.CCR_CUSTOM_METADATA_KEY);
6969
if (ccrCustomData != null) {
7070
Optional<ShardFollowTask> result;
7171
if (persistentTasks != null) {
@@ -78,8 +78,8 @@ static List<FollowerInfo> getFollowInfos(List<String> concreteFollowerIndices, C
7878
}
7979

8080
String followerIndex = indexMetadata.getIndex().getName();
81-
String remoteCluster = ccrCustomData.get(Ccr.CCR_CUSTOM_METADATA_REMOTE_CLUSTER_NAME_KEY);
82-
String leaderIndex = ccrCustomData.get(Ccr.CCR_CUSTOM_METADATA_LEADER_INDEX_NAME_KEY);
81+
String remoteCluster = ccrCustomData.get(CcrConstants.CCR_CUSTOM_METADATA_REMOTE_CLUSTER_NAME_KEY);
82+
String leaderIndex = ccrCustomData.get(CcrConstants.CCR_CUSTOM_METADATA_LEADER_INDEX_NAME_KEY);
8383
if (result.isPresent()) {
8484
ShardFollowTask params = result.get();
8585
FollowParameters followParameters = new FollowParameters();

0 commit comments

Comments
 (0)