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

适用版本: 8.8-8.9

1. 错误异常的基本描述 #

A primary endpoint is required when setting a secondary endpoint 是 Elasticsearch 在配置 Azure Blob Storage 快照仓库(snapshot repository)时抛出的配置错误。当你为 Azure 仓库客户端设置 secondary_endpoint(辅助终结点)但没有同时设置 endpoint(主终结点)时,就会触发此错误。Azure 的 RA-GRS(读访问异地冗余存储)功能支持主辅终结点,但辅助终结点必须依附于主终结点存在,不能单独定义。

常见现象 #

  • Elasticsearch 返回 HTTP 400 Bad Request 状态码,响应体中包含 SettingsException
  • 创建或更新 Azure 快照仓库的请求(PUT _snapshot/<repo_name>)失败。
  • 在 Elasticsearch 服务端日志中会记录详细的异常信息。
  • 如果是通过自动化脚本或 Terraform 配置仓库,会在客户端收到异常响应。
  • 仓库无法创建,导致后续的快照备份任务失败。

典型报错与异常栈 #

该异常的典型日志形态如下:

SettingsException: A primary endpoint is required when setting a secondary endpoint
    at org.elasticsearch.repositories.azure.AzureStorageSettings.laod(AzureStorageSettings.java:...)
    at org.elasticsearch.repositories.azure.AzureRepositoryPlugin.lambda$getClientSettings$0(AzureRepositoryPlugin.java:...)
    at org.elasticsearch.common.settings.Setting$GroupSetting.lambda$getConcreteSetting$0(Setting.java:...)

通过 API 请求的响应通常如下:

{
  "error": {
    "root_cause": [
      {
        "type": "settings_exception",
        "reason": "A primary endpoint is required when setting a secondary endpoint"
      }
    ],
    "type": "settings_exception",
    "reason": "A primary endpoint is required when setting a secondary endpoint"
  },
  "status": 400
}

2. 为什么会发生这个错误 #

Elasticsearch 的 Azure Blob Storage 仓库插件支持 Azure 的 RA-GRS 冗余策略,允许配置主终结点(endpoint)和辅助终结点(secondary_endpoint)。源码中的逻辑是:

if (hasEndpoint == false && hasSecondaryEndpoint) {
    throw new SettingsException("A primary endpoint is required when setting a secondary endpoint");
}

这意味着 secondary_endpoint 只是 endpoint 的补充,不能单独定义。常见原因包括:

  • 只配置了辅助终结点:运维人员只填写了 secondary_endpoint,忘记了配置 endpoint
  • 从标准 endpoint 迁移时遗漏:从标准 Azure endpoint 规则改为显式 endpoint 时,只迁移了 secondary_endpoint
  • 模板变量缺失:使用 Terraform 或 Ansible 等工具时,模板变量缺失导致 endpoint 渲染后为空。
  • 配置文件复制错误:从其他仓库配置复制时,可能只复制了部分配置。
  • 环境差异:在不同环境(开发、测试、生产)之间迁移配置时,遗漏了 endpoint

3. 如何排查和解决这个异常和解决这个异常 #

排查步骤 #

建议按以下顺序进行排查:

第一步:查看完整的错误响应和仓库配置 #

# 重现错误并查看完整响应
curl -X PUT "localhost:9200/_snapshot/my_azure_repo" -H 'Content-Type: application/json' -d @repo.json 2>&1 | jq .

# 查看 Elasticsearch 日志中的详细错误
tail -n 200 /var/log/elasticsearch/elasticsearch.log | grep -A 20 "A primary endpoint is required"

第二步:检查仓库配置中的 endpoint 设置 #

# 查看现有仓库配置
curl -X GET "localhost:9200/_snapshot/my_azure_repo?pretty"

# 检查是否配置了 secondary_endpoint 但缺少 endpoint
cat repo.json | jq '.settings'

第三步:验证正确的 Azure 仓库配置 #

// 错误示例:只有 secondary_endpoint
{
  "type": "azure",
  "settings": {
    "secondary_endpoint": "https://mystorage-secondary.blob.core.windows.net",
    // 错误:缺少 endpoint
  }
}

// 正确示例:同时配置 endpoint 和 secondary_endpoint
{
  "type": "azure",
  "settings": {
    "endpoint": "https://mystorage.blob.core.windows.net",
    "secondary_endpoint": "https://mystorage-secondary.blob.core.windows.net"
  }
}

// 正确示例:只使用主 endpoint(如果不需要辅助终结点)
{
  "type": "azure",
  "settings": {
    "endpoint": "https://mystorage.blob.core.windows.net"
    // 不配置 secondary_endpoint
  }
}

第四步:在测试环境验证 #

# 在测试环境创建 Azure 仓库
curl -X PUT "localhost:9200/_snapshot/test_azure_repo" -H 'Content-Type: application/json' -d '
{
  "type": "azure",
  "settings": {
    "endpoint": "https://mystorage.blob.core.windows.net",
    "secondary_endpoint": "https://mystorage-secondary.blob.core.windows.net",
    "container": "my-container",
    "base_path": "/backups"
  }
}'

# 验证仓库是否工作
curl -X PUT "localhost:9200/_snapshot/test_azure_repo/_verify?pretty"

