From 78790f19e534309046395c147fb682af256d8f46 Mon Sep 17 00:00:00 2001 From: Andrei Dan Date: Tue, 9 May 2023 19:12:48 +0100 Subject: [PATCH] [ILM] Fix the migrate to tiers service and migrate action tiers configuration (#95934) (#95965) The migrate action (although no allowed in the frozen phase) would seem to convert `frozen` to `data_frozen,data_cold,data_warm,data_hot` tier configuration. As the migrate action is not allowed in the frozen phase this would never happen, however the code is confusing as it seems like it could. The migrate to data tiers routing service shared the code used by the `migrate` action that converted `frozen` to `data_frozen,data_cold,data_warm,data_hot` if it would encounter an index without any `_tier_preference` setting but with a custom node attribute configured to `frozen` e.g. `include.data: frozen` As part of https://github.com/elastic/elasticsearch/issues/84758 we have seen frozen indices with the `data_frozen,data_cold,data_warm,data_hot` tier preference however we could never reproduce it. Relates to https://github.com/elastic/elasticsearch/issues/84758 --- docs/changelog/95934.yaml | 5 ++++ .../ilm/actions/ilm-migrate.asciidoc | 6 ++--- .../cluster/routing/allocation/DataTier.java | 13 ++++++---- .../routing/allocation/DataTierTests.java | 2 ++ ...MigrateToDataTiersRoutingServiceTests.java | 24 +++++++++++++++++-- 5 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 docs/changelog/95934.yaml diff --git a/docs/changelog/95934.yaml b/docs/changelog/95934.yaml new file mode 100644 index 0000000000000..ee4d72f4c8b25 --- /dev/null +++ b/docs/changelog/95934.yaml @@ -0,0 +1,5 @@ +pr: 95934 +summary: "[ILM] Fix the migrate to tiers service and migrate action tiers configuration" +area: ILM+SLM +type: bug +issues: [] diff --git a/docs/reference/ilm/actions/ilm-migrate.asciidoc b/docs/reference/ilm/actions/ilm-migrate.asciidoc index 61ce2e1a4064d..d3e55a35c5c9a 100644 --- a/docs/reference/ilm/actions/ilm-migrate.asciidoc +++ b/docs/reference/ilm/actions/ilm-migrate.asciidoc @@ -31,10 +31,8 @@ to `data_cold,data_warm,data_hot`. This moves the index to nodes in the The migrate action is not allowed in the frozen phase. The frozen phase directly mounts the searchable snapshot using a <> -of `data_frozen,data_cold,data_warm,data_hot`. This moves the index to nodes in the -<>. If there are no nodes in the frozen tier, it falls back to the -<> tier, then the <> tier, then finally the <> -tier. +of `data_frozen`. This moves the index to nodes in the +<>. The migrate action is not allowed in the hot phase. The initial index allocation is performed <>, diff --git a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/DataTier.java b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/DataTier.java index 69b8f5b29d937..d2b2c22a287fa 100644 --- a/server/src/main/java/org/elasticsearch/cluster/routing/allocation/DataTier.java +++ b/server/src/main/java/org/elasticsearch/cluster/routing/allocation/DataTier.java @@ -100,10 +100,15 @@ public class DataTier { final Map tmpSettings = new HashMap<>(); for (int i = 0, ordered_frozen_to_hot_tiersSize = ORDERED_FROZEN_TO_HOT_TIERS.size(); i < ordered_frozen_to_hot_tiersSize; i++) { String tier = ORDERED_FROZEN_TO_HOT_TIERS.get(i); - final String prefTierString = String.join(",", ORDERED_FROZEN_TO_HOT_TIERS.subList(i, ORDERED_FROZEN_TO_HOT_TIERS.size())) - .intern(); - tmp.put(tier, prefTierString); - tmpSettings.put(tier, Settings.builder().put(DataTier.TIER_PREFERENCE, prefTierString).build()); + if (tier.equals(DATA_FROZEN)) { + tmp.put(tier, DATA_FROZEN); + tmpSettings.put(DATA_FROZEN, Settings.builder().put(DataTier.TIER_PREFERENCE, DATA_FROZEN).build()); + } else { + final String prefTierString = String.join(",", ORDERED_FROZEN_TO_HOT_TIERS.subList(i, ORDERED_FROZEN_TO_HOT_TIERS.size())) + .intern(); + tmp.put(tier, prefTierString); + tmpSettings.put(tier, Settings.builder().put(DataTier.TIER_PREFERENCE, prefTierString).build()); + } } PREFERENCE_TIER_CONFIGURATIONS = Map.copyOf(tmp); PREFERENCE_TIER_CONFIGURATION_SETTINGS = Map.copyOf(tmpSettings); diff --git a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/DataTierTests.java b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/DataTierTests.java index b716dd1c83243..c5895e1ee635b 100644 --- a/server/src/test/java/org/elasticsearch/cluster/routing/allocation/DataTierTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/routing/allocation/DataTierTests.java @@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger; import static org.elasticsearch.cluster.routing.allocation.DataTier.DATA_COLD; +import static org.elasticsearch.cluster.routing.allocation.DataTier.DATA_FROZEN; import static org.elasticsearch.cluster.routing.allocation.DataTier.DATA_HOT; import static org.elasticsearch.cluster.routing.allocation.DataTier.DATA_WARM; import static org.elasticsearch.cluster.routing.allocation.DataTier.getPreferredTiersConfiguration; @@ -120,6 +121,7 @@ public void testGetPreferredTiersConfiguration() { assertThat(getPreferredTiersConfiguration(DATA_HOT), is(DATA_HOT)); assertThat(getPreferredTiersConfiguration(DATA_WARM), is(DATA_WARM + "," + DATA_HOT)); assertThat(getPreferredTiersConfiguration(DATA_COLD), is(DATA_COLD + "," + DATA_WARM + "," + DATA_HOT)); + assertThat(getPreferredTiersConfiguration(DATA_FROZEN), is(DATA_FROZEN)); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> getPreferredTiersConfiguration("no_tier")); assertThat(exception.getMessage(), is("invalid data tier [no_tier]")); } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/cluster/metadata/MetadataMigrateToDataTiersRoutingServiceTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/cluster/metadata/MetadataMigrateToDataTiersRoutingServiceTests.java index 2b12c6597cc6e..df4b8b52a696c 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/cluster/metadata/MetadataMigrateToDataTiersRoutingServiceTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/cluster/metadata/MetadataMigrateToDataTiersRoutingServiceTests.java @@ -148,7 +148,7 @@ public void testMigrateIlmPolicyForIndexWithoutILMMetadata() { assertThat(migratedColdAllocateAction.getRequire().size(), is(0)); } - public void testMigrateIlmPolicyFOrPhaseWithDeactivatedMigrateAction() { + public void testMigrateIlmPolicyForPhaseWithDeactivatedMigrateAction() { ShrinkAction shrinkAction = new ShrinkAction(2, null); AllocateAction warmAllocateAction = new AllocateAction(null, null, Map.of("data", "warm"), null, Map.of("rack", "rack1")); @@ -511,7 +511,7 @@ public void testAllocateActionDefinesRoutingRules() { } public void testConvertAttributeValueToTierPreference() { - assertThat(convertAttributeValueToTierPreference("frozen"), is("data_frozen,data_cold,data_warm,data_hot")); + assertThat(convertAttributeValueToTierPreference("frozen"), is("data_frozen")); assertThat(convertAttributeValueToTierPreference("cold"), is("data_cold,data_warm,data_hot")); assertThat(convertAttributeValueToTierPreference("warm"), is("data_warm,data_hot")); assertThat(convertAttributeValueToTierPreference("hot"), is("data_hot")); @@ -560,6 +560,26 @@ public void testMigrateIndices() { assertThat(migratedIndex.getSettings().get(TIER_PREFERENCE), is("data_warm,data_hot")); } + { + // test the migration of `include.data: frozen` configuration to the equivalent _tier_preference routing + IndexMetadata.Builder indexWithFrozenDataAttribute = IndexMetadata.builder("indexWithFrozenDataAttribute") + .settings(getBaseIndexSettings().put(DATA_ROUTING_INCLUDE_SETTING, "frozen")); + ClusterState state = ClusterState.builder(ClusterName.DEFAULT) + .metadata(Metadata.builder().put(indexWithFrozenDataAttribute)) + .build(); + + Metadata.Builder mb = Metadata.builder(state.metadata()); + + List migratedIndices = migrateIndices(mb, state, "data"); + assertThat(migratedIndices.size(), is(1)); + assertThat(migratedIndices.get(0), is("indexWithFrozenDataAttribute")); + + ClusterState migratedState = ClusterState.builder(ClusterName.DEFAULT).metadata(mb).build(); + IndexMetadata migratedIndex = migratedState.metadata().index("indexWithFrozenDataAttribute"); + assertThat(migratedIndex.getSettings().get(DATA_ROUTING_INCLUDE_SETTING), nullValue()); + assertThat(migratedIndex.getSettings().get(TIER_PREFERENCE), is("data_frozen")); + } + { // since the index has a _tier_preference configuration the migrated index should still contain it and have ALL the `data` // attributes routing removed