ElasticSearch跑起来很容易,但让它安全地跑在生产环境里,每一步都可能是一个坑。尤其是从零配置TLS证书和密码认证这个事,网上教程不少,但要么只讲单节点,要么直接假设你已经懂了一堆前置概念,真正能照着做完、做对的并不多。这篇文章我把自己的实操过程完整拆开,从证书规划、生成到集群配置、Kibana接入,再到常见问题的排查,一步步讲清楚,希望能帮你少走弯路。
先说结论:ElasticSearch集群的安全加固,核心就是两件事——加密传输(TLS)和身份认证(密码/RBAC)。TLS解决的是“数据在网络上裸奔”的问题,密码认证解决的是“谁都能访问你的集群”的问题。两者缺一不可。如果你只是在内网跑个Demo,也许觉得无所谓,但只要集群开始承载真实业务数据,或者需要多人协作、跨部门共享,安全检查就是一道绕不过去的门槛。而且从ElasticSearch 8.0开始,安全默认开启,如果你还在用7.x的老方案,升级之后可能直接连不上集群,这也是很多人踩坑的地方。
我个人建议不管版本新旧,都按这篇文章的思路从头捋一遍,因为你很可能在某个环节遇到过类似的问题:节点之间通信失败、Kibana登录报错、证书过期导致集群不可用……这些我都经历过,下面会把解决过程和思路一起写出来。
1. 安全加固的前置认知:认证、TLS、RBAC到底解决什么问题
在动手配置之前,必须先搞清楚ElasticSearch的安全模型到底由哪几部分组成。很多人一上来就急着生成证书、改配置,结果遇到报错完全不知道问题出在哪一层,就是因为脑子里没有这张“安全地图”。
1.1 三层安全体系:传输层、用户层、数据层
ElasticSearch的安全体系可以拆成三个层面:
传输层安全(TLS):负责加密节点之间、节点与客户端之间的通信。解决的是“中间人攻击”和“数据明文传输”的问题。你可以类比为寄快递时用加密箱子,即使快递中途被人截走,也看不到里面的内容。
用户认证(Authentication):确认“你是谁”。ElasticSearch内置了用户名密码体系,也可以对接LDAP、SAML等外部认证源。解决的是“谁都能访问”的问题。
权限授权(Authorization/RBAC):确认“你能干什么”。通过角色(Role)给用户分配具体的索引权限、集群操作权限。解决的是“越权访问”的问题。
这三层缺一不可。只配了TLS没有认证,等于快递箱子很坚固但大门敞开;只配了认证没有TLS,用户名密码在网络上裸奔,分分钟被截获。
1.2 为什么从6.x/7.x升级到8.x后,集群突然连不上了
很多团队遇到过这种情况:升级到ElasticSearch 8.x之后,原来用http://IP:9200直接访问的Kibana突然连不上了,用curl访问也提示证书错误。原因很简单——从8.0开始,ElasticSearch默认启用安全特性,自动生成自签证书和随机密码。
但这里有个关键点:ES 8.x自动生成的安全配置只适用于单节点新集群。如果你是从7.x升级过来的,或者要搭建多节点集群,自动生成的配置就不够用了,需要手动规划和重建安全配置。这篇文章的实操部分,虽然命令是从零开始,但思路同样适配升级场景,区别只是你需要先处理旧证书和旧配置残留。
1.3 先画出你的访问拓扑图
在动手之前,建议你先画一张简单的拓扑图,明确谁需要访问集群:
- 集群内部节点之间的通信(Transport 9300端口)
- Kibana连接ElasticSearch(HTTP 9200端口)
- Logstash/Beats等数据采集端连接ElasticSearch
- 开发人员/运维人员通过Kibana或API访问
不同的访问者影响证书规划。比如节点间通信需要配置Transport TLS,Kibana只需要HTTP层TLS。如果你的Kibana和ES不在同一台机器,Kibana本身也要配置访问ES的HTTPS地址和账号密码。这张图不用画得多标准,自己看得懂就行,但一定要画,它决定了你后面配置文件的每一项。
2. 证书规划与生成:CA、节点证书、实例证书的关系
证书是整个TLS加密的基础。很多教程直接让你用elasticsearch-certutil一键生成,但生成出来的东西到底分几种、每种的用途是什么,很多人并不清楚。这里我把证书体系彻底讲透。
2.1 证书体系:为什么需要私有CA
先理解一个概念:公开的HTTPS网站用的是CA(证书颁发机构)签发的证书,比如你访问网银时浏览器能自动信任。但ElasticSearch集群一般跑在内网,申请公网CA证书不现实,所以我们需要自己搭建一个私有CA,用这个私有CA去签发集群各节点的证书。
私有CA的作用是“自己人认自己人”。集群里的每个节点都信任这个私有CA,那么由它签发的证书在集群内部就具有公信力。你可以把CA理解为一个单位的公章,节点证书是盖了公章的工作证。
ElasticSearch提供了专门的工具来生成和管理这些证书:elasticsearch-certutil。这个工具随ElasticSearch安装包自带,不需要额外安装。
2.2 证书类型选择:节点证书还是实例证书
elasticsearch-certutil最核心的两个子命令是:
cert:生成节点证书(Node Certificate),用于节点间Transport通信csr:生成证书签名请求,适合对接外部CAhttp:生成HTTP层证书(实例证书),用于Kibana、客户端访问ES时的HTTPS加密
多节点集群的典型做法是:先用ca子命令生成私有CA,再用cert基于这个CA签发节点证书,同时用http生成HTTP证书。如果你把所有功能混在一张证书里,也不是不能用,但管理和轮换时会很麻烦。
实话说,8.x版本里elasticsearch-certutil在证书生成环节做了很多自动化,比如cert命令默认会生成包含节点私钥和证书的p12文件,并且支持把节点IP和域名都写进SAN(Subject Alternative Name)里。但正因为太自动化,很多人反而搞不清楚目录里那些文件分别是什么。
2.3 证书生成实操:完整命令与关键参数
下面我用一套完整的命令演示如何从零生成证书。假设我要搭建一个3节点集群,节点内网IP分别是:
- 10.0.0.11(es-node-1)
- 10.0.0.12(es-node-2)
- 10.0.0.13(es-node-3)
- Kibana独立部署在10.0.0.20
第一步:生成私有CA
bin/elasticsearch-certutil ca --pem --out ca.zip这里加--pem是为了生成PEM格式的CA证书和私钥,方便后续在多个节点间分发。执行后会提示设置CA私钥密码,生产环境建议设置。生成的是一个zip包,解压后包含ca.crt和ca.key两个文件。
第二步:生成节点证书
bin/elasticsearch-certutil cert \ --ca ca.zip \ --pem \ --out node-cert.zip \ --name node-cert \ --dns es-node-1,es-node-2,es-node-3 \ --ip 10.0.0.11,10.0.0.12,10.0.0.13这个命令基于刚才生成的CA,为三个节点签发证书。--dns和--ip参数会把节点的主机名和IP写入证书的SAN字段,客户端校验时会比对访问地址是否在SAN中。生产环境这两个参数务必填全,哪怕暂时不用域名,IP也一定要填对。
注意:
--pem生成的证书是PEM格式(crt/key),而不是p12格式。两种格式在ES中都可以使用,但我个人建议节点证书用PEM格式,HTTP证书用p12格式,原因是PEM便于用openssl查看和排查,p12便于Kibana等Java应用直接加载。
第三步:生成HTTP证书
bin/elasticsearch-certutil http --pem这个命令会进入交互式问答,包括:
- 是否生成CSR?选n
- 是否使用已有CA?选y,然后输入CA证书和私钥路径
- 证书有效期(默认3年),按需调整
- 需要覆盖哪些主机名和IP?这里填写所有需要访问ES的主机名/IP,包括Kibana访问地址
- 是否将证书打包到zip?选y
生成的zip解压后,http.p12或http.crt/http.key就是HTTP层要用的证书文件。
2.4 elasticsearch.yml 证书路径配置
证书生成后,需要把相关文件复制到各节点的config/certs/目录下,然后在elasticsearch.yml中声明路径。以节点1为例:
xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.keystore.path: certs/transport-cert.p12 xpack.security.transport.ssl.truststore.path: certs/transport-cert.p12 xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: certs/http.p12 xpack.security.http.ssl.truststore.path: certs/http.p12很多新手在这里会混淆keystore和truststore的区别。简单理解:keystore是你的身份证明(包含私钥和证书),truststore是你信任的CA列表(用于校验别人发来的证书)。节点间通信时,双方既要出示自己的keystore,又要用truststore验证对方。p12格式的文件可以同时充当keystore和truststore,所以上面两个路径填的是同一个文件。
这里还有一个verification_mode参数需要特别说明。它有三个取值:
- full:校验证书链和主机名
- certificate:只校验证书链,不校验主机名
- none:不做校验(仅在调试时用)
生产环境官方建议用full,但full要求证书SAN里必须包含节点的主机名,且节点之间通过主机名互相访问,不能直接写IP。如果你内网DNS解析不完善,可以退而求其次用certificate,配合IP访问,同时在证书SAN里把IP填全。
3. 集群配置:启用安全特性与密码认证
证书准备好了,接下来就是把ElasticSearch集群的安全开关打开。这一部分最容易出问题,因为每个节点的配置都要保持一致,漏了一个节点就可能导致整个集群无法形成。
3.1 集群节点的 elasticsearch.yml 完整配置
三节点集群的配置本质上只有两处不同:节点名称和网络地址。下面以节点1为例,展示完整的elasticsearch.yml安全相关配置:
# 集群基础配置 cluster.name: es-prod-cluster node.name: es-node-1 network.host: 10.0.0.11 # 节点发现 discovery.seed_hosts: - 10.0.0.11 - 10.0.0.12 - 10.0.0.13 cluster.initial_master_nodes: - es-node-1 - es-node-2 - es-node-3 # 安全认证 xpack.security.enabled: true # Transport 层TLS(节点间通信) xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.keystore.path: certs/transport-cert.p12 xpack.security.transport.ssl.truststore.path: certs/transport-cert.p12 # HTTP 层TLS(客户端/Kibana访问) xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: certs/http.p12 xpack.security.http.ssl.truststore.path: certs/http.p12节点2和节点3的配置基本一样,只需把node.name和network.host改成对应的值。
如果某个环节报证书校验失败,优先检查所有节点的transport-cert.p12文件是否完全一致、CA是否匹配。这个文件必须从同一套CA签发,不能各自生成各自的,否则节点之间互不信任。
3.2 使用 elasticsearch-keystore 管理密码
启用了安全认证之后,ElasticSearch启动时要求必须有内置用户密码。密码不是直接写在elasticsearch.yml里的——这是很多人的误区——而是通过elasticsearch-keystore命令写入本地密钥库。
# 在第一个节点上执行,创建并设置内置用户密码 bin/elasticsearch-setup-passwords interactiveelasticsearch-setup-passwords会有两种模式:
- interactive:逐个输入内置用户的密码
- auto:自动生成随机密码并在终端显示
建议在第一个节点上执行,并选择interactive。它会把所有内置用户的密码写入该节点的keystore,并且不会自动同步到其他节点,所以后续需要手动把密码同步到其他节点。
内置用户包括:
| 用户名 | 作用 |
|---|---|
| elastic | 超级用户,用于管理集群 |
| kibana_system | 供Kibana连接ES使用 |
| logstash_system | 供Logstash监控使用 |
| beats_system | 供Beats采集使用 |
| apm_system | 供APM Server使用 |
| remote_monitoring_user | 供监控采集使用 |
这里要特别注意:
elastic这个用户是超级管理员,密码务必妥善保存。kibana_system是Kibana用来连接ES的专用账号,不要在Kibana里用elastic登录去配数据视图,权限模型上会绕很多弯。
如果是升级场景,要执行的是:
bin/elasticsearch-setup-passwords interactive --force不加--force的话,如果检测到集群已经配置过密码,会拒绝执行。加了这个参数意味着覆盖旧密码,需要同步更新所有依赖旧密码的外部系统。
3.3 数据节点重启顺序与集群收敛
配置改完之后,必须重启集群。重启顺序有讲究:
- 先逐个重启数据节点,确认每个节点重启后都能正常加入集群
- 再重启Kibana
- 最后验证Logstash/Beats等数据管道
如果一次性把三个节点全重启,集群短暂处于无主状态,虽然ES的脑裂保护机制能兜底,但在生产环境这种行为不值得冒险。逐个重启的好处是:每个节点起来后能从集群里拿到最新状态,万一配置有问题,也容易定位是哪个节点没起来。
4. 密码认证的客户端全接入:Kibana、Logstash与Java应用
集群安全加固不是配完ES就结束了,所有访问ES的客户端都要跟着适配。这里分别讲清Kibana、Logstash和普通Java应用如何接入启用TLS与密码认证的集群。
4.1 Kibana接入HTTPS与kibana_system账号
Kibana这边需要修改两个地方:config/kibana.yml里的ES地址和账号。
server.host: "0.0.0.0" server.port: 5601 elasticsearch.hosts: ["https://10.0.0.11:9200", "https://10.0.0.12:9200", "https://10.0.0.13:9200"] elasticsearch.username: "kibana_system" elasticsearch.password: "你设置的密码" elasticsearch.ssl.certificateAuthorities: [ "/path/to/ca.crt" ] elasticsearch.ssl.verificationMode: fullKibana默认是信任所有证书的,但生产环境不建议这么做。elasticsearch.ssl.certificateAuthorities指定CA证书路径后,Kibana会用它来校验ES节点证书链的有效性。verificationMode建议设置成full,因为Kibana访问ES时用的是主机名或IP,full会一并校验SAN。
有一个很多人踩过的坑:Kibana配置里的密码是明文。如果对安全要求严格,建议用Kibana的keystore功能保存密码:
bin/kibana-keystore create bin/kibana-keystore add elasticsearch.password这样密码会写入Kibana的本地keystore,kibana.yml里就不需要出现明文密码了。虽然这不能算绝对的安全(keystore本身也能被本机管理员读取),但至少避免了密码随配置文件分发而泄露。
4.2 Logstash接入:SSL证书与user/password配置
Logstash接入ES需要改output插件配置。假设你的Logstash要往ES写数据:
output { elasticsearch { hosts => ["https://10.0.0.11:9200", "https://10.0.0.12:9200", "https://10.0.0.13:9200"] user => "logstash_system" password => "你设置的密码" ssl_certificate_verification => true cacert => "/path/to/ca.crt" } }这里面的user建议用logstash_system或者单独为数据管道创建的用户,不要直接拿elastic超级用户在生产环境跑数据管道。权限最小化是一个基本的安全习惯,万一凭证泄露,影响面可控。
Logstash的cacert参数指向CA证书,用于校验ES节点证书链。如果你忘了配这个,默认Logstash也会尝试校验证书,然后在日志里报一堆SSL验证失败的错,很多新手在这里卡住。
4.3 Java应用访问ES:TrustStore与RestClient配置
Java应用通过RestClient访问ES时,麻烦一点,因为需要把CA证书导入Java的TrustStore。
keytool -importcert -noprompt \ -alias elastic-ca \ -file ca.crt \ -keystore truststore.jks \ -storepass changeit然后在Java代码里配置:
final SSLContext sslContext = SSLContextBuilder.create() .loadTrustMaterial(new File("/path/to/truststore.jks"), "changeit".toCharArray()) .build(); RestClientBuilder builder = RestClient.builder( new HttpHost("10.0.0.11", 9200, "https"));如果是Spring Boot项目,用RestHighLevelClient或ElasticsearchClient,配置方式类似,核心都是把CA证书塞进TrustStore。这里要留意JKS和PKCS12格式的兼容性,现在JDK默认用PKCS12也能直接兼容JKS,但老项目里遗留的JKS文件要确认能正常加载。
5. 常见问题与排查技巧实录
配置过程中我前前后后踩过不少坑,这里挑代表性的记录一下排查思路。这些问题如果你也遇到了,按下面的顺序排查,能少消耗不少无谓的时间。
5.1 证书校验失败的排查:不只是看路径
现象:节点启动时日志报错,节点之间无法互相通信,错误信息类似包含“unable to find valid certification path to requested target”的SSL握手异常。
排查步骤:
- 确认所有节点的
transport-cert.p12文件来自同一套CA。最简单的方法是对比各节点文件的MD5,以及用openssl查看证书指纹 - 确认
elasticsearch.yml里的verification_mode设置。如果证书SAN里没有包含主机名,full模式会直接拒绝握手;可以先临时改成certificate验证问题是否出在主机名校验上 - 查看ES日志的完整报错,注意是客户端证书问题还是服务端证书问题。前者通常是某个节点的私钥不对,后者通常是信任链没建立
实用命令:
openssl x509 -in http.crt -text -noout | grep -A 1 "Subject Alternative Name"这条命令能快速查看证书的SAN字段,确认你填的IP和域名都在里面。SAN漏填导致的校验失败是我遇到过的最常见的证书类问题。
5.2 密码认证失败的常见原因:bootstrap密码与keystore
现象:执行elasticsearch-setup-passwords时报错,提示无法连接集群或认证失败。
排查要点:
elasticsearch-setup-passwords必须连接到一个运行中的集群节点,且该节点已完成初始化。如果集群还没起来,或者你只在某个节点上配置了安全但没有形成集群,这个命令会失败- 如果你的集群之前已经配置过安全,再次执行时需要加
--force。不加会提示密码已存在 - 如果你通过环境变量设置了
ELASTIC_PASSWORD,那么该密码只对当前节点的elastic用户生效,不代表所有内置用户都有密码。两种方式不能混用,建议统一走elasticsearch-setup-passwords interactive
5.3 Kibana连接正常但页面始终显示“Kibana server is not ready”
这个问题的常见原因是kibana_system账号密码配置错误,或者Kibana无法用HTTPS方式连上ES。
排查方法:
- 先看Kibana日志,有没有“status red”或者“license”类错误。Kibana和ES之间的证书校验失败往往会直接导致红色状态
- 在Kibana机器上手动用curl验证ES是否可访问:
curl -k -u kibana_system:密码 https://10.0.0.11:9200/如果curl能正常返回集群信息,说明ES端没问题,问题在Kibana配置;如果curl也报错,先解决ES端网络和证书问题
- 确认Kibana配置的
elasticsearch.hosts使用的是HTTPS协议。漏写s是最容易犯的低级错误
5.4 证书到期后的集群“雪崩”:提前规划轮换
证书都有有效期,默认3年左右。证书到期那天,节点间TLS握手全部失败,集群表现为大量节点被标记为不可用,Kibana直接红色。这个坑我亲眼见过,也和同事一起处理过,处理过程非常狼狈。
所以建议在证书到期前3个月就制定轮换计划。ElasticSearch支持热更新部分证书,不需要重启节点,但Transport层的证书更新往往还是需要滚动重启。实操中我倾向于设置一个定时任务,每两个月检查一次证书有效期,并在到期前90天发告警。
openssl x509 -in transport-cert.pem -noout -dates把检查命令做成脚本,输出到监控系统当作指标,是最省心也最稳妥的做法。
6. 一些real world建议和扩展方向
配置完TLS和密码认证只是安全加固的第一步。即使全部跑通,我也建议你持续关注以下几个方面——这些是在实际集群里维护安全时绕不开的问题,也给想进一步提升的读者留个方向。
第一,内置用户密码的轮换机制。安全策略齐全不代表密码不用换。建议每90天轮换一次内置用户密码,尤其是elastic和kibana_system。轮换时要按依赖关系倒序执行:先更新Kibana/Logstash等客户端的密码配置,再执行elasticsearch-setup-passwords --force更新ES侧密码,避免出现客户端先失效、服务端后更新的空窗期。
第二,审计日志的开启。ElasticSearch支持开启审计日志(audit log),记录谁在什么时间做了什么操作。在多人协作的团队中,这一步极其重要。配置方式是在每个节点上开启:
xpack.security.audit.enabled: true默认会记录所有事件,日志量较大,建议在索引和保留策略上提前规划,把审计日志单独投递到一个独立索引,设置较长的保留周期。
第三,不要把安全当作一次性工作。集群扩容、节点替换、所在机房迁移都会涉及证书和密码的重新适配。每次变更前先复盘证书体系,确认新节点能和存量节点互信。与其在故障时紧急处理,不如在变更前把安全检查项列成清单,逐项过一遍。
第四,考虑对接统一认证源。当集群规模大了以后,每增加一个人就要在ES里手动建用户,角色和权限管理成本会指数级上升。这时候可以考虑对接LDAP或者Active Directory。ES的xpack.security.authc.realms配置支持多种外部认证源,对接后用户和角色统一管,密码也由公司统一策略把控。ELK生态里还有一个叫“服务账号”的机制,适合机器对机器的调用场景,比在代码里写死普通用户密码要安全得多。
安全加固不是一个一劳永逸的步骤,而是一个需要持续维护的工程。最后分享一个小习惯:我会把所有证书的到期时间、所覆盖的节点列表、对应的CA文件位置整理成一份专门的“证书台账”,每次变更后更新。几次下来,面对审计和意外故障时会从容很多。希望这篇实战文章能帮你把ElasticSearch集群的安全底座打好,少踩几个我踩过的坑。