还原快照编辑

本指南介绍如何还原快照。快照是将数据副本存储在集群外部的一种便捷方式。您可以还原快照以在删除或硬件故障后恢复索引和数据流。您还可以使用快照在集群之间传输数据。

在本指南中,您将学习如何

  • 获取可用快照的列表
  • 从快照还原索引或数据流
  • 还原功能状态
  • 还原整个集群
  • 监控还原操作
  • 取消正在进行的还原

本指南还提供有关 还原到另一个集群排查常见的还原错误 的提示。

先决条件编辑

  • 要使用 Kibana 的 快照和还原 功能,您必须具有以下权限

    • 集群权限: monitormanage_slmcluster:admin/snapshotcluster:admin/repository
    • 索引权限: monitor 索引上的 all
  • 您只能将快照还原到具有已选举的 主节点 的正在运行的集群。快照的存储库必须 注册 并可供集群使用。
  • 快照和集群版本必须兼容。请参阅 快照兼容性
  • 要还原快照,集群的全局元数据必须可写。确保没有 集群阻止 阻止写入。还原操作会忽略 索引阻止
  • 在还原数据流之前,请确保集群包含一个 匹配的索引模板,并且启用了数据流。要检查,请使用 Kibana 的 索引管理 功能或 获取索引模板 API

    response = client.indices.get_index_template(
      name: '*',
      filter_path: 'index_templates.name,index_templates.index_template.index_patterns,index_templates.index_template.data_stream'
    )
    puts response
    GET _index_template/*?filter_path=index_templates.name,index_templates.index_template.index_patterns,index_templates.index_template.data_stream

    如果不存在此类模板,您可以 创建一个还原包含一个的集群状态。如果没有匹配的索引模板,数据流将无法滚动或创建支持索引。

  • 如果您的快照包含来自 App Search 或 Workplace Search 的数据,请确保在还原快照之前已还原 企业搜索加密密钥

注意事项编辑

从快照还原数据时,请牢记以下几点

  • 如果还原数据流,您也会还原其支持索引。
  • 您只能还原已 关闭 的现有索引,并且快照中的索引具有相同数量的主分片。
  • 您无法还原现有的打开的索引。这包括数据流的支持索引。
  • 还原操作会自动打开已还原的索引,包括支持索引。
  • 您只能从数据流还原特定的支持索引。但是,还原操作不会将已还原的支持索引添加到任何现有的数据流中。

获取可用快照的列表编辑

要查看 Kibana 中的可用快照列表,请转到主菜单并单击 堆栈管理 > 快照和还原

您还可以使用 获取存储库 API获取快照 API 来查找可用于还原的快照。首先,使用获取存储库 API 获取已注册的快照存储库列表。

response = client.snapshot.get_repository
puts response
GET _snapshot

然后使用获取快照 API 获取特定存储库中的快照列表。这还会返回每个快照的内容。

response = client.snapshot.get(
  repository: 'my_repository',
  snapshot: '*',
  verbose: false
)
puts response
GET _snapshot/my_repository/*?verbose=false

还原索引或数据流编辑

您可以使用 Kibana 的 快照和还原 功能或 还原快照 API 还原快照。

默认情况下,还原请求尝试还原快照中的所有常规索引和常规数据流。在大多数情况下,您只需要从快照还原特定的索引或数据流。但是,您无法还原现有的打开的索引。

如果您将数据还原到预先存在的集群,请使用以下方法之一来避免与现有索引和数据流发生冲突

删除并还原编辑

避免冲突的最简单方法是在还原之前删除现有的索引或数据流。为了防止意外重新创建索引或数据流,我们建议您暂时停止所有索引操作,直到还原操作完成。

如果 action.destructive_requires_name 集群设置是 false,请勿使用 删除索引 API 来定位 *.* 通配符模式。如果您使用 Elasticsearch 的安全功能,这将删除身份验证所需的系统索引。相反,请定位 *,-.* 通配符模式以排除这些系统索引和其他以点 (.) 开头的索引名称。

response = client.indices.delete(
  index: 'my-index'
)
puts response

response = client.indices.delete_data_stream(
  name: 'logs-my_app-default'
)
puts response
# Delete an index
DELETE my-index

# Delete a data stream
DELETE _data_stream/logs-my_app-default

在还原请求中,明确指定要还原的任何索引和数据流。

response = client.snapshot.restore(
  repository: 'my_repository',
  snapshot: 'my_snapshot_2099.05.06',
  body: {
    indices: 'my-index,logs-my_app-default'
  }
)
puts response
POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore
{
  "indices": "my-index,logs-my_app-default"
}

还原时重命名编辑

如果您想避免删除现有数据,您可以改为重命名要还原的索引和数据流。您通常使用此方法将现有数据与快照中的历史数据进行比较。例如,您可以使用此方法在意外更新或删除后查看文档。

在开始之前,请确保集群有足够的容量来容纳现有数据和还原的数据。

以下还原快照 API 请求会在还原的任何索引或数据流的名称前添加 restored-

response = client.snapshot.restore(
  repository: 'my_repository',
  snapshot: 'my_snapshot_2099.05.06',
  body: {
    indices: 'my-index,logs-my_app-default',
    rename_pattern: '(.+)',
    rename_replacement: 'restored-$1'
  }
)
puts response
POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore
{
  "indices": "my-index,logs-my_app-default",
  "rename_pattern": "(.+)",
  "rename_replacement": "restored-$1"
}

如果重命名选项生成两个或多个具有相同名称的索引或数据流,则还原操作将失败。

如果重命名数据流,其支持索引也会被重命名。例如,如果您将 logs-my_app-default 数据流重命名为 restored-logs-my_app-default,则支持索引 .ds-logs-my_app-default-2099.03.09-000005 将被重命名为 .ds-restored-logs-my_app-default-2099.03.09-000005

还原操作完成后,您可以比较原始数据和还原的数据。如果您不再需要原始索引或数据流,您可以将其删除并使用 重新索引 来重命名还原的索引或数据流。

response = client.indices.delete(
  index: 'my-index'
)
puts response

response = client.reindex(
  body: {
    source: {
      index: 'restored-my-index'
    },
    dest: {
      index: 'my-index'
    }
  }
)
puts response

response = client.indices.delete_data_stream(
  name: 'logs-my_app-default'
)
puts response

response = client.reindex(
  body: {
    source: {
      index: 'restored-logs-my_app-default'
    },
    dest: {
      index: 'logs-my_app-default',
      op_type: 'create'
    }
  }
)
puts response
# Delete the original index
DELETE my-index

# Reindex the restored index to rename it
POST _reindex
{
  "source": {
    "index": "restored-my-index"
  },
  "dest": {
    "index": "my-index"
  }
}

# Delete the original data stream
DELETE _data_stream/logs-my_app-default

# Reindex the restored data stream to rename it
POST _reindex
{
  "source": {
    "index": "restored-logs-my_app-default"
  },
  "dest": {
    "index": "logs-my_app-default",
    "op_type": "create"
  }
}

还原功能状态编辑

您可以还原 功能状态 以从快照恢复系统索引、系统数据流和功能的其他配置数据。

如果您还原快照的集群状态,则操作默认情况下会还原快照中的所有功能状态。类似地,如果您不还原快照的集群状态,则操作默认情况下不会还原任何功能状态。您还可以选择仅从快照还原特定的功能状态,而不管集群状态如何。

要查看快照的功能状态,请使用获取快照 API。

response = client.snapshot.get(
  repository: 'my_repository',
  snapshot: 'my_snapshot_2099.05.06'
)
puts response
GET _snapshot/my_repository/my_snapshot_2099.05.06

响应的 feature_states 属性包含快照中的功能列表以及每个功能的索引。

要从快照还原特定的功能状态,请在还原快照 API 的 feature_states 参数中指定响应中的 feature_name

还原功能状态时,Elasticsearch 会关闭并覆盖功能的现有索引。

还原 security 功能状态会覆盖用于身份验证的系统索引。如果您使用 Elasticsearch Service,请确保在还原 security 功能状态之前可以访问 Elasticsearch Service 控制台。如果您在自己的硬件上运行 Elasticsearch,请 在文件领域中创建超级用户 以确保您仍然可以访问您的集群。

response = client.snapshot.restore(
  repository: 'my_repository',
  snapshot: 'my_snapshot_2099.05.06',
  body: {
    feature_states: [
      'geoip'
    ],
    include_global_state: false,
    indices: '-*'
  }
)
puts response
POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore
{
  "feature_states": [ "geoip" ],
  "include_global_state": false,    
  "indices": "-*"                   
}

从还原操作中排除集群状态。

从恢复操作中排除快照中的其他索引和数据流。

恢复整个集群编辑

在某些情况下,您需要从快照中恢复整个集群,包括集群状态和所有功能状态。这些情况应该很少见,例如在灾难性故障的情况下。

恢复整个集群涉及删除重要的系统索引,包括用于身份验证的索引。请考虑是否可以恢复特定索引或数据流。

如果您要恢复到不同的集群,请在开始之前查看恢复到不同的集群

  1. 如果您备份了集群的配置文件,您可以将它们恢复到每个节点。此步骤是可选的,需要全集群重启

    关闭节点后,将备份的配置文件复制到节点的$ES_PATH_CONF目录。在重启节点之前,请确保elasticsearch.yml包含适当的节点角色、节点名称和其他特定于节点的设置。

    如果您选择执行此步骤,则必须在集群中的每个节点上重复此过程。

  2. 暂时停止索引并关闭以下功能

    • GeoIP 数据库下载器和 ILM 历史存储

      response = client.cluster.put_settings(
        body: {
          persistent: {
            'ingest.geoip.downloader.enabled' => false,
            'indices.lifecycle.history_index_enabled' => false
          }
        }
      )
      puts response
      PUT _cluster/settings
      {
        "persistent": {
          "ingest.geoip.downloader.enabled": false,
          "indices.lifecycle.history_index_enabled": false
        }
      }
    • ILM

      response = client.ilm.stop
      puts response
      POST _ilm/stop
    • 机器学习

      resp = client.ml.set_upgrade_mode(
          enabled="true",
      )
      print(resp)
      response = client.ml.set_upgrade_mode(
        enabled: true
      )
      puts response
      POST _ml/set_upgrade_mode?enabled=true
    • 监控

      response = client.cluster.put_settings(
        body: {
          persistent: {
            'xpack.monitoring.collection.enabled' => false
          }
        }
      )
      puts response
      PUT _cluster/settings
      {
        "persistent": {
          "xpack.monitoring.collection.enabled": false
        }
      }
    • Watcher

      response = client.watcher.stop
      puts response
      POST _watcher/_stop
    • 通用分析

      检查通用分析索引模板管理是否已启用

      response = client.cluster.get_settings(
        filter_path: '**.xpack.profiling.templates.enabled',
        include_defaults: true
      )
      puts response
      GET /_cluster/settings?filter_path=**.xpack.profiling.templates.enabled&include_defaults=true

      如果值为true,请禁用通用分析索引模板管理

      response = client.cluster.put_settings(
        body: {
          persistent: {
            'xpack.profiling.templates.enabled' => false
          }
        }
      )
      puts response
      PUT _cluster/settings
      {
        "persistent": {
          "xpack.profiling.templates.enabled": false
        }
      }
  3. 如果您使用 Elasticsearch 安全功能,请登录到节点主机,导航到 Elasticsearch 安装目录,并使用elasticsearch-users工具在文件领域中添加具有superuser角色的用户。

    例如,以下命令创建一个名为restore_user的用户。

    ./bin/elasticsearch-users useradd restore_user -p my_password -r superuser

    使用此文件领域用户进行身份验证请求,直到恢复操作完成。

  4. 使用集群更新设置 APIaction.destructive_requires_name设置为false。这使您可以使用通配符删除数据流和索引。

    response = client.cluster.put_settings(
      body: {
        persistent: {
          'action.destructive_requires_name' => false
        }
      }
    )
    puts response
    PUT _cluster/settings
    {
      "persistent": {
        "action.destructive_requires_name": false
      }
    }
  5. 删除集群中所有现有的数据流。

    response = client.indices.delete_data_stream(
      name: '*',
      expand_wildcards: 'all'
    )
    puts response
    DELETE _data_stream/*?expand_wildcards=all
  6. 删除集群中所有现有的索引。

    response = client.indices.delete(
      index: '*',
      expand_wildcards: 'all'
    )
    puts response
    DELETE *?expand_wildcards=all
  7. 恢复整个快照,包括集群状态。默认情况下,恢复集群状态还会恢复快照中的任何功能状态。

    response = client.snapshot.restore(
      repository: 'my_repository',
      snapshot: 'my_snapshot_2099.05.06',
      body: {
        indices: '*',
        include_global_state: true
      }
    )
    puts response
    POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore
    {
      "indices": "*",
      "include_global_state": true
    }
  8. 恢复操作完成后,恢复索引并重新启动您停止的任何功能

    恢复快照后,快照拍摄时使用的许可证也将恢复。如果您的许可证在快照拍摄后已过期,您需要使用更新许可证 API安装当前许可证。

    • GeoIP 数据库下载器和 ILM 历史存储

      response = client.cluster.put_settings(
        body: {
          persistent: {
            'ingest.geoip.downloader.enabled' => true,
            'indices.lifecycle.history_index_enabled' => true
          }
        }
      )
      puts response
      PUT _cluster/settings
      {
        "persistent": {
          "ingest.geoip.downloader.enabled": true,
          "indices.lifecycle.history_index_enabled": true
        }
      }
    • ILM

      response = client.ilm.start
      puts response
      POST _ilm/start
    • 机器学习

      resp = client.ml.set_upgrade_mode(
          enabled="false",
      )
      print(resp)
      response = client.ml.set_upgrade_mode(
        enabled: false
      )
      puts response
      POST _ml/set_upgrade_mode?enabled=false
    • 监控

      response = client.cluster.put_settings(
        body: {
          persistent: {
            'xpack.monitoring.collection.enabled' => true
          }
        }
      )
      puts response
      PUT _cluster/settings
      {
        "persistent": {
          "xpack.monitoring.collection.enabled": true
        }
      }
    • Watcher

      response = client.watcher.start
      puts response
      POST _watcher/_start
    • 通用分析

      如果该值最初为true,请再次启用通用分析索引模板管理,否则跳过此步骤

      response = client.cluster.put_settings(
        body: {
          persistent: {
            'xpack.profiling.templates.enabled' => true
          }
        }
      )
      puts response
      PUT _cluster/settings
      {
        "persistent": {
          "xpack.profiling.templates.enabled": true
        }
      }
  9. 如果需要,请重置action.destructive_requires_name集群设置。

    response = client.cluster.put_settings(
      body: {
        persistent: {
          'action.destructive_requires_name' => nil
        }
      }
    )
    puts response
    PUT _cluster/settings
    {
      "persistent": {
        "action.destructive_requires_name": null
      }
    }

监控恢复编辑

恢复操作使用分片恢复过程从快照中恢复索引的主分片。在恢复操作恢复主分片时,集群将具有yellow健康状态

所有主分片恢复后,复制过程将在合格的数据节点上创建和分发副本。复制完成后,集群健康状态通常变为green

在 Kibana 中启动恢复后,您将被导航到恢复状态页面。您可以使用此页面跟踪快照中每个分片的当前状态。

您还可以使用 Elasticsearch API 监控快照恢复。要监控集群健康状态,请使用集群健康 API

$response = $client->cluster()->health();
resp = client.cluster.health()
print(resp)
response = client.cluster.health
puts response
res, err := es.Cluster.Health()
fmt.Println(res, err)
const response = await client.cluster.health()
console.log(response)
GET _cluster/health

要获取有关正在进行的分片恢复的详细信息,请使用索引恢复 API

response = client.indices.recovery(
  index: 'my-index'
)
puts response
GET my-index/_recovery

要查看任何未分配的分片,请使用cat 分片 API

response = client.cat.shards(
  v: true,
  h: 'index,shard,prirep,state,node,unassigned.reason',
  s: 'state'
)
puts response
GET _cat/shards?v=true&h=index,shard,prirep,state,node,unassigned.reason&s=state

未分配的分片具有stateUNASSIGNEDprirep值为主分片为p,副本为runassigned.reason描述了分片保持未分配的原因。

要更深入地了解未分配分片的分配状态,请使用集群分配解释 API

response = client.cluster.allocation_explain(
  body: {
    index: 'my-index',
    shard: 0,
    primary: false,
    current_node: 'my-node'
  }
)
puts response
GET _cluster/allocation/explain
{
  "index": "my-index",
  "shard": 0,
  "primary": false,
  "current_node": "my-node"
}

取消恢复编辑

您可以删除索引或数据流以取消其正在进行的恢复。这还会删除集群中索引或数据流的任何现有数据。删除索引或数据流不会影响快照或其数据。

response = client.indices.delete(
  index: 'my-index'
)
puts response

response = client.indices.delete_data_stream(
  name: 'logs-my_app-default'
)
puts response
# Delete an index
DELETE my-index

# Delete a data stream
DELETE _data_stream/logs-my_app-default

恢复到不同的集群编辑

Elasticsearch Service 可以帮助您从其他部署中恢复快照。查看使用快照

快照不绑定到特定集群或集群名称。您可以在一个集群中创建快照,并在另一个兼容集群中恢复它。您从快照中恢复的任何数据流或索引也必须与当前集群的版本兼容。集群的拓扑结构不需要匹配。

要恢复快照,其存储库必须注册并可用于新集群。如果原始集群仍然对存储库具有写访问权限,请将存储库注册为只读。这可以防止多个集群同时写入存储库并损坏存储库的内容。它还阻止 Elasticsearch 缓存存储库的内容,这意味着其他集群所做的更改将立即变得可见。

在开始恢复操作之前,请确保新集群有足够的容量来容纳您要恢复的任何数据流或索引。如果新集群的容量较小,您可以

  • 添加节点或升级硬件以增加容量。
  • 恢复更少的索引和数据流。
  • 减少已恢复索引的副本数量

    例如,以下恢复快照 API 请求使用index_settings选项将index.number_of_replicas设置为1

    response = client.snapshot.restore(
      repository: 'my_repository',
      snapshot: 'my_snapshot_2099.05.06',
      body: {
        indices: 'my-index,logs-my_app-default',
        index_settings: {
          'index.number_of_replicas' => 1
        }
      }
    )
    puts response
    POST _snapshot/my_repository/my_snapshot_2099.05.06/_restore
    {
      "indices": "my-index,logs-my_app-default",
      "index_settings": {
        "index.number_of_replicas": 1
      }
    }

如果原始集群中的索引或支持索引使用分片分配过滤分配到特定节点,则新集群中将强制执行相同的规则。如果新集群不包含已恢复索引可以分配到的具有适当属性的节点,则除非在恢复操作期间更改这些索引分配设置,否则索引将无法成功恢复。

恢复操作还会检查已恢复的持久设置是否与当前集群兼容,以避免意外恢复不兼容的设置。如果您需要恢复具有不兼容持久设置的快照,请尝试在没有全局集群状态的情况下恢复它。

排查恢复错误编辑

以下是解决恢复请求返回的常见错误的方法。

无法恢复索引 [<index>],因为集群中已存在具有相同名称的打开索引编辑

您无法恢复已存在的打开索引。要解决此错误,请尝试恢复索引或数据流中的方法之一。

无法从具有 [y] 个分片的索引 [<snapshot-index>] 的快照中恢复具有 [x] 个分片的索引 [<index>]编辑

您只能在索引关闭且快照中的索引具有相同数量的主分片的情况下恢复现有索引。此错误表示快照中的索引具有不同数量的主分片。

要解决此错误,请尝试恢复索引或数据流中的方法之一。