Prechádzať zdrojové kódy

Add index forecasts to /_cat/allocation output (#97561)

This change adds shard size and ingest load forecasts to /_cat/allocation output
Ievgen Degtiarenko 1 rok pred
rodič
commit
92f6197819

+ 5 - 0
docs/changelog/97561.yaml

@@ -0,0 +1,5 @@
+pr: 97561
+summary: Add index forecasts to /_cat/allocation output
+area: Allocation
+type: enhancement
+issues: []

+ 14 - 2
docs/reference/cat/allocation.asciidoc

@@ -57,6 +57,16 @@ include::{es-repo-dir}/rest-api/common-parms.asciidoc[tag=cat-v]
 `shards`::
 Number of primary and replica shards assigned to the node.
 
+`shards.undesired`::
+Amount of shards that are scheduled to be moved elsewhere in the cluster
+or -1 other than desired balance allocator is used
+
+`write_load.forecast`::
+Sum of index write load forecasts
+
+`disk.indices.forecast`::
+Sum of shard size forecasts
+
 `disk.indices`::
 Disk space used by the node's shards. Does not include disk space for the
 <<index-modules-translog,translog>> or unassigned shards.
@@ -99,6 +109,8 @@ IP address and port for the node.
 `node`::
 Name for the node. Set using <<node-name,`node.name`>>.
 
+`node.role`, `r`, `role`, `nodeRole`::
+Node roles
 
 [[cat-allocation-api-example]]
 ==== {api-examples-title}
@@ -113,8 +125,8 @@ The API returns the following response:
 
 [source,txt]
 --------------------------------------------------
-shards disk.indices disk.used disk.avail disk.total disk.percent host      ip        node    node.role
-     1         260b    47.3gb     43.4gb    100.7gb           46 127.0.0.1 127.0.0.1 CSUXak2 himrst
+shards shards.undesired write_load.forecast disk.indices.forecast disk.indices disk.used disk.avail disk.total disk.percent host      ip        node    node.role
+     1                0                 0.0                  260b         260b    47.3gb     43.4gb    100.7gb           46 127.0.0.1 127.0.0.1 CSUXak2 himrst
 --------------------------------------------------
 // TESTRESPONSE[s/\d+(\.\d+)?[tgmk]?b/\\d+(\\.\\d+)?[tgmk]?b/ s/46/\\d+/]
 // TESTRESPONSE[s/CSUXak2 himrst/.+/ non_json]

+ 65 - 25
rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cat.allocation/10_basic.yml

@@ -2,8 +2,8 @@
 "Help":
 
   - skip:
-      version: " - 8.9.99"
-      reason:  "node.role column added in 8.10.0"
+      version: " - 8.13.99"
+      reason:  "shards.undesired, write_load.forecast and disk.indices.forecast are added in 8.14.0"
 
   - do:
       cat.allocation:
@@ -11,24 +11,27 @@
 
   - match:
       $body: |
-               /^  shards            .+   \n
-                   disk.indices      .+   \n
-                   disk.used         .+   \n
-                   disk.avail        .+   \n
-                   disk.total        .+   \n
-                   disk.percent      .+   \n
-                   host              .+   \n
-                   ip                .+   \n
-                   node              .+   \n
-                   node.role         .+   \n
+               /^  shards                .+   \n
+                   shards.undesired      .+   \n
+                   write_load.forecast   .+   \n
+                   disk.indices.forecast .+   \n
+                   disk.indices          .+   \n
+                   disk.used             .+   \n
+                   disk.avail            .+   \n
+                   disk.total            .+   \n
+                   disk.percent          .+   \n
+                   host                  .+   \n
+                   ip                    .+   \n
+                   node                  .+   \n
+                   node.role             .+   \n
                $/
 
 ---
 "One index":
 
   - skip:
-      version: " - 8.11.99"
-      reason:  "node.role column shown by default from 8.12.0 onwards"
+      version: " - 8.13.99"
+      reason:  "shards.undesired, write_load.forecast and disk.indices.forecast columns are added in 8.14.0"
 
   - do:
         indices.create:
@@ -42,6 +45,9 @@
             /^
               ( \s*                          #allow leading spaces to account for right-justified text
                 \d+                    \s+
+                \d+                    \s+
+                \d+(\.\d+)?            \s+
+                \d+(\.\d+)?[kmgt]?b    \s+
                 \d+(\.\d+)?[kmgt]?b    \s+
                 \d+(\.\d+)?[kmgt]?b    \s+
                 (\d+(\.\d+)?[kmgt]b   \s+)  #always should return value since we filter out non data nodes by default
@@ -65,8 +71,8 @@
 "Node ID":
 
   - skip:
-      version: " - 8.11.99"
-      reason:  "node.role column shown by default from 8.12.0 onwards"
+      version: " - 8.13.99"
+      reason:  "shards.undesired, write_load.forecast and disk.indices.forecast columns are added in 8.14.0"
 
   - do:
         cat.allocation:
@@ -76,6 +82,9 @@
       $body: |
             /^
               ( \d+                    \s+   #usually 0, unless some system index has been recreated before this runs
+                \d+                    \s+
+                \d+(\.\d+)?            \s+
+                \d+(\.\d+)?[kmgt]?b    \s+
                 \d+(\.\d+)?[kmgt]?b    \s+
                 \d+(\.\d+)?[kmgt]?b    \s+
                 (\d+(\.\d+)?[kmgt]b   \s+)?  #no value from client nodes
@@ -99,12 +108,11 @@
             $/
 
 ---
-
 "All Nodes":
 
    - skip:
-      version: " - 8.11.99"
-      reason:  "node.role column shown by default from 8.12.0 onwards"
+      version: " - 8.13.99"
+      reason:  "shards.undesired, write_load.forecast and disk.indices.forecast columns are added in 8.14.0"
 
    - do:
          cat.allocation:
@@ -115,6 +123,9 @@
              /^
                ( \s*                          #allow leading spaces to account for right-justified text
                  \d+                    \s+   #usually 0, unless some system index has been recreated before this runs
+                 \d+                    \s+
+                 \d+(\.\d+)?            \s+
+                 \d+(\.\d+)?[kmgt]?b    \s+
                  \d+(\.\d+)?[kmgt]?b    \s+
                  \d+(\.\d+)?[kmgt]?b    \s+
                  (\d+(\.\d+)?[kmgt]b   \s+)?  #no value from client nodes
@@ -138,8 +149,8 @@
 "Column headers":
 
   - skip:
-      version: " - 8.11.99"
-      reason:  "node.role column shown by default from 8.12.0 onwards"
+      version: " - 8.13.99"
+      reason:  "shards.undesired, write_load.forecast and disk.indices.forecast columns are added in 8.14.0"
 
   - do:
         cat.allocation:
@@ -148,6 +159,9 @@
 
       $body: |
            /^  shards                  \s+
+               shards.undesired        \s+
+               write_load.forecast     \s+
+               disk.indices.forecast   \s+
                disk.indices            \s+
                disk.used               \s+
                disk.avail              \s+
@@ -161,6 +175,9 @@
 
               ( \s*                          #allow leading spaces to account for right-justified text
                 \d+                    \s+   #usually 0, unless some system index has been recreated before this runs
+                \d+                    \s+
+                \d+(\.\d+)?            \s+
+                \d+(\.\d+)?[kmgt]?b    \s+
                 \d+(\.\d+)?[kmgt]?b    \s+
                 \d+(\.\d+)?[kmgt]?b    \s+
                 (\d+(\.\d+)?[kmgt]b   \s+)  #always should return value since we filter out non data nodes by default
@@ -211,12 +228,11 @@
 
 
 ---
-
 "Bytes":
 
   - skip:
-      version: " - 8.11.99"
-      reason:  "node.role column shown by default from 8.12.0 onwards"
+      version: " - 8.13.99"
+      reason:  "shards.undesired, write_load.forecast and disk.indices.forecast columns are added in 8.14.0"
 
   - do:
       cat.allocation:
@@ -226,6 +242,9 @@
       $body: |
             /^
               ( \d+                 \s+    #usually 0, unless some system index has been recreated before this runs
+                \d+                 \s+
+                \d+(\.\d+)?         \s+
+                \d+                 \s+
                 0                   \s+
                 \d+                 \s+
                 (\d+                 \s+)  #always should return value since we filter out non data nodes by default
@@ -240,7 +259,6 @@
             $/
 
 ---
-
 "Node roles":
 
   - skip:
@@ -259,3 +277,25 @@
             \n
           )+
         $/
+
+---
+"Node forecasts":
+
+  - skip:
+      version: " - 8.13.99"
+      reason:  "write_load.forecast and disk.indices.forecast columns added in 8.14.0"
+
+  - do:
+      cat.allocation:
+        h: [node, shards.undesired, write_load.forecast, disk.indices.forecast]
+
+  - match:
+      $body: |
+        /^
+          ( [-\w.]+                \s+
+            [-\w.]+                \s+
+            [-\w.]+                \s+
+            [\w]+
+            \n
+          )+
+        $/

+ 21 - 14
server/src/main/java/org/elasticsearch/rest/action/cat/RestAllocationAction.java

@@ -18,6 +18,7 @@ import org.elasticsearch.action.admin.indices.stats.CommonStatsFlags;
 import org.elasticsearch.client.internal.node.NodeClient;
 import org.elasticsearch.cluster.node.DiscoveryNode;
 import org.elasticsearch.cluster.routing.ShardRouting;
+import org.elasticsearch.cluster.routing.allocation.NodeAllocationStats;
 import org.elasticsearch.common.Strings;
 import org.elasticsearch.common.Table;
 import org.elasticsearch.common.unit.ByteSizeValue;
@@ -37,6 +38,8 @@ import static org.elasticsearch.rest.RestRequest.Method.GET;
 @ServerlessScope(Scope.INTERNAL)
 public class RestAllocationAction extends AbstractCatAction {
 
+    private static final String UNASSIGNED = "UNASSIGNED";
+
     @Override
     public List<Route> routes() {
         return List.of(new Route(GET, "/_cat/allocation"), new Route(GET, "/_cat/allocation/{nodes}"));
@@ -67,9 +70,10 @@ public class RestAllocationAction extends AbstractCatAction {
                 statsRequest.setIncludeShardsStats(false);
                 statsRequest.clear()
                     .addMetric(NodesStatsRequestParameters.Metric.FS.metricName())
+                    .addMetric(NodesStatsRequestParameters.Metric.ALLOCATIONS.metricName())
                     .indices(new CommonStatsFlags(CommonStatsFlags.Flag.Store));
 
-                client.admin().cluster().nodesStats(statsRequest, new RestResponseListener<NodesStatsResponse>(channel) {
+                client.admin().cluster().nodesStats(statsRequest, new RestResponseListener<>(channel) {
                     @Override
                     public RestResponse buildResponse(NodesStatsResponse stats) throws Exception {
                         Table tab = buildTable(request, state, stats);
@@ -86,6 +90,9 @@ public class RestAllocationAction extends AbstractCatAction {
         final Table table = new Table();
         table.startHeaders();
         table.addCell("shards", "alias:s;text-align:right;desc:number of shards on node");
+        table.addCell("shards.undesired", "text-align:right;desc:number of shards that are scheduled to be moved elsewhere in the cluster");
+        table.addCell("write_load.forecast", "alias:wlf,writeLoadForecast;text-align:right;desc:sum of index write load forecasts");
+        table.addCell("disk.indices.forecast", "alias:dif,diskIndicesForecast;text-align:right;desc:sum of shard size forecasts");
         table.addCell("disk.indices", "alias:di,diskIndices;text-align:right;desc:disk used by ES indices");
         table.addCell("disk.used", "alias:du,diskUsed;text-align:right;desc:disk used (total, not just ES)");
         table.addCell("disk.avail", "alias:da,diskAvail;text-align:right;desc:disk available");
@@ -100,22 +107,17 @@ public class RestAllocationAction extends AbstractCatAction {
     }
 
     private Table buildTable(RestRequest request, final ClusterStateResponse state, final NodesStatsResponse stats) {
-        final Map<String, Integer> allocs = new HashMap<>();
+        final Map<String, Integer> shardCounts = new HashMap<>();
 
         for (ShardRouting shard : state.getState().routingTable().allShardsIterator()) {
-            String nodeId = "UNASSIGNED";
-            if (shard.assignedToNode()) {
-                nodeId = shard.currentNodeId();
-            }
-            allocs.merge(nodeId, 1, Integer::sum);
+            String nodeId = shard.assignedToNode() ? shard.currentNodeId() : UNASSIGNED;
+            shardCounts.merge(nodeId, 1, Integer::sum);
         }
         Table table = getTableWithHeader(request);
 
         for (NodeStats nodeStats : stats.getNodes()) {
             DiscoveryNode node = nodeStats.getNode();
 
-            int shardCount = allocs.getOrDefault(node.getId(), 0);
-
             ByteSizeValue total = nodeStats.getFs().getTotal().getTotal();
             ByteSizeValue avail = nodeStats.getFs().getTotal().getAvailable();
             // if we don't know how much we use (non data nodes), it means 0
@@ -127,9 +129,13 @@ public class RestAllocationAction extends AbstractCatAction {
                     diskPercent = (short) (used * 100 / (used + avail.getBytes()));
                 }
             }
+            NodeAllocationStats nodeAllocationStats = nodeStats.getNodeAllocationStats();
 
             table.startRow();
-            table.addCell(shardCount);
+            table.addCell(shardCounts.getOrDefault(node.getId(), 0));
+            table.addCell(nodeAllocationStats != null ? nodeAllocationStats.undesiredShards() : null);
+            table.addCell(nodeAllocationStats != null ? nodeAllocationStats.forecastedIngestLoad() : null);
+            table.addCell(nodeAllocationStats != null ? ByteSizeValue.ofBytes(nodeAllocationStats.forecastedDiskUsage()) : null);
             table.addCell(nodeStats.getIndices().getStore().size());
             table.addCell(used < 0 ? null : ByteSizeValue.ofBytes(used));
             table.addCell(avail.getBytes() < 0 ? null : avail);
@@ -142,10 +148,12 @@ public class RestAllocationAction extends AbstractCatAction {
             table.endRow();
         }
 
-        final String UNASSIGNED = "UNASSIGNED";
-        if (allocs.containsKey(UNASSIGNED)) {
+        if (shardCounts.containsKey(UNASSIGNED)) {
             table.startRow();
-            table.addCell(allocs.get(UNASSIGNED));
+            table.addCell(shardCounts.get(UNASSIGNED));
+            table.addCell(null);
+            table.addCell(null);
+            table.addCell(null);
             table.addCell(null);
             table.addCell(null);
             table.addCell(null);
@@ -160,5 +168,4 @@ public class RestAllocationAction extends AbstractCatAction {
 
         return table;
     }
-
 }