背景:管理过数百个集群,使用方式千变万化,出现过各种各样的shards分配不了的情况,趁此假期做一些unassigned处理方案的总结;
先总结一下:所有的unassigned都可以通过explain API查到原因和处理方案
GET /_cluster/allocation/explain
{
"index":"index_name",
"shard":0,
"primary":false
}
先找到所有的unassigned分片:
curl -XGET localhost:9200/_cat/shards?h=index,shard,prirep,state,unassigned.reason| grep UNASSIGNED
出现unassigned的主要原因:
-
nodes 数小于分片副本数
-
节点失联(node_left)
-
node_permission设置不合理
-
rebalance过程中的yellow(一般不需要处理,只需要查清楚rebalance的原因)
-
磁盘空间不足(空间不足只能扩容或者删除旧的index,下面不做详细介绍)
-
节点暂时出现问题,等几分钟后又好了,这时候retry 5 次已经结束了,unassigned的分片已经不能分配了(此时可以通过retry API 进行重试,概率较小,直接贴出解决方案,下面不详细介绍了)
数据不重要可以delete:
如果数据不重要,可以直接delete index;
或者将副本数设置为0,再设置回原配置(yellow的情况)
修改副本分片API:
PUT movie/_settings
{
"index" : {
"number_of_replicas" : 1
}
}
删除index API:
delete index_name
设置不合理处理方案:
1.node数小于副本分片数
直接修改副本分片数API:
PUT movie/_settings
{
"index" : {
"number_of_replicas" : 1
}
}
如果发现是有某些节点被exclude导致节点不够,在确认node正常后,可以将exclude去掉:
PUT _cluster/settings
{
"transient" : {
"cluster.routing.allocation.exclude._ip" : null
}
}
2.设置索引在节点上最多容纳的分片不合理:
可增大这个参数:
PUT /index_name/_settings
{
"index.routing.allocation.total_shards_per_node":"3"
}
这个参数设置不合理可能会造成如下bug:
暂时没有正常的解决方案:retry也不会生效,只能改大total_shards_per_node参数,原因是es的allocation是通过分配器和17个决策器(责任链模式)进行分配的,只要节点符合决策条件就会分配,如上图的情况,只要前五个节点符合所有决策器条件就会直接分配,等轮到第6个shard开始分配的时候,发现不符合条件了,前五个shard也不会去重新分配,就只能让第6个shard变成unassigned状态了;
补充retry API:防止修改配置不生效
POST /_cluster/reroute?retry_failed=true
如果由于故障(异常)导致的分配不了的解决方案:
1.首先是解决故障,比如看到日志发现是分词器找不到导致不能正常运行,那么首先将分词器装好,然后再解决unassigned的问题,正常情况ES会自动分配,但是由于出现故障,导致分配分片的5次(默认)重试机会用完了,所以不会再自动分配,所以需要在故障解决完成之后进行retry;
POST /_cluster/reroute?retry_failed=true
处理节点离开集群后主分片不能分配的问题
节点离开再回来这种问题不是很好处理,可能性很多,一般的解决方案如下:
1.尝试进行retry
POST /_cluster/reroute?retry_failed=true
2.如果是自己操作的,设置延迟allocation时间较大,则不需要处理,等待allocation副本分配即可,或者减小延迟时间
(注:延迟分配是为了防止节点掉出去后立刻进行副本分片分配,比如node1掉出去了,shard马上开始重新分配,30s后node1又回来了,于是发现node1上的shard无效了,于是干掉node1上的shard,然后又重新分配一次,这样大大的消耗了性能)
修改延迟分配的时间API:
PUT */_settings
{
"settings": {
"index": {
"unassigned": {
"node_left": {
"delayed_timeout": "1m"
}
}
}
}
}
3.手动分配分片
如果到了需要手动分配这一步,说明故障时间比较长,或者故障节点过多,如果是red,那么这时候数据丢失已经无法避免了;
red情况下手动分配主分配操作流程:
1.先查询未分配的主分片原来是在哪个节点上
GET /order_orderlist/_shard_stores
2.将主分片分配(只丢失部分数据)
POST _cluster/reroute
{
"commands": [
{
"allocate_stale_primary": {
"index": "index_name",
"shard": 4,
"node": "node1",
"accept_data_loss" : true
}
}
]
}
3.如果数据不重要,可以不用放到原来的节点上,直接新建一个空分片替代
POST _cluster/reroute
{
"commands": [
{
"allocate_empty_primary": {
"index": "test_11",
"shard": 2,
"node": "node0",
"accept_data_loss" : true
}
}
]
}
yellow情况下手动分配副本分片操作:
POST /_cluster/reroute
{
"commands" :[
{
"allocate_replica" :
{
"index" : "index_name",
"shard" : 0,
"node": "node1"
}
}
]
}
补充:不是所有的unassigned都是不正常的,集群启动、扩容的时候就会有短暂的yellow,甚至Shard allocation过程由于延迟机制的设置,也会出现正常的yellow情况(当然这种也是不正常的,只是不是shard的不正常,而是集群层面的不正常,比如压力过大等情况)