📣 极限科技诚招搜索运维工程师(Elasticsearch/Easysearch)- 全职/北京 👉 : 立即申请加入

适用版本: 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/)时返回 500503 错误。
  • 已有用户认证失败,或新建用户无法生效。
  • 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 awarenessexclude 设置)阻止了 .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 索引执行 closedelete 等高风险操作。

  • 定期备份安全配置:使用快照功能定期备份集群状态,包括 .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 索引设置副本、监控集群健康状态、定期备份安全配置,可以有效降低该问题发生的概率。

相关错误 #

附:日志上下文 #

下面保留当前页面中的源码或日志片段,便于继续结合异常调用栈定位问题:

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);
}