红色或黄色集群健康状态

编辑

红色或黄色集群健康状态表示一个或多个分片未分配给节点。

  • 红色健康状态:集群有一些未分配的主分片,这意味着某些操作(如搜索和索引)可能会失败。
  • 黄色健康状态:集群没有未分配的主分片,但有一些未分配的副本分片。这会增加数据丢失的风险,并可能降低集群性能。

当您的集群处于红色或黄色健康状态时,它将继续在可能的情况下处理搜索和索引,但可能会延迟某些管理和清理活动,直到集群恢复为绿色健康状态。例如,一些 ILM 操作要求其操作的索引具有绿色健康状态。

在许多情况下,您的集群将自动恢复到绿色健康状态。如果集群没有自动恢复,则必须手动解决剩余的问题,以便管理和清理活动可以继续进行。请观看此视频,了解监控分配健康状况的演练。

诊断您的集群状态

编辑

检查您的集群状态

使用集群健康 API

resp = client.cluster.health(
    filter_path="status,*_shards",
)
print(resp)
response = client.cluster.health(
  filter_path: 'status,*_shards'
)
puts response
const response = await client.cluster.health({
  filter_path: "status,*_shards",
});
console.log(response);
GET _cluster/health?filter_path=status,*_shards

一个健康的集群具有绿色的 status 和零个 unassigned_shards。黄色状态意味着只有副本未分配。红色状态意味着一个或多个主分片未分配。

查看未分配的分片

要查看未分配的分片,请使用cat shards API

resp = client.cat.shards(
    v=True,
    h="index,shard,prirep,state,node,unassigned.reason",
    s="state",
)
print(resp)
response = client.cat.shards(
  v: true,
  h: 'index,shard,prirep,state,node,unassigned.reason',
  s: 'state'
)
puts response
const response = await client.cat.shards({
  v: "true",
  h: "index,shard,prirep,state,node,unassigned.reason",
  s: "state",
});
console.log(response);
GET _cat/shards?v=true&h=index,shard,prirep,state,node,unassigned.reason&s=state

未分配的分片的 stateUNASSIGNEDprirep 值对于主分片为 p,对于副本为 r

要了解为什么未分配的分片没有被分配,以及您必须采取什么措施才能允许 Elasticsearch 分配它,请使用集群分配解释 API

resp = client.cluster.allocation_explain(
    filter_path="index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*",
    index="my-index",
    shard=0,
    primary=False,
)
print(resp)
response = client.cluster.allocation_explain(
  filter_path: 'index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*',
  body: {
    index: 'my-index',
    shard: 0,
    primary: false
  }
)
puts response
const response = await client.cluster.allocationExplain({
  filter_path:
    "index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*",
  index: "my-index",
  shard: 0,
  primary: false,
});
console.log(response);
GET _cluster/allocation/explain?filter_path=index,node_allocation_decisions.node_name,node_allocation_decisions.deciders.*
{
  "index": "my-index",
  "shard": 0,
  "primary": false
}

修复红色或黄色集群状态

编辑

分片可能因多种原因而变为未分配。以下提示概述了最常见的原因及其解决方案。

重新启用分片分配
编辑

您通常会在重启或其他集群维护期间禁用分配。如果您事后忘记重新启用分配,Elasticsearch 将无法分配分片。要重新启用分配,请重置 cluster.routing.allocation.enable 集群设置。

resp = client.cluster.put_settings(
    persistent={
        "cluster.routing.allocation.enable": None
    },
)
print(resp)
response = client.cluster.put_settings(
  body: {
    persistent: {
      'cluster.routing.allocation.enable' => nil
    }
  }
)
puts response
const response = await client.cluster.putSettings({
  persistent: {
    "cluster.routing.allocation.enable": null,
  },
});
console.log(response);
PUT _cluster/settings
{
  "persistent" : {
    "cluster.routing.allocation.enable" : null
  }
}

请观看此视频,了解故障排除“不允许分配”的演练。

恢复丢失的节点
编辑

当数据节点离开集群时,分片通常会变为未分配。这可能是由于多种原因造成的,从连接问题到硬件故障。在您解决问题并恢复节点后,它将重新加入集群。然后,Elasticsearch 将自动分配任何未分配的分片。

为了避免在临时问题上浪费资源,Elasticsearch 默认情况下会延迟分配一分钟。如果您已恢复节点并且不想等待延迟期,则可以调用集群重新路由 API,不带任何参数来启动分配过程。该过程在后台异步运行。

response = client.cluster.reroute(
  metric: 'none'
)
puts response
POST _cluster/reroute?metric=none
修复分配设置
编辑

配置错误的分配设置可能会导致未分配的主分片。这些设置包括

要查看您的分配设置,请使用获取索引设置集群获取设置API。

resp = client.indices.get_settings(
    index="my-index",
    flat_settings=True,
    include_defaults=True,
)
print(resp)

resp1 = client.cluster.get_settings(
    flat_settings=True,
    include_defaults=True,
)
print(resp1)
response = client.indices.get_settings(
  index: 'my-index',
  flat_settings: true,
  include_defaults: true
)
puts response

