集群的版本升级

生产集群的时候,版本升级,是不可避免的,es主要的版本,es 2.x,es 5.x,es 1.x
如果你去运维一个es的集群,你要做各个版本之间的升级,你该怎么做。。。
三种策略:
1、面向的场景,就是同一个大版本之间的各个小版本的升级,比如说,我们这一节课,es 5.3升级到es 5.5 2、相邻的两个大版本之间的升级,比如es 2.x升级到es 5.x,es 2.4.3,升级到es 5.5 3、跨了几个大版本之间的升级,就比如说es 1.x升级到es 5.x
每一种场景使用的技术方案都是不一样的

es版本升级的通用步骤

(1)看一下最新的版本的breaking changes文档,官网,看一下,每个小版本之间的升级,都有哪些变化,新功能,bugfix (2)用elasticsearch migration plugin在升级之前检查以下潜在的问题(在老版本的时候可能还会去用,现在新版本这个plugin很少用了) (3)在开发环境的机器中,先实验一下版本的升级,定一下升级的技术方案和操作步骤的文档,然后先在你的测试环境里,先升级一次,搞一下 (4)对数据做一次全量备份,备份和恢复,最次最次的情况,哪怕是升级失败了,哪怕是你重新搭建一套全新的es (5)检查升级之后各个plugin是否跟es主版本兼容,升级完es之后,还要重新安装一下你的plugin
es不同版本之间的升级,用的升级策略是不一样的
(1)es 1.x升级到es 5.x,是需要用索引重建策略的 (2)es 2.x升级到es 5.x,是需要用集群重启策略的 (3)es 5.x升级到es 5.y,是需要用节点依次重启策略的
es的每个大版本都可以读取上一个大版本创建的索引文件,但是如果是上上个大版本创建的索引,是不可以读取的。比如说es 5.x可以读取es 2.x创建的索引,但是没法读取es 1.x创建的索引。

rolling upgrade(小版本升级)

