使用 Amazon Elasticsearch Service 索引快照 - Amazon Elasticsearch Service
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

使用 Amazon Elasticsearch Service 索引快照

快照是集群的索引和状态 的备份。状态包含集群设置、节点信息、索引设置和分片分配。

Amazon Elasticsearch Service 上的快照有两种形式:自动和手动。

  • 自动快照 用于集群恢复。在出现红色集群状态或其他数据丢失的情况时,您可以使用自动快照来恢复域。Amazon ES 在预配置的 Amazon S3 存储桶中存储自动快照,没有任何附加费用。

  • 手动快照用于集群恢复或者 将数据从一个集群移动到另一个集群。顾名思义,您必须自行启动手动快照。这些快照将存储在您自己的 Amazon S3 存储桶中,收取标准 S3 费用。如果您有来自自行管理的 Elasticsearch 集群的快照,那么甚至可以使用该快照迁移到 Amazon ES 域

所有 Amazon ES 域都制作自动快照,但频率不同:

  • 对于运行 Elasticsearch 5.3 及更高版本的域,Amazon ES 会每小时自动制作快照,并且将最多 336 个快照保留 14 天时间。

  • 对于运行 Elasticsearch 5.1 及更低版本的域,Amazon ES 会每日自动制作快照,并且将最多 14 个快照保留 30 天时间。

如果您的集群进入红色状态,Amazon ES 会停止制作自动快照。如果您在两周内未解决问题,则可能会永久丢失集群数据。有关问题排查步骤,请参阅红色集群状态

手动快照先决条件

要手动创建快照,您必须使用 IAM 和 Amazon S3。确认您已满足以下先决条件,然后再尝试创建快照。

先决条件 描述
S3 存储桶

为您的 Amazon ES 域存储手动快照。记下存储桶的名称。在两个地方需要用到它:

  • 附加到 IAM 角色的 IAM 策略的 Resource 语句

  • 用于注册快照存储库的 Python 客户端

有关更多信息,请参阅 Amazon Simple Storage Service 入门指南 中的创建存储桶

重要

对此存储桶应用 S3 Glacier 生命周期规则。手动快照不支持 S3 Glacier 存储类。

IAM 角色

委派权限给 Amazon Elasticsearch Service。本章剩余部分将此角色称为 TheSnapshotRole

此角色的信任关系必须在 Principal 语句中指定 Amazon Elasticsearch Service,如以下示例中所示:

{ "Version": "2012-10-17", "Statement": [{ "Sid": "", "Effect": "Allow", "Principal": { "Service": "es.amazonaws.com" }, "Action": "sts:AssumeRole" }] }

此角色必须附加以下策略:

{ "Version": "2012-10-17", "Statement": [{ "Action": [ "s3:ListBucket" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::s3-bucket-name" ] }, { "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Effect": "Allow", "Resource": [ "arn:aws:s3:::s3-bucket-name/*" ] } ] }

有关更多信息,请参阅 IAM 用户指南 中的添加 IAM 身份权限

权限

必须能够代入 TheSnapshotRole 角色才能注册快照存储库。还需要对 es:ESHttpPut 操作的访问权限。以下策略包括这些权限:

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iam:PassRole", "Resource": "arn:aws:iam::123456789012:role/TheSnapshotRole" }, { "Effect": "Allow", "Action": "es:ESHttpPut", "Resource": "arn:aws:es:region:123456789012:domain/my-domain/*" } ] }

如果您没有 iam:PassRole 权限来代入 TheSnapshotRole,您可能会遇到以下常见错误:

$ python register-repo.py {"Message":"User: arn:aws:iam::123456789012:user/MyUserAccount is not authorized to perform: iam:PassRole on resource: arn:aws:iam::123456789012:role/TheSnapshotRole"}

注册手动快照存储库

您必须通过 Amazon Elasticsearch Service 注册快照存储库,然后才能拍摄手动索引快照。此一次性操作需要使用允许访问 TheSnapshotRole 的凭证签发 AWS 请求,如手动快照先决条件中所述。

不能使用 curl 执行此操作,因为它不支持 AWS 请求签名。请改用示例 Python 客户端Postman 或某种其他方式发送已签名请求以注册快照存储库。此请求采用以下形式:

PUT elasticsearch-domain-endpoint/_snapshot/my-snapshot-repo-name { "type": "s3", "settings": { "bucket": "s3-bucket-name", "region": "region", "role_arn": "arn:aws:iam::123456789012:role/TheSnapshotRole" } }

注册快照目录是一次性操作,但要从一个域迁移到另一个域,您必须在旧域和新域中注册相同的快照存储库。存储库名称是任意的。

重要

如果 S3 存储桶位于 us-east-1 区域中,您必须使用 "endpoint": "s3.amazonaws.com" 而不是 "region": "us-east-1"

要为快照存储库启用使用 S3 托管密钥的服务器端加密,请将 "server_side_encryption": true 添加到 "settings" JSON。

如果域位于 VPC 中,则计算机必须连接到 VPC,请求才能成功注册快照存储库。访问 VPC 因网络配置而异,但很可能包括连接到 VPN 或企业网络。要检查您是否可以访问 Amazon ES 域,请在 Web 浏览器中导航到 https://your-vpc-domain.region.es.amazonaws.com 并验证您是否收到默认的 JSON 响应。

如果您使用精细访问控制,请参阅手动快照以了解其他步骤。

示例 Python 客户端

将下面的示例 Python 代码保存为 Python 文件,如 register-repo.py。客户端需要 适用于 Python 的 AWS 开发工具包 (Boto3)requestsrequests-aws4auth 程序包。客户端包含其他快照操作的带注释示例。

提示

签署 HTTP 请求中提供了一个基于 Java 的代码示例。

您必须更新以下变量:hostregionpath、和 payload

import boto3 import requests from requests_aws4auth import AWS4Auth host = '' # include https:// and trailing / region = '' # e.g. us-west-1 service = 'es' credentials = boto3.Session().get_credentials() awsauth = AWS4Auth(credentials.access_key, credentials.secret_key, region, service, session_token=credentials.token) # Register repository path = '_snapshot/my-snapshot-repo-name' # the Elasticsearch API endpoint url = host + path payload = { "type": "s3", "settings": { "bucket": "s3-bucket-name", # "endpoint": "s3.amazonaws.com", # for us-east-1 "region": "us-west-1", # for all other regions "role_arn": "arn:aws:iam::123456789012:role/TheSnapshotRole" } } headers = {"Content-Type": "application/json"} r = requests.put(url, auth=awsauth, json=payload, headers=headers) print(r.status_code) print(r.text) # # Take snapshot # # path = '_snapshot/my-snapshot-repo/my-snapshot' # url = host + path # # r = requests.put(url, auth=awsauth) # # print(r.text) # # # Delete index # # path = 'my-index' # url = host + path # # r = requests.delete(url, auth=awsauth) # # print(r.text) # # # Restore snapshot (all indices except Kibana and fine-grained access control) # # path = '_snapshot/my-snapshot-repo/my-snapshot/_restore' # url = host + path # # payload = { # "indices": "-.kibana*,-.opendistro_security", # "include_global_state": false # } # # headers = {"Content-Type": "application/json"} # # r = requests.post(url, auth=awsauth, json=payload, headers=headers) # # # Restore snapshot (one index) # # path = '_snapshot/my-snapshot-repo/my-snapshot/_restore' # url = host + path # # payload = {"indices": "my-index"} # # headers = {"Content-Type": "application/json"} # # r = requests.post(url, auth=awsauth, json=payload, headers=headers) # # print(r.text)

手动创建快照

快照不是即时发生的;它们需要一些时间才能完成,并且不代表集群的完美时间点视图。当快照正在进行时,您仍可以对文档编制索引并对集群发出其他请求,但新文档(和对现有文档的更新)通常不包含在快照中。快照包含 Elasticsearch 启动快照时存在的主分片。根据快照线程池的大小,快照中可能包含时间略有不同的不同分片。

Elasticsearch 快照为增量快照,这意味着它们仅存储自上次快照成功后已更改的数据。此增量性质意味着频繁快照与不频繁快照之间的磁盘使用率差异通常极其小。换句话说,一周内每小时快照(总共 168 个快照)占用的磁盘空间比一周结束时的一个快照所占用的磁盘空间并不高多少。此外,拍摄快照的频率越高,完成快照所需的时间就更少。一些 Elasticsearch 用户每半小时拍摄一次快照。

在创建快照时指定两项信息:

  • 快照存储库的名称

  • 快照名称

为了方便和简洁起见,本章中的示例使用 curl,这是一种常见的 HTTP 客户端。但是,如果您的访问策略指定 IAM 用户或角色,您必须对快照请求进行签名。您可以使用示例 Python 客户端中的带注释示例将签名 HTTP 请求置于 curl 命令使用的同一终端节点。

手动创建快照

  1. 如果当前正在制作快照,则您无法制作快照。要进行检查,请运行以下命令:

    curl -XGET 'elasticsearch-domain-endpoint/_snapshot/_status'
  2. 运行以下命令来手动创建快照:

    curl -XPUT 'elasticsearch-domain-endpoint/_snapshot/repository/snapshot-name'
注意

创建快照所需的时间会随着 Amazon ES 域大小的增长而增加。长时间运行的快照操作有时会遇到以下错误:504 GATEWAY_TIMEOUT。通常情况下,您可以忽略这些错误并等待操作成功完成。使用以下命令验证您的域中所有快照的状态:

curl -XGET 'elasticsearch-domain-endpoint/_snapshot/repository/_all?pretty'

还原快照

警告

如果您使用索引别名,请在删除别名的索引前停止向该别名写入请求 (或将别名切换至其他索引)。停止写入请求有助于避免以下情景:

  1. 您删除某个索引,同时会删除它的别名。

  2. 对于现已删除的别名的错误写入请求会创建一个与别名同名的新索引。

  3. 由于与新索引的命名冲突,您无法再使用别名。

如果将别名切换到其他索引,请在从快照中还原时指定 "include_aliases": false

还原快照

  1. 确定要还原的快照。要查看所有快照存储库,请运行以下命令:

    curl -XGET 'elasticsearch-domain-endpoint/_snapshot?pretty'

    在确定存储库后,您可以运行以下命令查看所有快照:

    curl -XGET 'elasticsearch-domain-endpoint/_snapshot/repository/_all?pretty'
    注意

    大多数自动快照存储在 cs-automated 存储库中。如果您的域对静态数据进行加密,这些快照将存储在 cs-automated-enc 存储库中。如果您没有看到要查找的手动快照存储库,请确保您已向域注册该存储库。

  2. (可选)删除或重命名 Amazon ES 域中的一个或多个索引。如果集群上的索引与快照中的索引之间没有命名冲突,则无需执行此步骤。

    您不能将索引的快照还原到已包含同名索引的 Elasticsearch 集群。Amazon ES 目前不支持 Elasticsearch _close API,因此,您必须使用以下备选项之一:

    • 删除同一个 Amazon ES 域中的索引,然后还原快照。

    • 从快照还原索引时为其重命名,之后为它们重新编制索引。

    • 将快照还原到另一个 Amazon ES 域 (只能通过手动快照实现).

    以下示例演示如何删除域的所有 现有索引:

    curl -XDELETE 'elasticsearch-domain-endpoint/_all'

    但如果您不打算还原所有索引,则可能需要仅删除一个索引:

    curl -XDELETE 'elasticsearch-domain-endpoint/index-name'
  3. 要还原快照,请运行以下命令:

    curl -XPOST 'elasticsearch-domain-endpoint/_snapshot/repository/snapshot/_restore'

    由于针对 Kibana 和精细访问控制索引的特殊权限,尝试还原所有索引时可能会失败,尤其是当您尝试从自动快照还原时。以下示例通过 my-index 快照存储库中的 2017-snapshot 来只还原一个索引 cs-automated

    curl -XPOST 'elasticsearch-domain-endpoint/_snapshot/cs-automated/2017-snapshot/_restore' -d '{"indices": "my-index"}' -H 'Content-Type: application/json'

    或者,您可能需要还原 Kibana 和精细访问控制索引以外的所有索引:

    curl -XPOST 'elasticsearch-domain-endpoint/_snapshot/cs-automated/2017-snapshot/_restore' -d '{"indices": "-.kibana*, -.opendistro_security"}' -H 'Content-Type: application/json'
注意

如果并非所有主分片都适用于涉及的索引,则快照的 state 可能为 PARTIAL。此值表示未成功存储至少一个分片中的数据。您仍可以从部分快照进行还原,但可能需要使用较旧的快照来还原任何缺失的索引。

将 Curator 用于快照

一些用户找到了 Curator 等方便用于索引和快照管理的工具。使用 pip 安装 Curator:

pip install elasticsearch-curator

Curator 提供了高级筛选功能,可帮助简化复杂集群上的管理任务。Amazon ES 在运行 Elasticsearch 5.1 版及更高版本的域上支持 Curator。您可以使用 Curator 作为命令行界面 (CLI) 或 Python API。如果您使用 CLI,请在命令行处导出您的凭证并配置 curator.yml,如下所示:

client: hosts: search-my-domain.us-west-1.es.amazonaws.com port: 443 use_ssl: True aws_region: us-west-1 aws_sign_request: True ssl_no_validate: False timeout: 60 logging: loglevel: INFO

有关使用 Python API 的示例 Lambda 函数,请参阅 使用 Curator 在 Amazon Elasticsearch Service 中轮换数据