response = client.cluster.get_settings(
  flat_settings: true,
  include_defaults: true
)
puts response
const response = await client.indices.getSettings({
  index: "my-index",
  flat_settings: "true",
  include_defaults: "true",
});
console.log(response);

const response1 = await client.cluster.getSettings({
  flat_settings: "true",
  include_defaults: "true",
});
console.log(response1);
GET my-index/_settings?flat_settings=true&include_defaults=true

GET _cluster/settings?flat_settings=true&include_defaults=true

您可以使用更新索引设置集群更新设置API 来更改设置。

分配或减少副本
编辑

为了防止硬件故障,Elasticsearch 不会将副本分配到与其主分片相同的节点。如果没有其他数据节点可用于托管副本,则它将保持未分配状态。要解决此问题,您可以

  • 向同一层添加数据节点以托管副本。
  • 更改 index.number_of_replicas 索引设置以减少每个主分片的副本数。我们建议每个主分片至少保留一个副本。
resp = client.indices.put_settings(
    settings={
        "index.number_of_replicas": 1
    },
)
print(resp)
response = client.indices.put_settings(
  body: {
    'index.number_of_replicas' => 1
  }
)
puts response
const response = await client.indices.putSettings({
  settings: {
    "index.number_of_replicas": 1,
  },
});
console.log(response);
PUT _settings
{
  "index.number_of_replicas": 1
}
释放或增加磁盘空间
编辑

Elasticsearch 使用低磁盘水位线以确保数据节点有足够的磁盘空间用于传入的分片。默认情况下,Elasticsearch 不会将分片分配给使用超过 85% 磁盘空间的节点。

要检查节点当前的磁盘空间,请使用cat 分配 API

resp = client.cat.allocation(
    v=True,
    h="node,shards,disk.*",
)
print(resp)
response = client.cat.allocation(
  v: true,
  h: 'node,shards,disk.*'
)
puts response
const response = await client.cat.allocation({
  v: "true",
  h: "node,shards,disk.*",
});
console.log(response);
GET _cat/allocation?v=true&h=node,shards,disk.*

如果您的节点的磁盘空间不足,您有以下几种选择

  • 升级您的节点以增加磁盘空间。
  • 删除不需要的索引以释放空间。如果您使用 ILM,则可以更新生命周期策略以使用可搜索快照或添加删除阶段。如果您不再需要搜索数据,则可以使用快照将其存储在集群外。
  • 如果您不再写入索引,请使用强制合并 API或 ILM 的强制合并操作将其段合并为更大的段。

    resp = client.indices.forcemerge(
        index="my-index",
    )
    print(resp)
    response = client.indices.forcemerge(
      index: 'my-index'
    )
    puts response
    const response = await client.indices.forcemerge({
      index: "my-index",
    });
    console.log(response);
    POST my-index/_forcemerge
  • 如果索引是只读的,请使用缩小索引 API或 ILM 的缩小操作来减少其主分片计数。

    resp = client.indices.shrink(
        index="my-index",
        target="my-shrunken-index",
    )
    print(resp)
    response = client.indices.shrink(
      index: 'my-index',
      target: 'my-shrunken-index'
    )
    puts response
    const response = await client.indices.shrink({
      index: "my-index",
      target: "my-shrunken-index",
    });
    console.log(response);
    POST my-index/_shrink/my-shrunken-index
  • 如果您的节点具有较大的磁盘容量,则可以增加低磁盘水位线或将其设置为显式字节值。

    resp = client.cluster.put_settings(
        persistent={
            "cluster.routing.allocation.disk.watermark.low": "30gb"
        },
    )
    print(resp)
    const response = await client.cluster.putSettings({
      persistent: {
        "cluster.routing.allocation.disk.watermark.low": "30gb",
      },
    });
    console.log(response);
    PUT _cluster/settings
    {
      "persistent": {
        "cluster.routing.allocation.disk.watermark.low": "30gb"
      }
    }
减少 JVM 内存压力
编辑

分片分配需要 JVM 堆内存。高 JVM 内存压力可能会触发断路器,从而停止分配并使分片保持未分配状态。请参阅高 JVM 内存压力

恢复丢失的主分片的数据
编辑

如果包含主分片的节点丢失,Elasticsearch 通常可以使用另一个节点上的副本替换它。如果您无法恢复节点并且副本不存在或无法恢复,则分配解释将报告 no_valid_shard_copy,您需要执行以下操作之一

  • 快照恢复丢失的数据
  • 从其原始数据源索引丢失的数据
  • 通过运行删除索引来接受索引级别的数据丢失
  • 通过执行集群重新路由 allocate_stale_primary 或 allocate_empty_primary 命令并使用 accept_data_loss: true 来接受分片级别的数据丢失

    仅在节点恢复不再可能时使用此选项。此过程分配一个空的主分片。如果节点稍后重新加入集群,Elasticsearch 将使用此较新的空分片中的数据覆盖其主分片,从而导致数据丢失。

    POST _cluster/reroute?metric=none
    {
      "commands": [
        {
          "allocate_empty_primary": {
            "index": "my-index",
            "shard": 0,
            "node": "my-node",
            "accept_data_loss": "true"
          }
        }
      ]
    }

请观看此视频,了解故障排除 no_valid_shard_copy 的演练。