跳转至

IK 中文分词插件安装 —— 执行结果回填

需求规格来源:docs/IK-INSTALL-HANDOFF.md(知识库建设对话移交,2026-10-13)。 执行方:EFK 工程对话。执行时间:2026-10-13 19:05–19:53(CST)。 本文件按需求规格第 7 节的 6 个小节顺序回填,只写结论与关键证据,不含任何口令。


1. 实际改动清单

只改一个文件、只加一条挂载,未改镜像、未动 data 卷内容、未改 Kibana / Filebeat。

  • 文件:manifests/10-elasticsearch.yaml
  • 改动:containers[0].volumeMounts 新增一条(与既有 data 挂载并列)
@@ -115,6 +115,11 @@
           volumeMounts:
             - name: data
               mountPath: /usr/share/elasticsearch/data
+            # IK 中文分词插件落 data PVC 子目录:plugins 目录未单独持久化,
+            # 只做 exec 安装会在容器重建后丢失(见 docs/IK-INSTALL-HANDOFF.md 第 3 节)。
+            - name: data
+              mountPath: /usr/share/elasticsearch/plugins
+              subPath: plugins
   volumeClaimTemplates:

initContainer(fix-data-perms)未改:它 chown/chmod 的是 data 整棵,已覆盖 plugins 子目录。

容器内实测挂载(改后):

192.168.31.249:/srv/nfs/k8s-hdd/pvc-.../plugins on /usr/share/elasticsearch/plugins type nfs4 (rw,...)

插件与词典最终落在 PVC 子目录 /usr/share/elasticsearch/data/plugins/analysis-ik/, 经 subPath: plugins 映射到 /usr/share/elasticsearch/plugins,因此重启不丢。

方案 C 之外的额外动作:elasticsearch-plugin install 未把包内 config/ 目录落盘(详见第 4 节), 故额外从同一 URL 的包中解出 config/ 并拷入 plugins/analysis-ik/config/。这是本方案成立的必要步骤。


2. 备份与时间戳

项 值
备份文件 backup/ik-install-20261013/10-elasticsearch.yaml.bak.20261013-190528
原路径 manifests/10-elasticsearch.yaml
备份时间 2026-10-13 19:05(CST)
子目录台账 backup/ik-install-20261013/README.md(含回滚步骤)
主台账 backup/README.md 第 14 条

备份与原件比对结果:diff -q 为空(备份即变更前原件)。


3. 验收结果

# 验收项 判据 实测结果 判定
A1 插件已安装 elasticsearch-plugin list 含 analysis-ik analysis-ik 通过
A2 中文分词生效 _analyze 用 ik_smart 切词 知识库/搭建/方案(ik_max_word 另出 知识/库) 通过
A3 持久化 再重启后 A1/A2 仍成立 重启 #5 后 list 仍为 analysis-ik、分词仍正确 通过
A4 ES 健康 _cluster/health green/yellow,Pod 1/1 yellow、active_primary_shards=156/156、elasticsearch-0 1/1 Running 通过
A5 EFK 无扰动 Kibana 可达、Filebeat 正常、已存索引仍在 Kibana /api/status=200;4 个 Filebeat Pod 均 Running;索引文档数不降反增 通过
A6 可回滚 回滚后 ES 正常、IK 不再加载 挂载 0 条、list 为空、ik_smart 报 400;ES 本身正常 通过

关键输出(原文摘录):

# A2(ik_smart)
{"tokens":[{"token":"知识库",...},{"token":"搭建",...},{"token":"方案",...}]}
# A2(ik_max_word)
{"tokens":[{"token":"知识库",...},{"token":"知识",...},{"token":"库",...},{"token":"搭建",...},{"token":"方案",...}]}
# A4
"status":"yellow","active_primary_shards":156,"unassigned_primary_shards":0
# A5:索引文档数对比(变更前 → 末态)
.ds-filebeat-8.19.0-2026.10.13-...      751934 → 785407
.ds-filebeat-host-8.19.0-2026.10.13-... 265449 → 275424
.security-7                                270 → 270   (green)
kibana_status_http=200
# A6
plugins 挂载条数 = 0 | plugin list = (空) | ik_smart = 400 failed to find global analyzer

A5 说明:变更期间 ES 有约 14 分钟的不可用窗口(详见第 4 节),Filebeat 期间按重试堆积并回补, 已存日志无丢失,且两日索引文档数在窗口后继续增长,符合规格书 K3 的预期。


4. 遇到的问题与绕过方式

4.1 主问题:安装器未落 config/ 目录 → 分词不可用,且集群 red

现象:插件安装并重启后,plugin list 显示 analysis-ik,但 _analyze 报

null_pointer_exception: Cannot invoke "...DictSegment.match(char[], int, int)" because
"org.wltea.analyzer.dic.Dictionary.singleton._StopWords" is null

ES 日志给出根因:

