【Elasticsearch】awareness 配置导致分片无法迁移问题排查

问题

现在要进行机房(rack)迁移,ES集群共有三个节点,开启了awareness allocation对应的attribute为rack(机房),集群中的所有节点都在同一个机房(历史遗留,理论上因为只有一个机房,所以该配置无意义)。进行机房迁移的操作是扩容了三个节点并将之前的三个节点exclude,但发现有部分分片无法迁移。

问题排查

抽查一个无法迁移分片的索引的分片分布如下

【Elasticsearch】awareness 配置导致分片无法迁移问题排查_第1张图片

问题在于gh-data-rt0728节点上的副本0分片为什么不能迁移到hlsc-data-rt-es0997节点呢?

使用_cluster/allocation/explain API查看原因(只保留所在节点gh-data-rt0728和hlsc-data-rt-es0997节点的信息):

{
  "index": "kibana1_copy.20231203",
  "shard": 0,
  "primary": false,
  "current_state": "started",
  "current_node": {
    "id": "4OKIXAODQS6TZ15Q1Q_r9Q",
    "name": "gh-data-rt0728",
    "transport_address": "10.22.170.21:8412",
    "attributes": {
      "机房": "gh"
    }
  },
  "can_remain_on_current_node": "no",
  "can_remain_decisions": [
    {
      "decider": "filter",
      "decision": "NO",
      "explanation": "node matches cluster setting [cluster.routing.allocation.exclude] filters [_ip:\"10.22.170.18 OR 10.22.170.21 OR 10.22.170.20\"]"
    }
  ],
    {
      "node_id": "bFxwzd5VRk6y0Pp_CV0g-g",
      "node_name": "hlsc-data-rt-es0997",
      "transport_address": "10.253.66.154:8412",
      "node_attributes": {
        "机房": "hlsc"
      },
      "node_decision": "no",
      "weight_ranking": 5,
      "deciders": [
        {
          "decider": "awareness",
          "decision": "NO",
          "explanation": "there are too many copies of the shard allocated to nodes with attribute [机房], there are [3] total configured shard copies for this shard id and [2] total attribute values, expected the allocated shard count per attribute [3] to be less than or equal to the upper bound of the required number of shards per attribute [2]"
        }
      ]
    }
  ]
}

通过返回结果可以看出,原因在于awareness decider对分配返回的结果为NO,看描述是说如果分片分配到hlsc-data-rt-es0997后,该机房上总共有shard 0的 3 个分片,大于最大值 2 。那么问题来了,现在分片不能进行分配,为什么之前未扩容3个新节点时分片能够分配呢?之前3个节点也在同一个机房,新扩容的3个节点也在同一个机房啊。

我们通过看ES源码来继续排查一下,主要关注上面的 **3 **和 2 这两个数字是如何计算出来的,下面是这两个数字计算的代码,省去了无用代码,可以看出currentNodeCount对应 **3 **maximumNodeCount对应 2 ,如果currentNodeCount大于maximumNodeCount则分片无法分配:

// shard attr实际值 -> 对应shard数量
ObjectIntHashMap<String> shardPerAttribute = new ObjectIntHashMap<>();
// 索引的副本数量+1
int shardCount = indexMetadata.getNumberOfReplicas() + 1;
// 该attr key的value种类
int numberOfAttributes = nodesPerAttribute.size(); 
final int currentNodeCount = shardPerAttribute.get(node.node().getAttributes().get(awarenessAttribute));
final int maximumNodeCount = (shardCount + numberOfAttributes - 1) / numberOfAttributes; 
            if (currentNodeCount > maximumNodeCount) {
                return allocation.decision(Decision.NO, NAME,
                        "there are too many copies of the shard allocated to nodes with attribute [%s], there are [%d] total configured " +
                        "shard copies for this shard id and [%d] total attribute values, expected the allocated shard count per " +
                        "attribute [%d] to be less than or equal to the upper bound of the required number of shards per attribute [%d]",
                        awarenessAttribute,
                        shardCount,
                        numberOfAttributes,
                        currentNodeCount,
                        maximumNodeCount);
            }
  • 对于机房迁移前,这些变量值为:

    shardCount = 3 // 索引有两个replica
    currentNodeCount = 3 // 3个分片分配在3个节点上
    numberOfAttributes = 1 // 所有节点都在同一个机房上
    maximumNodeCount = (3 + 1 - 1)/1 = 3
    

​ 由于currentNodeCount==maximumNodeCount,所以分片正常分配

  • 对于机房迁移后,这些变量值为:

    shardCount = 3 // 索引有两个replica
    currentNodeCount = 3 // 3个分片分配在3个节点上
    numberOfAttributes = 2 // 旧节点和新节点在不同的机房上,所以为2
    maximumNodeCount = (3 + 2 - 1)/2 = 2 
    

    由于currentNodeCount > maximumNodeCount,所以分片不能迁移

解决办法

  1. 我们可以看出numberOfAttributes的计算不会考虑exclude filter,导致发生了冲突,exclude filter配置中的节点无法分配分片,又因为awareness filter分片又无法分配到新扩容机房的节点。这里的逻辑可以进行改进,让awareness filternumberOfAttributes的计算排除掉exclude filter的节点。通过浏览社区issue发现https://github.com/elastic/elasticsearch/issues/52374提出了该问题,但仍没有解决。那么我们优先考虑临时解法。
  2. 扩容两个其他机房的节点使得分片可以分配到这个节点上
maximumNodeCount = (shardCount + numberOfAttributes - 1) / numberOfAttributes
                 = 1 +  (shardCount - 1) / numberOfAttributes
                 = 1 + 2 / numberOfAttributes
因为当前numberOfAttributes为 2 不能解决问题,所以预期numberOfAttributes大于 2 ,那么maximumNodeCount=1则每个分片需要分配在不同机房的节点,因为shardCount = 3那么必须有3个及以上的可用机房节点
  1. 因为对于该集群来说awareness filter配置无意义,可以删除该配置

你可能感兴趣的:(elasticsearch,大数据,搜索引擎)