ElasticSearch 快照备份和还原
ES提供快照和恢复功能,我们可以在远程文件系统仓库(比如共享文件系统、S3、HDFS等)中单独给部分索引或者整个集群创建快照。这些快照对备份非常有用,它们能相对较快地被恢复。但是,快照只能被恢复到可以读取他们的ES版本中:
在5.x创建的索引的快照可以被恢复到6.x;
在2.x创建的索引的快照可以被恢复到5.x;
在1.x创建的索引的快照可以被恢复到2.x;
相反,在1.x中创建的索引快照不能被恢复到5.x或者6.x,在2.x中创建的索引快照不能被恢复到6.x中。
快照是增量的,可以包含在多个ES版本中创建的索引。如果在一个快照中的任何索引时在不兼容的ES版本中创建的,你将不能恢复该快照。
在升级前备份数据的时候,如果快照中的索引是在与你升级版本不兼容的ES版本中创建的,那么这些快照将不能被恢复。
如果你的情况是需要恢复一个与你当前运行的集群版本不兼容的索引快照,你可以先恢复到最新的兼容版本中,然后在当前版本中使用 reindex-from-remote 重建索引。远程Reindexing只能在源索引source为enabled的情况下进行。获取并重建数据索引的时间可能比简单恢复快照要长的多。如果你的数据量较大,建议先用一部分数据测试远程reindex,以便了解需要花费的时间。
Repositories
必须先注册一个快照仓库,然后才能进行快照和恢复操作。建议为每个主版本创建一个新快照仓库。有效的仓库设置取决于仓库类型。
如果多个集群注册同一个快照仓库,只有一个集群可以对仓库进行写访问,其他所有集群应该设置该仓库为 readonly 模式。
跨主版本时快照格式可能会改变,所以不同版本的集群写同一个快照仓库,某个版本写的快照可能对其他版本不可见,仓库快照也存在问题。ES不支持仓库对所有集群设置为readonly,其中一个集群和不同主版本的多个集群一起工作。
1. 注册创建快照仓库
curl -X PUT "localhost:9200/_snapshot/my_backup" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "my_backup_location"
}
}
2. 查看已注册快照仓库
curl -X GET "localhost:9200/_snapshot/my_backup"
可以使用逗号间隔多个仓库,星号通配符匹配仓库名字,下面示例返回仓库名以repo开头的和包含backup的仓库信息
curl -X GET "localhost:9200/_snapshot/repo*,*backup*"
获取所有已注册快照仓库,省略仓库名或者使用_all
curl -X GET "localhost:9200/_snapshot"
或者
curl -X GET "localhost:9200/_snapshot/_all"
3. 查看快照仓库列表
# curl -X GET "10.17.4.200:9200/_cat/repositories?v"
id type
elasticsearch_backup fs
test fs
4. Shared File System Repository
共享文件系统仓库(“type”: “fs”)使用共享文件系统存快照,如果要注册共享文件系统仓库,必须在所有master和data节点挂载相同的共享文件系统到同一个路径位置。这个路径位置(或者它的一个父目录)必须在所有master和data节点的path.repo设置上注册。
假设共享文件系统挂载到 /mount/backups/my_fs_backup_location,应该在elasticsearch.yml文件中添加如下配置:
path.repo: ["/mount/backups", "/mount/longterm_backups"]
The path.repo setting supports Microsoft Windows UNC paths as long as at least server name and share are specified as a prefix and back slashes are properly escaped:
path.repo: ["\\\\MY_SERVER\\Snapshots"]
所有节点启动之后,执行下面的命令注册名字为my_fs_backup的共享文件系统仓库:
curl -X PUT "localhost:9200/_snapshot/my_fs_backup" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "/mount/backups/my_fs_backup_location",
"compress": true
}
}
如果仓库路径使用相对路径,该路径将根据在path.repo中定义的第一个路径决定:
curl -X PUT "localhost:9200/_snapshot/my_fs_backup" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "my_fs_backup_location",
"compress": true
}
}
compress: Turns on compression of the snapshot files. Compression is applied only to metadata files (index mapping and settings). Data files are not compressed. Defaults to true.
5. 仓库确认
仓库被注册之后,会立即在所有master和data节点上被验证以确保对当前集群所有的节点有效。在注册或者更新仓库时,参数verify可以显示禁用仓库核实确认操作:
curl -X PUT "localhost:9200/_snapshot/my_unverified_backup?verify=false" -H 'Content-Type: application/json' -d'
{
"type": "fs",
"settings": {
"location": "my_unverified_backup_location"
}
}
验证过程可以通过下面的命令手动执行:
curl -X POST "localhost:9200/_snapshot/my_unverified_backup/_verify"
上面返回一个仓库验证成功的节点列表或者验证失败时的错误信息。
Snapshot
创建快照
一个仓库可以拥有同一个集群的多个快照。在一个集群中快照拥有一个唯一名字作为标识。在仓库 my_backup 中创建名字为 snapshot_1 的快照,可以通过执行下面的命令来实现:
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completion=true"
参数 wait_for_completion 决定请求是在快照初始化后立即返回(默认),还是等快照创建完成之后再返回。快照初始化时,所有之前的快照信息会被加载到内存,所以在一个大的仓库中改请求需要若干秒(甚至分钟)才能返回,即使参数 wait_for_completion 的值设置为 false。
默认情况下,创建一个快照会包含集群中所有打开和启动状态的索引。可以通过在创建快照的请求体中定义索引列表来改变这个默认处理:
curl -X PUT "localhost:9200/_snapshot/my_backup/snapshot_2?wait_for_completion=true" -H 'Content-Type: application/json' -d'
{
"indices": "index_1,index_2",
"ignore_unavailable": true,
"include_global_state": false
}
要包含到快照中索引列表可以使用支持多个索引语法的 indices 参数来指定。快照请求也支持 ignore_unavailable 选项,该选项设置为 true 时,在创建快照时会忽略不存在的索引。默认情况下,如果选项 ignore_unavailable 没有设值,一个索引缺失,快照请求会失败。
通过设置 include_global_state 为 false,可以阻止集群全局状态信息被保存为快照的一部分。默认情况下,如果如果一个快照中的一个或者多个索引没有所有主分片可用,整个快照创建会失败,该情况可以通过设置 partial 为 true 来改变。
快照名可以通过使用 date_math_expressions 来自动获得,和创建新索引时类似。注意特殊字符需要 URI 转码处理。
例如,在名字中使用当前日期,比如 snapshot-2018.05.11,来创建快照,可以使用如下命令完成:
# PUT /_snapshot/my_backup/<snapshot-{now/d}>
curl -X PUT "localhost:9200/_snapshot/my_backup/%3Csnapshot-%7Bnow%2Fd%7D%3E"
索引的快照过程是增量的。在创建索引快照的过程中,ElasticSearch会分析仓库中已经存在的索引文件,只拷贝那些在最后一次快照之后被创建或者更新的文件。That allows multiple snapshots to be preserved in the repository in a compact form. 快照过程以非阻塞的方式执行,所有的索引和搜索操作都可以对正在被创建快照的索引继续执行。一个快照表示的是这个索引在快照被创建时间点的索引视图,所以在索引过程开始之后被添加到索引中的记录不会出现在快照中。快照过程会立即在已经启动的主分片上开始并且不会在此时重新定位。在版本 1.2.0 以前,如果共同快照中的索引在集群中发生任何重新定位或者初始化(the cluster has any relocating or initializing primaries of indices participating in the snapshot),快照操作将失败,从 1.2.0 版本开始,ElasticSearch 会等重新定位或者初始化主分片完成之后再进行快照操作。
除了创建每个索引的备份,快照过程也能存储全局集群元数据,包括持久化的集群设置和模版。临时设置和注册的快照仓库不会存储为快照的一部分。
任何时候,在集群中只能有一个快照过程被执行。当创建一个特定分片的快照时,该分片不能移动到另一个节点,这会干扰(interfere with)平衡进程和分配过滤(allocation filtering)。ElasticSearch 一旦在快照完成之后才能移动分片到其他节点。
查看快照
一旦快照创建完成,可以通过以下命令获取快照信息:
curl -X GET "localhost:9200/_snapshot/my_backup/snapshot_1"
这个命令返回快照的基本信息,包括开始合结束时间、创建快照的 ElasticSearch 版本、包含的索引列表、快照当前状态和快照期间产生的失败索引列表。快照的状态有:
状态 描述
IN_PROGRESS The snapshot is currently running.
SUCCESS The snapshot finished and all shards were stored successfully.
FAILED The snapshot finished with an error and failed to store any data.
PARTIAL The global cluster state was stored, but data of at least one shard wasn’t stored successfully. The failure section in this case should contain more detailed information about shards that were not processed correctly.
INCOMPATIBLE The snapshot was created with an old version of Elasticsearch and therefore is incompatible with the current version of the cluster.
跟仓库类似,在一次查询中可以查询多个快照的信息,也支持通配符:
curl -X GET "localhost:9200/_snapshot/my_backup/snapshot_*,some_other_snapshot"
仓库当前存储的所有快照可以通过下面的命令获取:
curl -X GET "localhost:9200/_snapshot/my_backup/_all"
如果一些快照不可用,会导致获取命令执行失败。可以通过设置布尔参数 ignore_unavailable 来指定返回当前可用的所有快照。
从基于云存储的仓库中获取所有的快照,在消耗和性能方面看代价都比较高。如果只是获取快照的 names/uuids 和每个快照的索引列表,可以设置可选的布尔参数 verbose 为 true,这样再执行快照的获取,性能表现更好,消耗更划算。注意,设置 verbose 为 false,会忽略关于快照的所有其他信息,例如状态信息、快照分片的数量等,verbose 参数的默认值为 true。
当前正在运行的快照可以使用如下命令获取:
curl -X GET "localhost:9200/_snapshot/my_backup/_current"
删除快照
从仓库中删除一个快照,使用如下命令:
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_2"
当一个快照从仓库中删除,ElasticSearch 将删除该快照关联的但不被其他快照使用的所有文件。如果在快照创建的时候执行快照删除操作,此快照创建进程将终止且所有该进程已创建的文件也将被清理。所以,快照删除操作可以用来取消错误启动的长时间运行的快照操作。
删除仓库
可以使用下面命令注销仓库:
curl -X DELETE "localhost:9200/_snapshot/my_backup"
当一个仓库被注销时,ElasticSearch 只删除仓库存储快照的引用位置,快照本身没有被删除并且在原来的位置。
Restore
快照可以通过执行以下命令恢复
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore"
默认情况下,快照中的所有索引将被恢复,集群状态不被恢复。可以通过在恢复请求中使用 indices 和 include_global_state 选项来指定要恢复的索引和允许恢复集群全局状态。索引列表支持多索引语法。rename_pattern 和 rename_replacement 选项在恢复时通过正则表达式来重命名索引。设置 include_aliases 为 false 可以防止与索引关联的别名被一起恢复。
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "index_1,index_2",
"ignore_unavailable": true,
"include_global_state": true,
"rename_pattern": "index_(.+)",
"rename_replacement": "restored_index_$1"
}
恢复操作可以在正常运行的集群上执行。已存在的索引只能在关闭状态下才能恢复,并且要跟快照中索引拥有相同数目的分片。还原操作自动打开关闭状态的索引,如果被还原索引在集群不存在,将创建新索引。如果集群状态通过 include_global_state (默认是 false)选项被还原,在集群中不存在的模板会被新增,已存在的同名模板会被快照中的模板替换。持久化设置会被添加到现有的持久化设置中。
部分还原
默认情况下,如果参与恢复操作的一个或者多个索引没有全部可用分片的快照,整个恢复操作将会失败。比如部分分片快照备份操作失败,上面的情况就会发生。这种情况依然可以通过设置 partial 为 true 来实现快照的恢复。注意在这种情况下,只有成功完成快照备份的分片才会被还原,而所有丢失的 其它分片将被创建成空分片。
恢复过程中修改索引设置
在恢复过程中,大部分的索引配置会被覆盖。例如,下面的命令将恢复索引 index_1,不创建任何副本并切换回默认的索引刷新时间间隔:
curl -X POST "localhost:9200/_snapshot/my_backup/snapshot_1/_restore" -H 'Content-Type: application/json' -d'
{
"indices": "index_1",
"index_settings": {
"index.number_of_replicas": 0
},
"ignore_index_settings": [
"index.refresh_interval"
]
}
请注意,有些设置不能再恢复操作时被修改,比如 index.number_of_shards。
恢复到不同的集群
存储在快照中的信息是不和特定的集群或者集群名绑定的。因此可以将一个集群的快照恢复到另外一个集群中去。需要做的就是在新的集群中注册包含快照的仓库,然后启动恢复快照过程。新的集群不必具有相同的大小和拓扑结构(topology)。但是,新集群的版本必须和创建快照的集群的版本一致或者更高(只能高出1个主版本)。例如,可以恢复1.x版本的快照到2.x版本的集群中,但是不能恢复到5.x版本的集群中。
如果新集群大小比原集群小,需要做一些额外的考虑。首先,确保新集群具有足够的容量来存储快照中的所有索引。恢复过程中可以通过修改索引配置来降低副本数量,这样有助于恢复快照到更小的集群。也可以使用 indices 参数来指定恢复索引的子集。
如果原来集群中的索引使用了分片分配过滤器(shard allocation filtering)来分配索引到特定的节点,那么相同的规则将在新集群中被执行。所以,如果新集群不包含具有可以使被还原索引分配到自身的的属性的节点,索引将不会被成功恢复,除非在恢复时更改索引的分配配置。
恢复操作还会检查恢复持久化设置是否与当前集群兼容,以避免意外恢复不兼容的设置,例如 discovery.zen.minimum_master_nodes,因此在添加所必需数目的备选主节点之前,禁用较小的集群。如果需要恢复具有不兼容持久化设置的快照,则请尝试在没有全局集群状态的情况下执行。
快照状态
使用以下命令可以获取当前运行快照列表的详细状态信息:
curl -X GET "localhost:9200/_snapshot/_status"
可以指定快照名,以获取指定快照的信息,即使它不是正在运行状态:
curl -X GET "localhost:9200/_snapshot/my_backup/snapshot_1/_status"
也支持多个ID:
curl -X GET "localhost:9200/_snapshot/my_backup/snapshot_1,snapshot_2/_status"
Monitoring snapshot/restore progress
有几种方法可以用来监测快照创建与还原正在运行时的执行进度。在创建快照与还原时指定 wait_for_completion 参数来阻塞客户端,直到操作完成,这是一个可以用来获取操作完成通知的最简单方法。
快照操作还可以通过定期获取快照信息来监测:
curl -X GET "localhost:9200/_snapshot/my_backup/snapshot_1"
请注意,获取快照信息操作与创建快照操作使用相同的资源和线程池,因此在执行获取快照信息时如果创建快照的线程正在备份大的分片,可能导致要在返回结果前等待可用的资源。在非常大的分片备份情况中等待的时间回很长。
为了获得更多的直接和完整的信息,可以用快照的status命令来查看:
curl -X GET "localhost:9200/_snapshot/my_backup/snapshot_1/_status"
快照信息命令返回正在进行的快照的基本信息,而快照状态命令返回参与快照的每个分片的当前状态完整分解(complete breakdown of the current state for each shard participating in the snapshot)。
还原过程是基于 Elasticsearch 标准恢复机制。因此标准的恢复监控服务可以用来监控还原的状态。当集群执行还原操作时通常会进入 red 状态。这是因为还原操作是从恢复被还原索引的主分片开始的,在此期间主分片状态变为不可用,表现为集群状态为 red。一旦主分片恢复完成,ElasticSearch 开始创建所需数目的副本的标准复制过程,这时集群切换到 yellow 状态。一旦完成所有必需副本的创建,集群变切换到 green 状态。
集群健康状态只提供了还原过程的一个比较粗略的一个状态。还可以通过使用 indices recovery 和 cat recovery 接口获取更详细的恢复过程的状态信息。
Stopping currently running snapshot and restore operations
快照和恢复框架只允许在同一个时间点运行一个快照或者一个恢复操作。如果当前运行的快照被错误执行,或者执行时间特别长,可以通过快照删除操作来终止操作。快照删除操作会检查要删除的快照是否正在运行,如果是,删除操作会在从仓库中删除快照数据之前停止快照运行。
curl -X DELETE "localhost:9200/_snapshot/my_backup/snapshot_1"
恢复操作使用标准分片恢复机制。所以任何当前正在运行的恢复操作都可以通过删除正在被恢复的索引来取消。请注意,所有已删除索引的数据都将因为这个操作被移除。
Effect of cluster blocks on snapshot and restore operations
许多快照备份和恢复操作都会被集群和索引的锁影响。例如,注册和注销仓库需要写全局元数据。快照操作需要要求所有的索引及其元数据以及全局元数据可读。恢复操作要求全局元数据可写,而索引级别的锁在恢复过程中被忽略,因为索引的恢复本质上是重新创建索引。请注意,仓库内容不是集群的一部分,因此集群锁不影响仓库内部操作,比如获取一个已注册的仓库的快照列表或者删除其中的快照。