为什么会出现机器配置一致的情况下,分配不平衡的情况呢?
怎么样才能将较大的分片迁移出来呢,添加节点怎么避免这种情况呢?
背景条件:
集群扩容,添加了 20个hot节点,8个cold节点。hot均衡正常,cold节点在均衡时,新加的节点磁盘使用达到了 cluster.routing.allocation.disk.watermark.low水位线,但分片数远远小于其他的cold节点,通过检查发现大分片数量远远大于其他节点
(cold的服务器配置都是一致的,包含磁盘、内存等)
均衡后cold和hot的磁盘使用
新cold节点分片数远远小于其他的cold节点
hot节点分片数与磁盘使用
cold节点分片数与磁盘使用
扩容前集群基本配置:
集群版本: 7.17.6
数据节点: 采用是hot + cold 模式,hot保留5天 通过Lifecycle 轮转至cold,cold数据保留60天
容量: 700T,cold 和hot 磁盘使用基本60%左右
索引与分片: 索引个数有5600(一副本), 分片有25,200
分片大小不一致,少部分分片在70G左右,其他都在10G一下。
节点: 每个服务器部署4个节点,hot节点有72个,每个节点分片在70左右;cold节点有32个,每个节点分片在1400个左右
扩容前后hot和cold的每台服务器配置分别都是一致的,包含磁盘、内存等
hot 磁盘 31T
cold 磁盘 144T
关于分片分配
分片分配的两个基本流程控制
- Shard allocation: 未分配的分片应该分配到哪些节点
- Shard rebalancing:已分配的分片移动到另一个节点
重新平衡的工作原理
在未达到其他限制条件的情况下,是根据分片数来分配分片的,所以可能出现了分配不平衡的情况
#https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-cluster.html
根据每个节点的分片分配计算权重得分,移动分片达到均衡
cluster.routing.allocation.balance.shard: 0.45f #(动态 权重因子(浮点数) 默认为0.45f
cluster.routing.allocation.balance.index: 0.55f #(动态 特定节点 每个索引的分片数的权重因子(浮点数) 默认为0.55f
cluster.routing.allocation.balance.threshold: 1.0f #(动态 集群在优化分片平衡方面不那么积极 默认为1.0f
其他影响分片分配的配置
控制是否开启平衡配置
cluster.routing.allocation.enable: all
cluster.routing.rebalance.enable: all #(动态)all- (默认) 重新均衡
cluster.routing.allocation.allow_rebalance: indices_all_active #动态 always- 始终允许重新平衡。 ndices_all_active- (默认)仅当集群中的所有分片(主分片和副本)都已分配时
基于磁盘分片分配
cluster.routing.allocation.disk.threshold_enabled: true # (动态)默认为true。设置为false禁用磁盘分配决定器。
cluster.routing.allocation.disk.watermark.low: 95% #(动态) 可以写绝对值 100gb, 默认为85,%此设置对新创建索引的主分片没有影响,但会阻止分配它们的副本。
cluster.routing.allocation.disk.watermark.high: 98% #(动态) 可以写绝对值 50gb, 默认为90%, 此设置影响所有分片的分配,无论之前是否分配
cluster.routing.allocation.disk.watermark.flood_stage: 99% #(动态)可以写绝对值 10gb, 默认为 95%, index.blocks.read_only_allow_delete每个索引强制执行只读索引块 此设置是防止节点耗尽磁盘空间的最后手段。当磁盘利用率低于高水位线时,索引块会自动释放。
基于一台机器多节点分配限制
cluster.routing.allocation.awareness.attributes: rack_id
cluster.routing.allocation.same_shard.host: true#(动态)允许根据主机名和主机地址执行检查以防止在单个主机上分配同一分片的多个实例。
基于分片过滤
# 目前集群暂未配置
cluster.routing.allocation.include.{attribute} #(动态{attribute})将分片分配给至少具有一个逗号分隔值的 节点。
cluster.routing.allocation.require.{attribute} #(动态{attribute})仅将分片分配给具有所有逗号分隔值的 节点。
cluster.routing.allocation.exclude.{attribute} #(动态)不要将分片分配给{attribute}具有任何逗号分隔值的节点。
#索引级别
index.routing.allocation.include.{attribute}
index.routing.allocation.require.{attribute}
index.routing.allocation.exclude.{attribute}
基于分片数量配置
cluster.max_shards_per_node: 655350 #(动态)限制集群的主分片和副本分片的总数, 默认为1000.
cluster.max_shards_per_node.frozen: 655350 #(动态)限制集群的主和副本冻结分片的总数, 默认为3000
index.routing.allocation.total_shards_per_node: #分配给单个节点的最大分片数(副本和主分片)
cluster.routing.allocation.total_shards_per_node: -1#(动态)分配给每个节点的主分片和副本分片的最大数量。默认为 -1(无限制)
cluster.indices.tombstones.size: 500 #(静态)索引墓碑可防止不属于集群的节点在发生删除时加入集群并重新导入索引
为什么没有根据cpu和内存重平衡机制
内存和 CPU 压力可能比磁盘空间压力更瞬态,由瞬态问题而开始重新分配分片不太适合。
如果集群新加的节点保持空闲状态,集群将比较新的分片分配到新的节点
如果是hot节点而且没有awareness 相关的配置 容易导致新加的节点资源负载较大shard allocation filter 以防止将新索引分配给为空的新节点
#7.17.6
float weight(Balancer balancer, ModelNode node, String index) {
final float weightShard =node.numShards() - balancer.avgShardsPerNode();
final float weightIndex =node.numShards(index) - balancer.avgShardsPerNode(index);
return theta0 * weightShard + theta1 * weightIndex;
分片都被认为是等效的,并且仅通过分片数量在节点之间进行平衡,该策略有利于重新平衡操作,但不利于新分片分配。
从 8.6 开始会考虑分片大小(diskUsage)
float weight(Balancer balancer, ModelNode node, String index) {
final float weightShard =node.numShards() - balancer.avgShardsPerNode();
final float weightIndex =node.numShards(index) - balancer.avgShardsPerNode(index);
final float ingestLoad = (float) (node.writeLoad() - balancer.avgWriteLoadPerNode());
final float diskUsage = (float) (node.diskUsageInBytes() - balancer.avgDiskUsageInBytesPerNode());
return theta0 * weightShard + theta1 * weightIndex + theta2 * ingestLoad + theta3 * diskUsage;
}
为什么会出现机器配置一致的情况下,hot均衡正常, cold分片分配不平衡的情况呢?
# Elastic cluster is getting overloaded by incorrect shard allocation - #2 by DavidTurner - Elasticsearch - Discuss the Elastic Stack
分片都被认为是等效的,并且仅通过分片数量在节点之间进行平衡, 从 8.6 开始会考虑分片大小,避免较大的分片集中在特定节点上,这将通过分散高流量数据流的分片来减少索引热点,从而改善热节点之间 CPU 使用的平衡。
较大的分片集中在新加的节点上(cold节点)
1. 仅通过分片数量在节点之间进行平衡
2. 如果集群新加的节点保持空闲状态,集群将比较新的分片分配到新的节点
3. 较大的分片容易集中在新加的节点上
综合上述原因:
原因是cold节点保留数据较长, 节点较少,导致每个节点分片较多,且大分片索引每个节点都有260个,计算权重得分绝对差就比较大,受上述条件影响较大,导致新加cold节点大分片索引分片比较集中,目前oa-cold-130机器总分片有2976,大分片索引bro-conn 有1814个
hot保留5天数据,hot节点72个,每个节点分片70个左右,扩容5台机器部署20个hot节点,每台7T磁盘,扩容后每个节点分片在54个左右
扩容前:conn索引72分片 * 5天 * (1+1)副本 / 72个hot = 每个节点 10分片
conn索引72分片 * 5天 = 360分片 * 单个分片按最大的60G计算* (1+1)副本 ≈ 44T
5台机器 * 每台机器7T磁盘 * 磁盘的水位线配置在85% ≈ 30T
cold保留55天数据,cold节点32个,每个节点分片1400个左右,扩容2台机器部署8个cold节点,每台144T磁盘,扩容后每个节点分片在1100个左右
扩容前: conn索引72分片* 55天 * (1+1)副本 / 30个cold ≈ 每个节点264 分片
conn索引72分片 * 55天 = 3960分片 * 单个分片按最大的60G计算* (1+1)副本 ≈ 464T
2台机器 * 每台机器144T磁盘 * 磁盘的水位线配置在85% ≈ 244T
怎么样才能将较大的分片迁移出来呢,添加节点怎么避免这种情况呢
采用下列三种方式手动重新平衡,添加节点时需要将大的索引过滤排除分配到新添加的节点中,先将一些较小的索引分片自动分配到新节点中,避免出现这种情况
强制手动重新平衡
方式1 :设置单个索引分配给单个节点的最大分片--- 临时配置用完即删
bro-conn 72分片 *(1+1)副本/ 32个cold节点 ≈5 ,考虑到集群稳定性,可以设置6~8,(见图:较大的分片集中在新加的节点上(cold节点))
添加
PUT bro-conn-*/_settings
{
"index.routing.allocation.total_shards_per_node": 7
}
删除
PUT bro-conn-*/_settings
{
"index.routing.allocation.total_shards_per_node": null
}
方式2:手动更改集群中各个分片的分配-精确到分片
#https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-reroute.html
POST /_cluster/reroute?metric=none
{
"commands": [
{
"move": {
"index": "test", "shard": 0,
"from_node": "node1", "to_node": "node2"
}
}
]
}
方式3: 索引级分片分配过滤
#https://www.elastic.co/guide/en/elasticsearch/reference/7.17/shard-allocation-filtering.html
PUT index-name-*/_settings
{
"index.routing.allocation.exclude._ip": "10.84.246.130,10.84.246.60"
}
注意,涉及的索引较多 会引发集群负载较高,比如迁入迁出的机器的带宽和load会上升
参考文档:
Suboptimal shard allocation with imbalanced shards
Elastic cluster is getting overloaded by incorrect shard allocation