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同步,请勿在站点侧修改)