前言

在 Kubernetes 日志平台中,Kibana 无法登录是一个比较常见但又容易误判的问题。
很多时候,表面现象看起来像是账号密码错误,实际上问题可能出在 Kibana 与 Elasticsearch 之间的 HTTPS 证书链上。

这次故障的核心问题,就是 Elasticsearch 证书过期,导致 Kibana 无法完成 TLS 校验,最终表现为平台登录失败。

本文记录一次完整的排查与修复过程,供后续类似问题参考。


一、环境说明

本次环境部署在 Kubernetes logging 命名空间,主要组件包括:

  • Elasticsearch

  • Kibana

  • Filebeat

资源类型如下:

  • StatefulSet/elasticsearch-master

  • Deployment/kibana-kibana

  • DaemonSet/filebeat-filebeat

这说明当前环境属于 自建 / Helm + StatefulSet 部署模式,而不是 ECK Operator 托管模式。
这一区别非常重要,因为自建模式下 证书不会自动轮换,需要手工维护。


二、问题现象

现场故障表现如下:

  1. Kibana 页面可以打开,但输入账号密码后无法正常登录

  2. Elasticsearch、Kibana、Filebeat 的 Pod 基本都在运行

  3. Kibana 日志中持续出现以下报错:

certificate has expired
unable to verify the first certificate

从现象上看,很容易误以为是:

  • 用户名密码错误

  • Elasticsearch 认证异常

  • Kibana 自身故障

但实际上,这类报错已经明确指向了 TLS 证书校验失败


三、问题分析

1. 为什么 Kibana 无法登录

Kibana 的登录认证并不是完全独立完成的。
用户在页面输入账号密码后,Kibana 需要调用 Elasticsearch 进行认证。

如果 Kibana 与 Elasticsearch 之间的 HTTPS 连接存在问题,比如:

  • 证书过期

  • CA 不受信任

  • 证书链不完整

那么认证请求在真正校验账号密码之前,就已经失败了。

也就是说,这次“无法登录”并不是典型的账号问题,而是 Kibana 无法通过 HTTPS 正常连接 Elasticsearch


2. 证书是否真的过期

为了确认是不是证书问题,首先查看 Elasticsearch 当前实际加载的证书:

curl -k -u elastic:你的密码 https://10.233.52.179:9200/_ssl/certificates?pretty

返回结果显示,当前加载的以下证书都已过期:

  • /usr/share/elasticsearch/config/certs/ca.crt

  • /usr/share/elasticsearch/config/certs/tls.crt

这一步基本可以直接定性:

Elasticsearch 当前挂载的 CA 证书和服务端证书都已过期。


3. 证书来自哪里

继续查看 Elasticsearch 的 StatefulSet 配置:

kubectl -n logging get sts elasticsearch-master -o yaml | egrep -A5 -B2 "secretName:|mountPath:|xpack.security|ssl"

可以确认:

  • 证书挂载目录为 /usr/share/elasticsearch/config/certs

  • 使用的 Secret 为 elasticsearch-master-certs

  • HTTP 和 Transport 层都使用该 Secret 中的:

    • ca.crt

    • tls.crt

    • tls.key

这说明问题已经非常明确:

本次故障的根因,就是 elasticsearch-master-certs 这套证书已过期。


四、解决思路

由于本次不只是服务端证书 tls.crt 过期,连签发它的 ca.crt 也已经过期,因此不再适合继续沿用旧 CA。

正确的处理方式是:

  1. 重新生成新的 CA

  2. 使用新的 CA 重新签发 Elasticsearch 证书

  3. 更新 Kubernetes Secret

  4. 重启 Elasticsearch

  5. 重启 Kibana,使其重新加载新的 CA 信任链


五、解决过程

1. 确认资源状态

先确认环境中的组件状态:

kubectl get all -n logging

确认当前环境为自建 StatefulSet/Deployment 模式,而非 ECK。


2. 确认 Elasticsearch 当前证书已过期

curl -k -u elastic:你的密码 https://10.233.52.179:9200/_ssl/certificates?pretty

确认:

  • ca.crt 已过期

  • tls.crt 已过期


3. 确认证书 Secret 来源

kubectl -n logging get sts elasticsearch-master -o yaml | egrep -A5 -B2 "secretName:|mountPath:|xpack.security|ssl"

确认 Elasticsearch 使用的证书 Secret 为:

elasticsearch-master-certs

4. 在 Elasticsearch Pod 中生成新证书

进入 Elasticsearch Pod:

kubectl -n logging exec -it elasticsearch-master-0 -- bash

创建工作目录:

mkdir -p /tmp/es-cert-renew
cd /tmp/es-cert-renew

创建实例配置文件:

cat > instances.yml <<'EOF'
instances:
  - name: elasticsearch-master
    dns:
      - elasticsearch-master
      - elasticsearch-master.logging
      - elasticsearch-master.logging.svc
      - elasticsearch-master.logging.svc.cluster.local
      - elasticsearch-master-0
      - elasticsearch-master-0.elasticsearch-master-headless
      - elasticsearch-master-0.elasticsearch-master-headless.logging
      - elasticsearch-master-0.elasticsearch-master-headless.logging.svc
      - elasticsearch-master-0.elasticsearch-master-headless.logging.svc.cluster.local
    ip:
      - 10.233.52.179
EOF

生成新的 CA:

/usr/share/elasticsearch/bin/elasticsearch-certutil ca --pem --days 1095 --out /tmp/es-cert-renew/ca.zip
unzip -o /tmp/es-cert-renew/ca.zip -d /tmp/es-cert-renew/ca

使用新 CA 生成 Elasticsearch 证书:

/usr/share/elasticsearch/bin/elasticsearch-certutil cert --pem \
  --ca-cert /tmp/es-cert-renew/ca/ca/ca.crt \
  --ca-key /tmp/es-cert-renew/ca/ca/ca.key \
  --days 1095 \
  --in /tmp/es-cert-renew/instances.yml \
  --out /tmp/es-cert-renew/es.zip

unzip -o /tmp/es-cert-renew/es.zip -d /tmp/es-cert-renew/es
find /tmp/es-cert-renew -type f | sort

5. 导出新证书到宿主机

mkdir -p /root/es-cert-renew-20260415
cd /root/es-cert-renew-20260415

kubectl -n logging exec elasticsearch-master-0 -- cat /tmp/es-cert-renew/ca/ca/ca.crt > ca.crt
kubectl -n logging exec elasticsearch-master-0 -- cat /tmp/es-cert-renew/es/elasticsearch-master/elasticsearch-master.crt > tls.crt
kubectl -n logging exec elasticsearch-master-0 -- cat /tmp/es-cert-renew/es/elasticsearch-master/elasticsearch-master.key > tls.key

检查新证书:

openssl x509 -in ca.crt -noout -dates -subject -issuer
openssl x509 -in tls.crt -noout -dates -subject -issuer

6. 备份并更新 Elasticsearch Secret

先备份原有 Secret:

kubectl -n logging get secret elasticsearch-master-certs -o yaml > /root/elasticsearch-master-certs.bak.yaml

然后更新 Secret:

kubectl -n logging create secret generic elasticsearch-master-certs \
  --from-file=ca.crt=ca.crt \
  --from-file=tls.crt=tls.crt \
  --from-file=tls.key=tls.key \
  --dry-run=client -o yaml | kubectl apply -f -

7. 重启 Elasticsearch

kubectl -n logging rollout restart statefulset/elasticsearch-master
kubectl -n logging rollout status statefulset/elasticsearch-master
kubectl -n logging get pod -n logging -w

重启后,Elasticsearch 一度出现 Running 0/1,但继续查看日志后发现:

  • 节点已正常启动

  • 已完成主节点选举

  • 9200/9300 已正常监听

  • 索引已恢复

  • Elasticsearch 已进入 started 状态

说明证书更新已经成功,只是 readiness probe 在等待集群状态恢复。


8. 再次验证 Elasticsearch 新证书是否生效

curl -k -u elastic:你的密码 https://10.233.52.179:9200/_ssl/certificates?pretty

确认新证书的有效期已经更新。


9. 检查 Kibana 的 CA 配置

查看 Kibana Deployment:

kubectl -n logging get deploy kibana-kibana -o yaml | egrep -A8 -B3 "elasticsearch.ssl|ELASTICSEARCH|certificateAuthorities|verificationMode|secretName|mountPath"

确认 Kibana 已配置:

  • ELASTICSEARCH_HOSTS=https://elasticsearch-master:9200

  • ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=/usr/share/kibana/config/certs/ca.crt

并且挂载的 Secret 也是:

elasticsearch-master-certs

说明 Kibana 的证书信任路径本身没有问题。


10. 重启 Kibana

虽然 Secret 已经更新,但 Kibana 进程仍可能继续持有旧的 TLS 信任状态,因此需要重启 Kibana:

kubectl -n logging rollout restart deployment/kibana-kibana
kubectl -n logging rollout status deployment/kibana-kibana
kubectl -n logging get pod -n logging -w

11. 验证 Kibana 日志和登录情况

查看 Kibana 最新日志:

kubectl -n logging logs deploy/kibana-kibana --tail=200 | egrep "certificate|x509|security_exception|unable to verify|No living connections|expired|SSL|tls"

确认以下错误已消失:

certificate has expired
unable to verify the first certificate

随后再次访问 Kibana 页面,确认已恢复正常登录。


六、处理结果

最终结果如下:

  • Elasticsearch 新证书已成功生效

  • Kibana 已重新加载新的 CA 证书

  • Kibana 不再报证书校验错误

  • 平台恢复正常登录


七、经验总结

这次问题有几个典型经验:

1. 自建 Elasticsearch 证书不会自动续期

只要不是 ECK,就必须自己维护证书生命周期。

2. Kibana 登录失败不一定是账号问题

出现 certificatex509unable to verify 时,应优先排查 TLS 证书链。

3. 更新 ES 证书后,Kibana 也需要同步处理

即使 Kibana 配置没问题,也需要重启以重新加载新的 CA。

4. 建议建立证书到期告警

至少应对以下证书设置提前预警:

  • Elasticsearch HTTP 证书

  • Elasticsearch CA 证书

  • Kibana 对外证书

  • Ingress / 代理层证书


结语

这次故障的本质并不复杂,但排查过程中很容易被“登录失败”这个表象误导。
真正的问题并不是账号本身,而是 Kibana 与 Elasticsearch 之间的 HTTPS 信任链失效

遇到类似问题时,建议优先确认三件事:

  1. Elasticsearch 当前实际加载的证书是否过期

  2. Kibana 是否信任当前 CA

  3. 证书更新后,相关组件是否已重启并重新加载配置

把这三步走清楚,问题基本都能快速收敛。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