排查时需要注意的问题 #

  • 检查所有 Azure 客户端配置:如果定义了多个 Azure 客户端,确保出错的那个配置正确。
  • 注意 endpoint_suffix:如果配置了 endpoint_suffix,通常不应再手工设置 secondary_endpoint,两者可能冲突。
  • 确认仓库类型:确保你配置的是 Azure Blob Storage 仓库,不是 S3 或 GCS。
  • 区分环境:不同环境(开发、测试、生产)的 endpoint 可能不同,确认使用的是正确的环境配置。

4. 如何解决这个错误 #

常用修复思路 #

方案一:补齐 primary endpoint(推荐) #

# 更新仓库配置,添加缺失的 endpoint
curl -X PUT "localhost:9200/_snapshot/my_azure_repo" -H 'Content-Type: application/json' -d '
{
  "type": "azure",
  "settings": {
    "endpoint": "https://mystorage.blob.core.windows.net",
    "secondary_endpoint": "https://mystorage-secondary.blob.core.windows.net",
    "container": "my-container",
    "base_path": "/backups"
  }
}'

方案二:如果不需要辅助终结点,直接移除 secondary_endpoint #

# 如果不需要 RA-GRS 的辅助终结点,移除它
curl -X PUT "localhost:9200/_snapshot/my_azure_repo" -H 'Content-Type: application/json' -d '
{
  "type": "azure",
  "settings": {
    "endpoint": "https://mystorage.blob.core.windows.net",
    "container": "my-container",
    "base_path": "/backups"
  }
}'

方案三:使用 endpoint_suffix 代替手工 endpoint #

# 使用 Azure 标准 endpoint suffix,不需要手工设置 endpoint
curl -X PUT "localhost:9200/_snapshot/my_azure_repo" -H 'Content-Type: application/json' -d '
{
  "type": "azure",
  "settings": {
    "account": "mystorage",
    "endpoint_suffix": "core.windows.net",
    "container": "my-container",
    "base_path": "/backups"
  }
}'

方案四:在 Terraform 或 Ansible 中修复 #

# Terraform 示例:确保 endpoint 和 secondary_endpoint 同时存在
resource "elasticsearch_snapshot_repository" "azure_repo" {
  name = "my_azure_repo"
  type = "azure"
  
  settings = {
    endpoint            = "https://mystorage.blob.core.windows.net"
    secondary_endpoint  = "https://mystorage-secondary.blob.core.windows.net"
    container           = "my-container"
    base_path           = "/backups"
  }
}

后续注意事项与推荐建议 #

  • 建立仓库配置规范:为团队制定 Azure 仓库配置的规范,明确 endpoint 是必填项,secondary_endpoint 是选填项且依赖于 endpoint
  • 在 CI/CD 中加入校验:对于仓库配置,在部署前进行结构校验,确保 secondary_endpoint 出现时一定有对应的 endpoint
  • 使用变量管理配置:在 Terraform、Ansible 或 Helm 中,使用变量来管理 endpoint 配置,避免硬编码。
  • 监控仓库状态:通过 Elasticsearch 的仓库验证 API 和监控工具,及时发现配置问题。
  • 参考 Azure 文档:在配置 Azure 仓库前,先查阅 Azure 官方文档,确认 endpoint 格式和冗余策略。

借助 INFINI 产品提升排障效率 #

  • INFINI Console 提供快照仓库的可视化管理界面,可以直观地查看、编辑和验证 Azure 仓库配置。通过 Console 的仓库管理功能,可以快速发现缺少 endpoint 的配置,并直接编辑修复。

  • INFINI Gateway 可以作为 Elasticsearch API 的代理层,在仓库创建请求到达 Elasticsearch 之前进行拦截和检查。Gateway 可以自动检测缺少 endpoint 的配置,并根据预定义的策略进行处理(如自动补齐、拒绝请求、告警通知等)。

  • 对于依赖 Azure Blob Storage 进行快照备份的团队,建议结合 INFINI Console 的仓库管理功能和 INFINI Gateway 的请求治理能力,建立从仓库配置、验证、监控到告警的完整流程,减少因配置错误导致的备份失败。

5. 小结 #

A primary endpoint is required when setting a secondary endpoint 是一个典型的 Azure 仓库配置错误,根源在于 secondary_endpoint 不能脱离 endpoint 单独存在。虽然报错信息直接指向配置关系不完整,但解决思路很简单:要么补齐 endpoint,要么移除 secondary_endpoint

在实际工作中,为避免此类问题,建议在开发阶段使用 INFINI Console 的可视化工具来构造和验证仓库配置,在 CI/CD 流程中加入配置校验,并使用 INFINI Gateway 作为防护层来拦截错误的配置请求。

相关错误 #

参考文档 #

附:日志上下文 #

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

if (hasEndpointSuffix && hasSecondaryEndpoint) {
    throw new SettingsException("Both an endpoint suffix as well as a secondary endpoint were set");
} else if (hasEndpoint == false && hasSecondaryEndpoint) {
    throw new SettingsException("A primary endpoint is required when setting a secondary endpoint");
}
if (hasEndpointSuffix) {
    connectionStringBuilder.append(";EndpointSuffix=").append(endpointSuffix);
}