问题描述
在启动ES服务并试图加入其他节点上已启动的集群时,出现报错(原文是一大段话,我按语义拆成了几段):
[2024-03-19T16:32:02,844][WARN ][o.e.c.s.DiagnosticTrustManager] [node-2-master] failed to establish trust with server at [<unknown host>]; the server provided a certificate with subject name [CN=workerxx], fingerprint [85e5xxx], no keyUsage and extendedKeyUsage [serverAuth];
the certificate is valid between [2024-03-19T02:34:51Z] and [2026-03-19T02:34:51Z] (current time is [2024-03-19T08:32:02.843439860Z], certificate dates are valid);
the session uses cipher suite [TLS_AES_256_GCM_SHA384] and protocol [TLSv1.3]; the certificate has subject alternative names [DNS:localhost,IP:fe80:0:0:0:xxxx:xx:dfc5:1816,IP:192.xx.xx.xxx,IP:0:0:0:0:0:0:0:1,IP:127.0.0.1,IP:fe80:0:0:0:503:d573:42c0:8add,IP:10.xx.xx.xx,DNS:workerxx];
the certificate is issued by [CN=Elasticsearch security auto-configuration HTTP CA]; the certificate is signed by (subject [CN=Elasticsearch security auto-configuration HTTP CA] fingerprint [0439xxx]) which is self-issued;
the [CN=Elasticsearch security auto-configuration HTTP CA] certificate is not trusted in this ssl context ([xpack.security.transport.ssl (with trust configuration: StoreTrustConfig{path=certs/transport.p12, password=<non-empty>, type=PKCS12, algorithm=PKIX})]);
这段日志警告来自Elasticsearch节点node-2-node2
,显示它未能与服务器建立信任连接,具体服务器地址为<unknown host>
。服务器提供的证书包含如下信息:
- 主题名称:CN=workerxx
- 指纹
- 该证书没有指定keyUsage和extendedKeyUsage的serverAuth属性
- 证书日期有效
- 会话使用的加密套件:TLS_AES_256_GCM_SHA384,协议:TLSv1.3
- 证书包含了多个主题备用名称(Subject Alternative Names, SANs),包括localhost和其他几个IP地址以及DNS名称workerxx
- 证书由名为CN=Elasticsearch security auto-configuration HTTP CA的机构颁发
- 签名证书同样是自签发的(self-issued)
问题分析
日志显示,在Elasticsearch节点node-2-master
上出现了SSL握手失败的情况,原因是该节点未能与目标服务器建立信任关系。具体错误是:
当前Elasticsearch节点的SSL上下文(xpack.security.transport.ssl)信任的证书主体也是CN=Elasticsearch security auto-configuration HTTP CA
,但已信任的证书指纹与服务器提供的不一致,造成信任链校验失败。
为了解决这个问题,需要采取以下步骤:
-
确认节点
node-2-master
上的SSL配置文件(在这个例子中是certs/transport.p12
)是否包含正确的、应该被信任的证书及其链。目前,节点信任的证书指纹是c7bd...
,而服务器提供的证书指纹是85e5...
。 -
更新Elasticsearch节点上的信任证书存储以包含正确的CA证书和服务器证书,确保它们能形成有效的信任链。
-
检查并确保所有节点间通信使用的都是同一个信任根CA,并且证书链完整无误。
-
对于Elasticsearch的安全性配置,尤其是
xpack.security.transport.ssl
的部分,应确保所有的节点都有相同且正确的信任设置。
但是,这些证书都是自动生成且直接拷贝到其他节点的,并未进行任何修改。并且还有一个现象就是,与master在同一台机器上的ES实例与其通信时是正常的,不过这也可以推测相同机器用的是本地回环地址进行的通信,故信任链在证书中是生效的。
排查与解决
指纹相关?
尝试使用ssh登录远程节点,并记录远程节点的指纹(询问时回答yes),再次尝试无效。
hosts文件记录错误?
由于我的机器是由两个不同网段接通的,一个千兆,一个万兆,故将本地的/etc/hosts文件中的改为配置文件中填写的千兆IP地址,报错相同。
证书文件损坏?
由于本机器的文件都是从其他节点拷贝来的,可能出现损坏,故重新检查和拷贝一遍后问题依然存在。
重新生成ssl证书并分发?
我重新解压开一个编译包,让它自动生成一份http、Transport的p12证书,然后覆盖到所有需要的节点,结果本地节点仍然可以正常启动组成集群,但是另一个机器还是无法通过信任链校验,无法通信,至此,问题有点陷入僵局的意思。
采用token方案进行观察(解决)
翻看之前搭建集群的记录,似乎不能直接把证书拷贝过去使用。由于之前是采用的token的方案,没有过多配置,我先清空远程节点的discovery相关属性,使用token的方案加入集群观察一下。
主节点先生成token:
./bin/elasticsearch-create-enrollment-token -s node
使用指定token的方式加入集群非常顺利,几乎是秒过!
./bin/elasticsearch -d --enrollment-token eyJ2ZXIiOi...
执行上述命令后节点启动正常,并立即识别了远程master节点,顺利加入集群。
这种方案只修改了以下三个配置:
cluster.name: my-app-es
node.name: node-2-master
node.roles: [master,ingest]
需要注意的是,这个服务由于我指定的是master角色,所以没有指定任何端口。
data节点指定端口的尝试
前面新增了一个master角色,现在尝试增加一个data角色。
修改配置:
cluster.name: my-app-es
node.name: node-2-node1
node.roles: [ data, ingest ]
http.port: 9201
transport.port: 9301
之后启动命令与前述相同,节点也顺利加入了集群。
正常情况的总结
观察上述两个过程,启动前certs目录是没有的,启动后自动生成了证书,并且配置自动修改好,显然这个证书就是本地可用的。
拷贝证书再测试
# 从node1拷贝证书到node2,覆盖node2
cp -r node1/config/certs/ node2/config/
cp node1/config/elasticsearch.keystore node2/config
# 修改node2的配置,主要是增加发现信息,修改端口
cd node2/config/
vim config/elasticsearch.yml
rm -rf data/*
rm -rf logs/*
# 非token方式启动
./bin/elasticsearch -d
这样也是启动成功的,最终集群从3节点变成6个节点了(2主4数),如下图:
总结
所以,绕了一圈SSL证书仅需要在本地生成,踩这个坑主要是由于ES 8.x版本将证书生成进行了自动化(对用户透明了),所以忽略了这一点。这个举措本身是简化用户操作的,因此,建议使用指定token的方式组建集群,不要手动配置证书了。
另外,每个ES节点配置中的发现信息(discovery.seed_hosts
)随着加入集群的顺序而改变,后加入的节点会自动添加前面已在集群内的节点信息,但是手动启动的不会自己变更。最后集群的节点配置各不相同,全部重启也不会同步该信息。