rolling upgrade会让es集群每次升级一个node,对于终端用户来说,是没有停机时间的。在一个es集群中运行多个版本,长时间的话是不行的,因为shard是没法从一较新版本的node上replicate到较旧版本的node上的。
先部署一个es 5.3.2版本,将配置文件放在外部目录,同时将data和log目录都放在外部,然后插入一些数据,然后再开始下面的升级过程
adduser elasticsearch passwd elasticsearch
chown -R elasticsearch /usr/local/elasticsearch chown -R elasticsearch /var/log/elasticsearch chown -R elasticsearch /var/data/elasticsearch chown -R elasticsearch /etc/elasticsearch
su elasticsearch
elasticsearch -d -Epath.conf=/etc/elasticsearch
curl -XPUT 'http://localhost:9200/forum/article/1?pretty' -d ' { "title": "first article", "content": "this is my first article" }'
(1)禁止shard allocation
停止一个node之后,这个node上的shard全都不可用了,此时shard allocation机制会等待一分钟,然后开始shard recovery过程,也就是将丢失掉的primary shard的replica shard提升为primary shard,同时创建更多的replica shard满足副本数量,但是这个过程会导致大量的IO操作,是没有必要的。因此在开始升级一个node,以及关闭这个node之前,先禁止shard allocation机制:
curl -XPUT 'http://localhost:9200/_cluster/settings?pretty' -d ' { "persistent": { "cluster.routing.allocation.enable": "none" } }'
(2)停止非核心业务的写入操作,以及执行一次flush操作
可以在升级期间继续写入数据,但是如果在升级期间一直写入数据的话,可能会导致重启节点的时候,shard recovery的时间变长,因为很多数据都是translog里面,没有flush到磁盘上去。如果我们暂时停止数据的写入,而且还进行一次flush操作,把数据都刷入磁盘中,这样在node重启的时候,几乎没有什么数据要从translog中恢复的,重启速度会很快,因为shard recovery过程会很快。用下面这行命令执行flush:POST _flush/synced。但是flush操作是尽量执行的,有可能会执行失败,如果有大量的index写入操作的话。所以可能需要多次执行flush,直到它执行成功。
(3)停止一个node然后升级这个node
在完成node的shard allocation禁用以及flush操作之后,就可以停止这个node。
如果你安装了一些插件,或者是自己设置过jvm.options文件的话,需要先将/usr/local/elasticsearch/plugins拷贝出来,作为一个备份,jvm.options也拷贝出来
将老的es安装目录删除,然后将最新版本的es解压缩,而且要确保我们绝对不会覆盖config、data、log等目录,否则就会导致我们丢失数据、日志、配置文件还有安装好的插件。
kill -SIGTERM 15516
(4)升级plugin
可以将备份的plugins目录拷贝回最新解压开来的es安装目录中,包括你的jvm.options
自己去官网,找到各个plugin的git地址,git地址上,都有每个plugin version跟es version之间的对应关系。要检查一下所有的plugin是否跟要升级的es版本是兼容的,如果不兼容,那么需要先用elasticsearch-plugin脚本重新安装最新版本的plugin。
(5)启动es node
接着要注意在启动es的时候,在命令行里用-Epath.conf= option来指向一个外部已经配置好的config目录。这样的话最新版的es就会复用之前的所有配置了,而且也会根据配置文件中的地址,找到对应的log、data等目录。然后再日志中查看这个node是否正确加入了cluster,也可以通过下面的命令来检查:GET _cat/nodes。
elasticsearch -d -Epath.conf=/etc/elasticsearch
(6)在node上重新启用shard allocation
一旦node加入了cluster之后,就可以重新启用shard allocation
curl -XPUT 'http://localhost:9200/_cluster/settings?pretty' -d ' { "persistent": { "cluster.routing.allocation.enable": "all" } }'
(7)等待node完成shard recover过程
我们要等待cluster完成shard allocation过程,可以通过下面的命令查看进度:GET _cat/health。一定要等待cluster的status从yellow变成green才可以。green就意味着所有的primary shard和replica shard都可以用了。
在rolling upgrade期间,primary shard如果分配给了一个更新版本的node,是一定不会将其replica复制给较旧的版本的node的,因为较新的版本的数据格式跟较旧的版本是不兼容的。但是如果不允许将replica shard复制给其他node的话,比如说此时集群中只有一个最新版本的node,那么有些replica shard就会是unassgied状态,此时cluster status就会保持为yellow。此时,就可以继续升级其他的node,一旦其他node变成了最新版本,那么就会进行replica shard的复制,然后cluster status会变成green。
如果没有进行过flush操作的shard是需要一些时间去恢复的,因为要从translog中恢复一些数据出来。可以通过下面的命令来查看恢复的进度:GET _cat/recovery。
(8)重复上面的步骤,直到将所有的node都升级完成
 

full cluster restart(相邻大版本升级)

