5.0 的插件改动有 14 条,但哪条对你有影响,取决于
plugins目录里装了什么。bin/plugin改名bin/elasticsearch-plugin、插件 zip 必须带顶层elasticsearch/目录、isolated选项删除(每个插件独立 classloader)、site 插件删除、multicast 插件删除、Cloud AWS/Azure/GCE 拆分改名,另外有一批插件接口从onModule(XxxModule)换成XxxPlugin。本文按 v5.6.16 逐条列出,并标出哪些是配置改动、哪些要重写插件。
说明
实测环境:本地 Elasticsearch 5.6.16 官方 tar 包(配 .eslab/jdk 下的 JDK 8),用 bin/elasticsearch-plugin 命令行工具做检查;测试插件在 /tmp 下临时构造,装完立即卸载,发行版的 plugins 目录跑完是空的。
来源和边界先交代:本文的依据出自 v5.6.16 标签下的官方文件(plugins.asciidoc、ListPluginsCommand.java、PluginCli.java),文中引用的原文均来自这些文件。示例取自官方示例;哪些是文档写明、哪些是我的推断,正文里逐处标注。

图 1:官方文件 plugins.asciidoc(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 plugins.asciidoc
命令行与包结构
5.0 迁移文档(migrate_5_0/plugins.asciidoc 第 4–7 行)开篇:
The command
bin/pluginhas been renamed tobin/elasticsearch-plugin. The structure of the plugin ZIP archive has changed. All the plugin files must be contained in a top-level directory calledelasticsearch. If you use the gradle build, this structure is automatically generated.
两处变化:
- 命令名:
bin/plugin install x改成bin/elasticsearch-plugin install x,部署脚本里的调用都要改; - 包结构:插件 zip 内所有文件必须在顶层
elasticsearch/目录下。用 gradle 构建的会自动生成这个结构,手工打包的要注意。
同一节后面还有两条和命令行相关(第 103–113 行):
- 以前可以把
-D形式的参数直接传给 plugin 脚本来传 Java 系统属性,5.0 起不允许,必须通过ES_JAVA_OPTS传; - 通过
path.plugins指定自定义插件目录的能力被删除。

图 2:官方文件 ListPluginsCommand.java(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 ListPluginsCommand.java
isolated 选项删除
isolatedoption has been removed. Each plugin will have its own classloader.
以前安装插件时可以加 --isolated 让它拥有独立的 classloader,避免和核心或其他插件的类冲突。5.0 起这不是可选项,每个插件都有自己的 classloader。
对使用者的影响是去掉 --isolated 参数;对插件作者来说,依赖被核心同类库覆盖的问题不再需要自己处理。

图 3:官方文件 PluginCli.java(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 PluginCli.java
被删除或替换的几类插件
| 变更 | 官方说法(原文要点) |
|---|---|
| Site 插件删除 | 应改用 Kibana 插件实现(第 13–16 行) |
| Multicast 插件删除 | 改用 unicast 发现或某个云发现插件(第 18–21 行) |
| Delete-By-Query 插件删除 | 改用核心的 Delete By Query API,支持节流、重试、取消,但不再支持 timeout,改取消 API(第 92–96 行) |
| Mapper Attachments 插件废弃 | 改用 ingest-attachment 插件(第 98–101 行) |
| Cloud AWS 拆分 | 拆成 discovery-ec2 和 repository-s3(第 40–45 行) |
| Cloud Azure 拆分 | 拆成 discovery-azure-classic、repository-azure、store-smb(第 56–62 行) |
| Cloud GCE 改名 | 改名 discovery-gce(第 88–90 行) |
AWS 拆分之外,代理设置也一起改名了(第 47–54 行),六组:
cloud.aws.proxy_host -> cloud.aws.proxy.host
cloud.aws.ec2.proxy_host -> cloud.aws.ec2.proxy.host
cloud.aws.s3.proxy_host -> cloud.aws.s3.proxy.host
cloud.aws.proxy_port -> cloud.aws.proxy.port
cloud.aws.ec2.proxy_port -> cloud.aws.ec2.proxy.port
cloud.aws.s3.proxy_port -> cloud.aws.s3.proxy.port
Azure 那条还带一个配置结构变化:原来 cloud.azure.storage 下面直接写 account 和 key,5.0 起要给它一个 id,因为可以定义多个存储账户:
cloud:
azure:
storage:
my_account:
account: your_azure_storage_account
key: your_azure_storage_key
site 插件影响的是一类用法:用插件提供静态页面。升级后这类页面全部不可用,替代方案要提前想好,这是能力没了,不是改个配置能解决的。
multicast 从 2.0 起已经降级为插件,5.0 连插件也没有。必须显式配置 discovery.zen.ping.unicast.hosts,或者用云环境发现插件。对零配置测试集群是体验退化,对生产是收敛:集群成员关系变可预期。
自定义查询/评分函数插件的接口变更
这一条只影响插件开发者,但改动不小(第 23–38 行):
Plugins implementing custom queries need to implement the
fromXContent(QueryParseContext)method in theirQueryParsersubclass rather thanparse. [...] Also, the query builder needs to be registered as aNamedWriteable. This is all done by implementing theSearchPlugininterface and overriding thegetQueriesmethod.The query object can then transform itself into a lucene query through the new
toQuery(QueryShardContext)method, which returns a lucene query to be executed on the data node.
核心是把"解析"和"执行"拆成两段:
fromXContent(QueryParseContext):从请求体解析出一个中间表示,这个中间表示就是 Java API 里的查询对象,并且要注册为NamedWriteable,以便节点间二进制传输;toQuery(QueryShardContext):在数据节点上把这个对象转成真正可执行的 Lucene 查询。
评分函数插件同理:ScoreFunctionParser 实现 fromXContent,函数对象通过 toFunction(QueryShardContext) 转成 Lucene function。
这么改的原因是协调节点负责解析、数据节点负责执行,两者之间传输的必须是可序列化的查询对象,而不是"解析完直接生成 Lucene 对象"。这样自定义查询才能像内置查询一样在集群里传输、缓存、分片级执行。
一批插件接口从 onModule 换成 XxxPlugin
同一节后半段是一批接口改动(第 115–154 行):
| 插件做什么 | 5.0 做法 | 要删掉的 |
|---|---|---|
| 注册自定义脚本 | 实现 ScriptPlugin |
onModule(ScriptModule) |
| 注册自定义分析组件 | 实现 AnalysisPlugin |
onModule(AnalysisModule) |
| 注册自定义 mapper | 实现 MapperPlugin |
onModule(IndicesModule) |
| 注册自定义 action | 实现 ActionPlugin |
onModule(ActionModule) |
注册自定义 RestHandler |
实现 ActionPlugin |
onModule(NetworkModule) |
| 注册自定义检索行为(Query、Suggester、ScoreFunction、FetchSubPhase、Highlighter 等) | 实现 SearchPlugin |
onModule(SearchModule) |
另外两条:
SearchParseElement接口删除。自定义搜索请求段只能放在ext元素下,插件通过SearchPlugin.SearchExtSpec(SearchExtParser解析 XContent 成SearchExtBuilder)接入;解析现在发生在协调节点,结果随搜索请求序列化到数据节点,存在搜索上下文里供后续取用;- 测试相关:
ESIntegTestCase#pluginList删除,改用Arrays.asList,理由是所有插件都要求 Java 1.8 之后不再需要它。
最后还有一条容易被忽略的数据侧影响(第 161–164 行):mapper-size 插件的 _size 元字段,对 2.x 创建的索引,在聚合、脚本、排序里不可访问。需要这些功能要用 5.x 重新索引数据。
自研插件怎么评估
原文里"5.0 把 AbstractSearchScript 换成 SearchScript、构造签名变了"这类说法未逐条核实,以官方迁移文档为准(文档里这一节写的是 ScriptPlugin 与 onModule 的替换)。不管具体是哪一个扩展点,评估自研插件可以按这几步:
- 先看这个扩展点在不在上面那张表里。在的话,改动量主要是把
onModule换成对应的XxxPlugin; - 确认这个插件还有没有必要存在。有些自定义查询、评分逻辑后来有了官方能力(衰减函数、Painless 脚本能直接表达的逻辑等),能替代的就别再维护自研插件;
- 自研插件依赖 ES 内部类,而内部类跨版本没有兼容承诺,每次大版本升级都可能要改。插件数量应当当成一项技术债来管理:每加一个都要有明确理由(官方能力确实做不到),并记录它依赖了哪些内部类,下次升级时才能估改动量。
部署脚本里要改的地方
# 命令名变了
bin/plugin install x # 5.0 之前
bin/elasticsearch-plugin install x # 5.0 起
# --isolated 参数删了(现在每个插件本来就隔离)
bin/elasticsearch-plugin install x --isolated # 删掉参数即可
# Java 系统属性不再能直接传给 plugin 脚本
bin/plugin -Des.some.property=x ... # 5.0 之前
ES_JAVA_OPTS="-Des.some.property=x" bin/elasticsearch-plugin install x # 5.0 起
排查范围不只是部署脚本:
- Dockerfile 里的安装命令;
- Ansible / Puppet / Chef 的插件安装步骤;
- 启动脚本里的插件检查逻辑(比如判断某个插件是否已安装);
- 文档和 Runbook 里的命令(照着复制的人会踩坑)。
最后一类最容易漏,因为没人会去执行文档里的命令验证。全局搜 bin/plugin、--isolated、path.plugins,把所有命中处一起改掉。
升级检查清单
- 先列出每个节点实际安装的插件(见下一节),再对照本文各条;
- 脚本里
bin/plugin全量替换成bin/elasticsearch-plugin; - 自研插件检查压缩包结构(顶层
elasticsearch/目录),去掉--isolated; - 传
-D系统属性的改成ES_JAVA_OPTS;用了path.plugins的改回默认插件目录; - 清点 site 插件,寻找 Kibana 插件或独立工具替代;
- 还在用 multicast 的集群改成 unicast 显式配置;
cloud-aws按用途换成discovery-ec2/repository-s3,并按新名字改代理设置;cloud-azure拆成三个并给存储账户加 id;cloud-gce改名discovery-gce;- delete-by-query 插件换成核心 API,去掉 timeout 参数的用法;
- mapper-attachments 换成
ingest-attachment; - 自研插件按上面的对照表换成
XxxPlugin;自定义查询/评分按SearchPlugin+fromXContent+toQuery/toFunction重写; - 2.x 创建的索引如果在聚合、脚本、排序里用了
_size,规划重新索引。
先列插件,再读清单
插件相关的改动麻烦在它依赖你装了什么插件。官方列的变更对有没有影响,取决于 plugins 目录里有什么。
所以排查的第一步是先列一遍实际安装的插件,变更列表留到后面读,再逐个对照,没装的那些可以直接跳过。这一节能省不少时间:变更列表有十几条,实际用到的插件也许只有两三个,做完这个过滤,剩下要细看的只有少数几条。
# 每个节点上已安装的插件
bin/elasticsearch-plugin list
# 通过 API 看各节点的插件情况
curl -s 'localhost:9200/_cat/plugins?v'
list 是 elasticsearch-plugin 的子命令之一(ListPluginsCommand、PluginCli),_cat/plugins 在 5.6.16 里也有(RestPluginsAction)。
顺着一个思路再想一层:插件是升级风险的主要来源之一。核心功能的变更官方会重点说明、社区讨论也多;插件的变更容易被忽略,而且不同插件的维护状态差异很大,有的跟着主版本走,有的长期不更新。
所以给插件做一次清点,不只是为了这次升级:
- 哪些是必需的(业务依赖);
- 哪些是历史遗留(当初试过、现在没人用);
- 哪些已经不再维护。
我的判断是第三类最值得处理:它们迟早会成为升级的阻塞项,早处理比晚处理便宜。清掉之后集群启动更快,故障面也更小。
在 5.6.16 上跑一遍
「先看装了什么,再对照改动」这个顺序,用一次目录检查和一次插件安装就能走完。

图 4:5.6.16 的 bin/ 里只有 elasticsearch-plugin 与 elasticsearch-plugin.bat,bin/plugin 显示 MISSING;elasticsearch-plugin list 输出为空(没装任何插件)。本地实测输出。

图 5:构造一个 site=true 的 plugin-descriptor.properties(放在 zip 的顶层 elasticsearch/ 目录下)后,elasticsearch-plugin install 回 -> Installed test-site,list 里出现 test-site,remove 后列表重新为空。本地实测输出。
ls -1 bin/ | grep -i plugin
# elasticsearch-plugin
# elasticsearch-plugin.bat
bin/elasticsearch-plugin list
# (空)
命令改名这一条验得很直接:5.6.16 里根本没有 bin/plugin 这个文件,部署脚本中残留的 bin/plugin install x 会直接 command not found。图 5 同时也把「zip 必须带顶层 elasticsearch/ 目录」走了一遍——本次正是按这个结构打包才装上的。
有一处与官方说法对不上,原样记在这里:官方把 site 插件列为「删除」,升级后静态页面不可用;本机 5.6.16 却能把 site=true 的插件装得上、也列得出来。安装成功不等于页面还能访问——本机没有起节点去请求插件提供的静态资源,所以「下线」到底指不再 serve 页面,还是连安装都不允许,本地判断不了。这一条挂起,不替官方圆,也不据这次安装结果推翻原文。
结论是清点时不能只看 install 是否成功,还得按用途验证能力还在不在。我的建议是升级前把 elasticsearch-plugin list 的结果逐项对照 14 条改动,脚本里的 bin/plugin 全量替换;对 site 类插件单独起一次实例、实际请求一下页面,再决定用 Kibana 插件还是独立工具替代。
边界:
- 图 4、图 5 出自 5.6.16 的命令行工具,只验了
install/list/remove,没有起节点验证插件加载或静态页面; - 测试插件只写了最小的 descriptor,没有 Java 类,安装后能否被节点正常加载未实测;
--isolated、path.plugins、multicast 与云插件拆分、插件接口重写等条目未逐个验;- 5.0 之前没有对应版本二进制,
bin/plugin的实际形态未做运行期对照。
写在最后
5.0 的插件改动分成三层:命令行和包结构(bin/elasticsearch-plugin、顶层 elasticsearch/ 目录、ES_JAVA_OPTS、path.plugins 删除),插件的存废(site、multicast、delete-by-query、mapper-attachments、三个云插件的拆分改名),插件接口(XxxPlugin 取代 onModule、SearchPlugin 加 fromXContent 加 toQuery、SearchParseElement 删除)。
前两层改配置和脚本,第三层要改代码。我的建议是先列一遍装了什么插件,能直接跳过大部分条目。
参考
本文对照 Elasticsearch
v5.6.16标签的官方文档核对,引文逐字取自原文。「在 5.6.16 上跑一遍」里已实际检查 bin 目录(bin/plugin不存在、只有elasticsearch-plugin)并装/卸过一个测试插件(见该节)。本次实测与官方「site 插件删除」不完全一致:site=true的插件在 5.6.16 上仍能安装并列出,本机未起节点验证静态页面是否可用,该条挂起、未据此下结论。--isolated、path.plugins等其余条目与 5.0 之前的形态未实测。