适用版本: 6.8-7.17(含 X-Pack Security 开启场景)
1. 错误说明 #
at least one primary shard for the security index is unavailable 表示 Elasticsearch 的 安全索引(.security 或 .security-7) 至少有一个主分片处于不可用状态,导致安全模块无法正常读取或写入安全配置数据。
该错误通常发生在启用 X-Pack Security 的集群中,当 .security 索引的主分片未正常分配或节点不可达时触发。由于安全索引存储了用户、角色、角色映射等关键认证信息,该问题会直接影响集群的认证与授权功能。
常见现象 #
- 集群状态显示为
red,.security索引健康状态异常。 - 执行用户管理、角色管理相关 API(如
PUT /_security/user/、PUT /_security/role/)时返回500或503错误。 - 已有用户认证失败,或新建用户无法生效。
- Kibana 无法启动或反复报认证错误,日志中出现
unable to load security index相关信息。 - 节点日志中出现如下异常信息:
IllegalStateException: at least one primary shard for the security index is unavailable
Caused by: UnavailableShardsException[at least one primary shard for the security index is unavailable]
at org.elasticsearch.xpack.security.SecurityIndexManager$SecurityIndexState.getUnavailableReason(SecurityIndexManager.java)
典型报错与异常栈 #
[2024-01-15T10:23:45,123][WARN ][o.e.x.s.SecurityIndexManager] [node-1] Security index is not available
java.lang.IllegalStateException: at least one primary shard for the security index is unavailable
at org.elasticsearch.xpack.security.SecurityIndexManager.getUnavailableReason(SecurityIndexManager.java:XXX)
at org.elasticsearch.xpack.security.SecurityIndexManager.isAvailable(SecurityIndexManager.java:XXX)
2. 原因分析 #
.security 索引是 Elasticsearch 安全模块的核心索引,默认有 1 个主分片。当该主分片无法分配或所在节点不可用时,就会触发此异常。
常见原因 #
- 节点宕机或下线:持有
.security索引主分片的节点离开集群,且未触发分片重分配。 - 磁盘空间不足:
.security索引所在节点的磁盘使用率达到cluster.routing.allocation.disk.watermark.flood_stage阈值,分片被强制迁移或置为只读。 - 分片分配异常:分片分配规则(如
allocation awareness、exclude设置)阻止了.security主分片分配到任何可用节点。 - 索引被意外关闭或删除:
.security索引被人为执行了POST /.security/_close或误删除,导致安全配置无法加载。 - 集群恢复期间:节点刚重启,
.security索引的主分片尚未完成分配,此时调用安全相关 API 会触发该错误。 - 版本升级后兼容问题:跨大版本升级后,
.security索引的 mapping 或数据结构发生变化,旧分片无法正常加载。
诊断思路 #
先确认 .security 索引的实际状态,再判断是分配问题、节点问题还是数据问题:
# 查看 .security 索引的健康状态
GET /_cat/indices/.security*?v&h=index,health,status,pri,rep,docs.count,store.size
# 查看 .security 索引的分片分配详情
GET /_cat/shards/.security*?v&h=index,shard,prirep,state,docs,store,node
# 查看未分配分片的详细原因
GET /_cluster/allocation/explain
3. 解决方案 #
步骤一:确认 .security 索引状态 #
# 查看索引是否存在及其基本信息
GET /_cat/indices/.security*?v
# 查看索引详细设置
GET /.security*/_settings?pretty
如果索引不存在,说明 .security 索引已被删除,需参考步骤四处理。
步骤二:检查分片分配情况 #
# 查看分片分配失败的具体原因
GET /_cluster/allocation/explain?pretty
{
"index": ".security-7",
"shard": 0,
"primary": true
}
常见分配失败原因及对应处理:
NODE_LEFT:持有主分片的节点已下线,等待节点重新加入或手动触发分片重分配。DISK_WATERMARK_EXCEEDED:磁盘空间不足,清理磁盘或调整水位线设置。ALLOCATION_FAILED:分片分配失败,尝试手动分配。
步骤三:手动触发分片分配 #
如果分片因临时故障未自动分配,可尝试手动分配:
# 查看集群中可用的节点
GET /_cat/nodes?v&h=name,node.role,disk.avail,heap.percent
# 若节点正常但分片未分配,尝试手动分配(指定目标节点 ID)
POST /_cluster/reroute
{
"commands": [
{
"allocate_empty_primary": {
"index": ".security-7",
"shard": 0,
"node": "target-node-name",
"accept_data_loss": true
}
}
]
}
注意:
allocate_empty_primary会丢失该分片上的数据,仅在确认数据可丢失或索引需要重建时使用。对于.security索引,通常建议优先尝试从快照恢复或重建索引。
步骤四:处理 .security 索引被删除的情况 #
如果 .security 索引已被删除,需要重建安全索引并重新配置用户和角色:
# 1. 停止所有写入安全配置的请求
# 2. 删除残留的索引(如果存在但状态异常)
DELETE /.security*
# 3. 重启集群节点或等待安全模块自动重建 .security 索引
# 安全模块会在下次调用安全 API 时自动尝试重建索引
# 4. 验证索引是否自动重建
GET /_cat/indices/.security*?v
# 5. 重新创建内置用户和角色(参考原配置)
# 如使用内置用户,可通过自动引导流程重新初始化
步骤五:处理磁盘空间不足问题 #
# 查看磁盘使用情况
GET /_cat/allocation?v&h=node,shard,disk.indices,disk.used,disk.avail,disk.total,disk.percent
# 临时调高磁盘水位线(仅用于紧急恢复,后续需清理磁盘)
PUT /_cluster/settings
{
"transient": {
"cluster.routing.allocation.disk.watermark.flood_stage": "95%",
"cluster.routing.allocation.disk.watermark.high": "90%",
"cluster.routing.allocation.disk.watermark.low": "85%"
}
}
# 清理磁盘后,恢复默认设置
PUT /_cluster/settings
{
"transient": {
"cluster.routing.allocation.disk.watermark.flood_stage": null,
"cluster.routing.allocation.disk.watermark.high": null,
"cluster.routing.allocation.disk.watermark.low": null
}
}
步骤六:等待集群恢复 #
如果错误发生在节点重启或集群恢复期间,通常是暂时性错误,等待分片自动分配完成即可:
# 持续观察集群健康状态
GET /_cluster/health?wait_for_status=yellow&timeout=30s
# 观察 .security 索引分片分配进度
GET /_cat/shards/.security*?v
4. 预防措施 #
- 确保
.security索引有副本:默认.security索引只有 1 个主分片、0 个副本,建议设置 1 个副本以提高可用性。
# 为 .security 索引设置副本数(需在索引创建时或动态更新 settings)
PUT /.security-7/_settings
{
"index.number_of_replicas": 1
}
- 监控集群健康状态:配置对
red状态和.security索引健康度的告警,及时发现分片不可用问题。
# 定期检查的示例命令
GET /_cluster/health?filter_path=status,unassigned_shards,initializing_shards
合理配置磁盘水位线:确保磁盘使用率不超过
flood_stage阈值,避免分片被强制下线。避免在生产环境手动操作
.security索引:不要对.security索引执行close、delete等高风险操作。定期备份安全配置:使用快照功能定期备份集群状态,包括
.security索引数据,以便在意外删除后快速恢复。
# 创建包含安全索引的快照
PUT /_snapshot/my_backup/snapshot_20240601
{
"indices": ".security*",
"ignore_unavailable": true
}
- 控制节点下线顺序:在维护或升级时,先确保
.security索引的主分片已迁移到其他节点,再下线目标节点。
借助 INFINI 产品提升排障效率 #
- INFINI Console 适合查看集群健康度、节点指标、索引状态、分片分配详情和错误趋势,帮助快速判断
.security索引异常是节点问题、磁盘问题还是配置问题。 - INFINI Gateway 适合部署在 Elasticsearch 前面做请求观测、限流和流量治理,避免因大量无效重试导致安全模块压力增大。
- 建议将
.security索引健康状态、分片分配失败事件和磁盘使用率统一接入监控面板,在问题影响用户认证前及时预警。
5. 小结 #
at least one primary shard for the security index is unavailable 错误的根本原因通常是 .security 索引的主分片未正常分配,可能由节点下线、磁盘空间不足或分片分配规则异常引起。由于安全索引关系到整个集群的认证与授权功能,出现该问题时应优先恢复 .security 索引的可用性,再排查深层原因。
通过为 .security 索引设置副本、监控集群健康状态、定期备份安全配置,可以有效降低该问题发生的概率。
相关错误 #
- index-not-found-exception:索引不存在异常
- unavailable-shards-exception:分片不可用异常
- red-status-cluster:集群 Red 状态
- disk-flood-stage:磁盘水位线超限
- illegal-state-exception:非法状态异常
附:日志上下文 #
下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:
if (localState.indexAvailable) {
throw new IllegalStateException("caller must make sure to use a frozen state and check indexAvailable");
}
if (localState.indexExists) {
return new UnavailableShardsException(null, "at least one primary shard for the security index is unavailable");
} else {
return new IndexNotFoundException(SECURITY_INDEX_NAME);
}