滚动升级策略,集群,集群里面有多个节点,一个节点一个节点的重启和升级
如果是大版本之间的升级,集群重启策略,要先将整个集群全部停掉,如果采取滚动升级策略的话,可能导致说,一个集群内,有些节点是es 5.5,有些节点是es 2.4.3,这样的话是可能会有问题的
升级的过程,其实是跟之前的一模一样的
es在进行重大版本升级的时候,一般都需要采取full cluster restart的策略,重启整个集群来进行升级。rolling upgrade在重大版本升级的时候是不合适的。
执行一个full cluster restart升级的过程如下:
我们先停掉之前的es 5.5,删除所有相关的目录,然后安装一个es 2.4.3,再将其升级到es 5.5
chown -R elasticsearch /usr/local/elasticsearch chown -R elasticsearch /var/log/elasticsearch chown -R elasticsearch /var/data/elasticsearch chown -R elasticsearch /etc/elasticsearch
su elasticsearch
elasticsearch -d -Dpath.conf=/etc/elasticsearch kill -SIGTERM 15516
curl -XPUT 'http://localhost:9200/forum/article/1?pretty' -d ' { "title": "first article", "content": "this is my first article" }'
(1)禁止shard allocation
我们停止一个node时,可能导致部分replica shard死掉了,此时shard allocation机制会立即在其他节点上分配一些replica shard过去。如果是停止node导致primary shard死掉了,会将其他node上的replica shard提升为primary shard,同理会给其复制足够的replica shard,保持replica副本数量。但是这回导致大量的IO开销。我们首先得先禁止这个机制:
curl -XPUT 'http://localhost:9200/_cluster/settings?pretty' -d ' { "persistent": { "cluster.routing.allocation.enable": "none" } }'
(2)执行一次flush操作
我们最好是停止接受新的index写入操作,并且执行一次flush操作,确保数据都fsync到磁盘上。这样的话,确保没有数据停留在内存和WAL日志中。shard recovery的时间就会很短。
此时,最好是执行synced flush操作,因为我们最好是确保说flush操作成功了,再执行下面的操作
如果flush操作报错了,那么可以反复多执行几次
(3)关闭和升级所有的node
如果是将es 2.x版本升级到es 5.x版本,唯一的区别就在这里开始了,先将整个集群中所有的节点全部停止
将最新版本的es解压缩替代之前的es安装目录之前,一定要记得先将plugins做个备份
将集群上所有node上的es服务都给停止,然后按照rolling upgrade中的步骤对集群中所有的node进行升级
将所有的节点全部停掉,将所有的node全部替换为最新版本的es安装目录
(4)升级plugin
最新版的es解压开来以后,就可以看看,可以去做一个plugin的升级
es plugin的版本是跟es版本相关联的,因此必须使用elasticsearch-plugin脚本来安装最新的plugin版本
(5)启动cluster集群
如果我们有专门的master节点的话,就是那些将node.master设置为true的节点(默认都是true,都有能力作为master节点),而且node.data设置为false,那么就先将master node启动。等待master node组建成一个cluster之后,这些master node中会选举一个正式的master node出来。可以在log中检查master的选举。
只要minimum number of master-eligible nodes数量的node发现了彼此,他们就会组成一个cluster,并且选举出来一个master。从这时开始,可以监控到加入cluster的node。
依次将所有的node重新启动起来
elasticsearch -d -Epath.conf=/etc/elasticsearch
如果是将es 2.x升级到es 5.x,记得将log4j.properties拷贝到你外部的目录中去,而且还要重新做目录的权限的更改
(6)等待cluster状态变成yellow
只要每个ndoe都加入了cluster,就会开始对primary shard进行receover过程,就是看有没有数据在WAL日志中的,给恢复到内存里。刚开始的话,_cat/health请求会反馈集群状态是red,这意味着不是所有的primary shard都被分配了。
只要每个node发现了自己本地的shard之后,集群status就会变成yellow,意味着所有的primary shard都被发现了,但是并不是所有的replica shard都被分配了。
(7)重新启用allocation
直到所有的node都加入了集群,再重新启用shard allocation,可以让master将replica分配给那些本地已经有replica shard的node上。
curl -XPUT 'http://localhost:9200/_cluster/settings?pretty' -d ' { "persistent": { "cluster.routing.allocation.enable": "all" } }'
cluster这个时候就会开始将replica shard分配给data node。此时可以恢复index和search操作,不过最好还是等待replica shard全部分配完之后,再去恢复读写操作。
我们可以通过下面的api来监控这个过程
GET _cat/health
GET _cat/recovery
如果_cat/health中的status列变成了green,那么所有的primary和replica shard都被成功分配了

跨越多个大版本升级

