VictoriaLogs vector 采集报 TLS 证书验证失败的排查记录
记录时间:2026-09-23
环境:测试集群(二进制部署 K8s 1.28.15,麒麟 V10 SP3,ARM64,Docker 28.0.4 + cri-dockerd,3 master + 3 node);VictoriaLogs 集群 helm chart victoria-logs-cluster 0.2.8(v1.52.0);chart 自带 vector 0.57.0-distroless-libc
一、问题现象
VictoriaLogs 集群部署完成后,开启 chart 自带的 vector(DaemonSet)采集容器日志。Pod 全部 Running,但日志采集一直不入库。看 vector Pod 日志,kubernetes_logs source 在反复重试,报错核心信息:
Watcher Stream received an error. Retrying. error=InitialListFailed(...)
X509VerifyResult { code: 18, error: "self-signed certificate" }
我的第一反应:测试集群是二进制部署的自签证书环境,八成是 vector 连 apiserver 的 TLS 链路有问题。
二、排查过程
vector 报错后我先查了它的机制:kubernetes_logs source 经 K8s API 取 Pod 元数据,默认走 in-cluster 配置。查官方 issue 发现 vector 有个已知问题(#15725):它的 kube-rs 客户端走 in-cluster 时不加载 SA 卷的 ca.crt,自签 CA 集群会验证失败,需要显式挂 kubeconfig。我按官方建议挂了 kubeconfig(内嵌集群 CA),报错还是原封不动。
于是我在 master 节点直接验证证书链:
echo | openssl s_client -connect 192.168.120.51:6443 -CAfile /etc/kubernetes/ssl/ca.pem 2>&1 | grep "Verify return"
Verify return code: 18 (self signed certificate)
连 master 本机用集群自己的 CA 都验证不过 apiserver 证书。到这里确定了,问题在 apiserver 证书本身,不在 vector。顺着证书查下去定位到根因(见下节),修完证书后 vector 正常采集入库。
三、根因分析
cfssl 签发的证书不带 AKI,叠加 CA 与证书 subject 撞名,触发 openssl 的”无 AKI 且 issuersubject 即自签”判定规则,openssl 系客户端全部验证失败。
| 层 | 结论 |
|---|---|
| 集群证书体系 | 没坏。apiserver 旧证书是 ca.pem 合法签发的 |
| vector 自身 | 有已知缺陷(issue #15725),in-cluster 不加载 SA 卷 ca.crt,必须显式 kubeconfig |
| 根因 | cfssl 无 AKI + subject 撞名 + openssl 启发式判定,三者叠加 |
三组对照实验把这个结论钉死了(同一张 ca.pem、同一套 cfssl 签发流程、同样不带 AKI,唯一变量是证书 subject 是否与 CA 撞名):
openssl verify -CAfile /etc/kubernetes/ssl/ca.pem /etc/etcd/ssl/etcd.pem
# /etc/etcd/ssl/etcd.pem: OK(CN=etcd,不撞名)
openssl verify -CAfile /etc/kubernetes/ssl/ca.pem /etc/kubernetes/ssl/kube-controller-manager.pem
# OK(CN=system:kube-controller-manager,不撞名)
openssl verify -CAfile /etc/kubernetes/ssl/ca.pem /etc/kubernetes/ssl/kube-apiserver.pem.bak.0923
# error 18 at 0 depth lookup: self signed certificate(CN=kubernetes,撞名)
不撞名的全过、撞名的报 18,说明 cfssl 签的证书签名没有问题,是 openssl 的判定规则在撞名场景误判。
四、解决方案
- vector 侧(永久依赖):kubeconfig ConfigMap 挂载 +
kube_config_file显式指定(绕 vector 自身缺陷);certificate-authority-data内嵌 ca.pem(集群标准信任)。文件已落仓库victoria-logs/xc-test/vector-kubeconfig.yaml - 集群侧(治本):openssl 原生重签三台 apiserver 证书(含 SKI/AKI/SAN),证书+私钥成对滚动替换,详见部署笔记《二进制部署K8s1.28集群(arm64版).md》的「证书签发与滚动替换」章节
- 新部署方案(演进定稿):apiserver 证书 CN 改为 kube-apiserver(kubeadm 标准),与 CA 不撞名后 cfssl 签发即可,不再需要 openssl 特殊命令;同步改 conf 的
--requestheader-allowed-names=kube-apiserver(聚合层联动)。部署笔记正文已按此定稿
五、验证
# 三台 master 全部通过(治本完成的标志)
for h in 51 52 53; do echo "== host$h =="; echo | openssl s_client -connect 192.168.120.$h:6443 -CAfile /etc/kubernetes/ssl/ca.pem 2>&1 | grep "Verify return"; done
# 预期三行 Verify return code: 0 (ok)
# 全集群证书终验(2026-09-23 实测全 OK)
for f in /etc/kubernetes/ssl/*.pem; do
case "$f" in *key.pem|*ca.pem) continue;; esac
openssl verify -CAfile /etc/kubernetes/ssl/ca.pem "$f" 2>&1 | head -1
done
# admin / kube-apiserver(openssl 重签版)/ controller-manager /
# kubelet-client / kube-proxy / kube-scheduler 全部 OK
# 旧证书备份 .pem.bak.0923 不匹配 *.pem 未被列出,单独验过报 18(撞名实锤)
# vector 采集入库(流字段花括号快查)
curl -s -u <vmauth账号>:<vmauth密码> "http://<vmlogs入口域名>/select/logsql/query" \
-d 'query={kubernetes.pod_namespace="monitoring"}' | head -c 1500
六、注意事项
- 二进制部署环境新组件接入先查它的 TLS 栈:Go 系客户端与 openssl 系客户端对同一张证书的验证结论可能相反,不要用”kubectl 正常”推断”证书没问题”
- 控制面证书替换必须证书+私钥成对操作,且两者都要先备份。漏私钥 apiserver 起不来,报错是
private key does not match public key - 证书重签的生死判据是
openssl verify -CAfile ca.pem <证书>出 OK,出不了 OK 绝不替换进集群 - vector 的 kubeconfig ConfigMap 更新后 Pod 不会自动重载(进程启动时只读一次),需要重建 Pod
- 无 CA 可用时,可以把服务器证书本身当信任锚临时兜底,但终态必须回归 CA 信任
七、参考资料
- vector issue #15725:kubernetes_log error for self signed certificate
- vector kubernetes_logs source 官方文档
- VictoriaLogs 官方文档
- 部署笔记:
/Users/glj/bendibiji/kubernetes/二进制部署K8s1.28集群(arm64版).md