java.io.FileNotFoundException: /usr/share/elasticsearch/plugins/analysis-ik/config/surname.dic (No such file or directory)
  at org.wltea.analyzer.dic.Dictionary.loadSurnameDict(Dictionary.java:545)
  at org.wltea.analyzer.dic.Dictionary.initial(Dictionary.java:148)
  at com.infinilabs.ik.elasticsearch.ConfigurationSub.<init>(ConfigurationSub.java:26)

根因:elasticsearch-plugin install <url> 只把 jar 与描述文件装进插件目录, zip 包内的 config/ 目录(含 main.dic / surname.dic / stopword.dic 等 12 个词典与 IKAnalyzer.cfg.xml)未落盘; 容器内全盘检索 *.dic 为 0 条,config/analysis-ik 亦不存在。

影响面超出预期:IK 的 tokenizer factory 在 AnalysisRegistry.build 阶段被实例化, 其构造失败会让索引创建失败(.security-7 亦被波及),使集群一度进入 red (156 个 primary 中最多 111 个 unassigned)。这不只是分词不可用,而是日志检索整体中断约 14 分钟。

绕过:从同一 URL下载的 zip 中解出 config/,拷入 PVC 上的 plugins/analysis-ik/config/,重启即恢复:

curl -sL -o /tmp/ik-8.19.0.zip https://get.infini.cloud/elasticsearch/analysis-ik/8.19.0
python3 -c "import zipfile;zipfile.ZipFile('/tmp/ik-8.19.0.zip').extractall('/tmp/ik-extract')"
kubectl -n monitoring exec elasticsearch-0 -c elasticsearch -- \
  mkdir -p /usr/share/elasticsearch/plugins/analysis-ik/config
kubectl -n monitoring cp /tmp/ik-extract/config/. \
  monitoring/elasticsearch-0:/usr/share/elasticsearch/plugins/analysis-ik/config -c elasticsearch
kubectl -n monitoring rollout restart sts/elasticsearch

遗留影响:词典在 PVC 上是手工补的,日后重装/升级该插件必须重复此步(见第 6 节)。 建议:把 plugins/analysis-ik/config 一并纳入 PVC 备份策略,或改造成 initContainer 幂等补齐。

4.2 过程性失误(已纠正,不影响结论)

首次执行 A6 回滚时,kubectl apply -f 用了相对路径,而终端工作目录是工程上级目录, 两次 apply 均未命中文件(报 path does not exist),该轮回滚实际未生效。 随后改用绝对路径重做,A6 结果以第 3 节为准。

4.3 非问题(勿误读为报错)

ES 日志中下列两行为 IK 的正常 INFO 记录,不是错误:

try load config from /usr/share/elasticsearch/config/analysis-ik/IKAnalyzer.cfg.xml
try load config from /usr/share/elasticsearch/plugins/analysis-ik/config/IKAnalyzer.cfg.xml

安装时另有 ES 8.18+ 的 Entitlements 提示(legacy Security Policy file / outbound_network), 属新安全机制下的兼容提醒,不影响本插件功能;升级 ES 大版本时需重新取匹配版本的 IK 包。


5. 回滚实测

已真跑过(2026-10-13 19:39–19:50 CST),分两段:

段 动作 实测结果
回滚 kubectl apply -f backup/ik-install-20261013/10-elasticsearch.yaml.bak.20261013-190528 + 等就绪 plugins 挂载 0 条;plugin list 为空;ik_smart 返回 400(analyzer 不存在);ES 自身正常
恢复 kubectl apply -f manifests/10-elasticsearch.yaml + 等就绪 plugin list 回到 analysis-ik;分词恢复正常

回滚步骤与 backup/ik-install-20261013/README.md 第 2 节一致。 回滚后 PVC 内残留的 plugins/ 目录不影响 ES 运行(容器不再挂载它)。


6. 遗留项与后续建议

# 事项 说明
1 重装插件必须补 config/ 见 4.1。建议在重装流程中固化为一步,或将词典纳入 PVC 备份
2 PVC 回收策略为 Delete data PVC 若被删除(工程 rollback --force),插件与词典一并消失,需按本文件重新安装
3 升级 ES 需重取 IK 包 版本号必须与 ES 一致;本次为 8.19.0
4 知识库侧建索引 拟名 knowledge,字段用 ik_max_word、查询用 ik_smart,由知识库工程负责;本工程只保证插件可用且持久
5 未做自定义词典 当前用 IK 自带词典;如需业务词表,利用 IKAnalyzer.cfg.xml 的 ext_dict(文件位于 PVC 上,改动后需重启)
6 未给存量索引加 IK 映射 按规格书第 8 节边界,未改动 EFK 存量检索行为

来源:/home/rain/Documents/k8s_ins/monitoring-p2-20261001/docs/IK-INSTALL-RESULT.md | 最后更新:2026-10-13 19:49(由 build/sync.py 同步,请勿在站点侧修改)