es只能使用上一个大版本创建的索引。举例来说,es 5.x可以使用es 2.x中的索引,但是不能使用es 1.x中的索引。
es 5.x如果使用过于陈旧的索引去启动,就会启动失败
如果我们在运行es 2.x集群,但是索引是从2.x之前的版本创建的,那么在升级到es 5.x之前,我们需要删除旧索引,或者reindex这些索引,用reindex in place的策略。
如果我们在运行es 1.x的集群,有两个选择,首先升级到es 2.4.x,然后reindex所有的旧索引,用reindex in place的策略,接着升级到es 5.x。创建一个新的5.x集群,然后使用reindex-from-remote直接从es 1.x集群中将索引倒入5.x集群中。
同时运行一个es 1.x的集群,同时也运行一个es 5.x的集群,然后用reindex功能,将es 1.x中的所有数据都导入到es 5.x集群中
elasticsearch -d -Dpath.conf=/etc/elasticsearch kill -SIGTERM 15516
chown -R elasticsearch /usr/local/elasticsearch-1.7.4 chown -R elasticsearch /usr/local/elasticsearch-5.5.0
curl -XPUT 'http://localhost:9200/forum/article/1?pretty' -d ' { "title": "first article", "content": "this is my first article" }'
(1)reindex in place
将1.x中的索引reindex最简单的方法,就是用elasticsearch migration plugin去做reindex。但是首先需要先升级到es 2.3.x或2.4.x。
migration plugin中提供的reindex工具会执行以下操作:
创建新的索引,但是会将es版本号拼接到索引名称上,比如my_index-2.4.1,从旧的索引中拷贝mapping和setting。禁止新索引的refresh,并且将replica数量设置为0.主要是为了更高效的reindex。
将旧索引设置为只读,不允许新的数据写入旧索引中
从旧索引中,将所有的数据reindex到新索引中
对新索引的refresh_interval和number_of_replicas的值重新设置为旧索引中的值,并且等待索引变成green
将旧索引中存在的alias添加到新索引中
删除旧的索引
给新索引添加一个alia,使用旧索引的名称,比如将my_index设置为my_index-2.4.1的alia
此时,就可以有一份新的2.x的索引,可以在5.x中使用
(2)upgrading with reindex-from-remote
如果在运行1.x cluster,并且想要直接迁移到5.x,而不是先迁移到2.x,那么需要进行reindex-from-remote操作
es包含了向后兼容性的代码,从而允许上一个大版本的索引可以直接在这个版本中使用。如果要直接从1.x升级到5.x,我们就需要自己解决向后兼容性的问题。
首先我们需要先建立一个新的5.x的集群。5.x集群需要能够访问1.x集群的rest api接口。
对于每个我们想要迁移到5.x集群的1.x的索引,需要做下面这些事情:
在5.x中创建新的索引,以及使用合适的mapping和setting,将refresh_interval设置为-1,并且设置number_of_replica为0,主要是为了更快的reindex。
用reindex from remote的方式,在两个集群之间迁移index数据
curl -XPOST 'http://localhost:9201/_reindex?pretty' -d ' { "source": { "remote": { "host": "http://localhost:9200" }, "index": "forum" }, "dest": { "index": "forum" } }'
remote cluster必须显示在elasticsearch.yml中列入白名单中,使用reindex.remote.whitelist属性
reinde过程中会使用的默认的on-heap buffer最大大小是100mb,如果要迁移的数据量很大,需要将batch size设置的很小,这样每次同步的数据就很少,使用size参数。还可以设置socket_timeout和connect_timeout,比如下面:
POST _reindex { "source": { "remote": { "host": "http://otherhost:9200", "socket_timeout": "1m", "connect_timeout": "10s" }, "index": "source", "size": 10, "query": { "match": { "test": "data" } } }, "dest": { "index": "dest" } }
如果在后台运行reindex job,就是将wait_for_completion设置为false,那么reindex请求会返回一个task_id,后面可以用来监控这个reindex progress的进度,GET _tasks/TASK_ID
一旦reindex完成之后,可以将refresh_interval和number_of_replicas设置为正常的数值,比如30s和1
一旦新的索引完成了replica操作,就可以删除旧的index了