K8s部署ElasticSearch与外部SpringBoot连接遇ConnectionClosedException
解决SpringBoot连接ECK部署Elasticsearch时的ConnectionClosedException问题
问题根源
ECK部署的Elasticsearch集群默认使用自签名SSL证书,外部SpringBoot应用的RestClient如果未配置信任该证书,会在SSL握手阶段失败,最终表现为连接关闭异常。
解决步骤
1. 导出Elasticsearch集群的CA证书
从Kubernetes集群中导出ECK生成的CA证书:
# 替换<your-es-cluster-name>为你的Elasticsearch集群名称 kubectl get secret <your-es-cluster-name>-es-ca-internal -o jsonpath='{.data.ca\.crt}' | base64 -d > es-ca.crt
2. 配置SpringBoot信任该证书
方式一:通过自定义信任库配置
先创建包含ES CA证书的信任库:
# 设置信任库密码,替换your-truststore-password为自定义密码 keytool -importcert -file es-ca.crt -alias es-ca -keystore es-truststore.jks -storepass your-truststore-password
然后在SpringBoot启动参数中指定信任库:
-Djavax.net.ssl.trustStore=path/to/es-truststore.jks -Djavax.net.ssl.trustStorePassword=your-truststore-password
方式二:在RestClient配置类中直接加载证书
将导出的es-ca.crt放入SpringBoot项目的resources目录,然后编写配置类:
import org.apache.http.HttpHost; import org.apache.http.ssl.SSLContextBuilder; import org.elasticsearch.client.RestClientBuilder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.net.ssl.SSLContext; import java.io.InputStream; import java.security.KeyStore; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @Configuration public class ElasticsearchConfig { @Bean public RestClientBuilder restClientBuilder() throws Exception { // 加载CA证书 CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream certInputStream = getClass().getResourceAsStream("/es-ca.crt"); X509Certificate cert = (X509Certificate) cf.generateCertificate(certInputStream); // 构建信任库 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null); trustStore.setCertificateEntry("es-ca", cert); // 创建SSL上下文 SSLContext sslContext = SSLContextBuilder.create() .loadTrustMaterial(trustStore, null) .build(); // 配置RestClient return RestClient.builder(new HttpHost("localhost", 9200, "https")) .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder.setSSLContext(sslContext)) .setDefaultHeaders(new org.apache.http.Header[]{ new org.apache.http.message.BasicHeader("Authorization", "Basic " + java.util.Base64.getEncoder().encodeToString(("elastic:your-password").getBytes())) }); } }
替换代码中的your-password为Elasticsearch的elastic用户密码,localhost:9200为port-forward暴露的地址。
3. 验证版本兼容性
7.17.6客户端与7.16.2服务端属于同一大版本,理论上兼容,但如果上述配置后仍有问题,可尝试将客户端版本降级至7.16.2,保持与服务端版本一致。
4. 确认网络连通性
确保kubectl port-forward命令持续运行,用curl测试连通性:
curl -u elastic:your-password --cacert es-ca.crt https://localhost:9200
若curl能正常返回集群信息,说明网络与证书配置无问题,再排查SpringBoot代码细节。
内容的提问来源于stack exchange,提问作者Tony Cavanagh
相关产品推荐
相关产品推荐

