同VPC下Spring Boot ECS服务无法连接DocumentDB集群排查求助
我在AWS环境中通过CloudFormation部署了运行在ECS Fargate Docker容器内的Spring Boot应用,同时在同一VPC(含两个子网)中部署了单实例DocumentDB集群。本地使用MongoDB(内存版和Docker镜像)时,Spring Boot应用可正常连接(IDE和Docker Compose环境均测试通过)。
在CloudFormation的ECS容器定义中,我注入了DocumentDB实例作为Spring Boot的环境参数:
- Name: SPRING_DATA_MONGODB_HOST Value: !GetAtt DbCluster.Endpoint - Name: SPRING_DATA_MONGODB_PORT Value: !GetAtt DbCluster.Port
部署完成后,DocumentDB集群的主机地址类似:foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com,密码存储在Secrets Manager并关联至数据库,秘钥中的主机地址与集群地址一致。
同一VPC内的Cloud9实例可通过mongosh正常连接该DocumentDB集群,执行nslookup foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com也能解析到VPC内的IP地址。
Spring Boot实例启动日志显示其已正确加载DocumentDB地址:
2023-04-11T23:18:39.610Z INFO 1 --- [ main] org.mongodb.driver.client : MongoClient with metadata {"driver": {"name": "mongo-java-driver|sync|spring-boot", "version": "4.8.2"}, "os": {"type": "Linux", "name": "Linux", "architecture": "amd64", "version": "5.10.173-154.642.amzn2.x86_64"}, "platform": "Java/Eclipse Adoptium/17.0.6+10"} created with settings MongoClientSettings{… clusterSettings={hosts=[foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com:27017], srvServiceName=mongodb, mode=SINGLE, …
但最终应用出现连接超时错误:
org.springframework.dao.DataAccessResourceFailureException: Timed out after 30000 ms while waiting to connect. Client view of cluster state is {type=UNKNOWN, servers=[{address=foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com:27017, type=UNKNOWN, state=CONNECTING, exception={com.mongodb.MongoSocketReadTimeoutException: Timeout while receiving message}, caused by {java.net.SocketTimeoutException: Read timed out}}]
我已尝试重启ECS任务,排除数据库未初始化的可能;ECS服务关联的安全组未定义出站规则,默认允许所有端口的出站流量(已通过控制台确认)。
核心疑问
既然Spring Boot、DocumentDB和Cloud9都运行在同一VPC中,为何Cloud9可正常连接DocumentDB,而Spring Boot ECS Fargate实例却无法连接?应从哪些方面排查?
另外,我使用了ECS Service Connect,已设置Cloud Map命名空间example.internal,并为ECS服务启用了Service Connect(端口名为my-service)。Service Connect的sidecar代理容器是否会阻止服务的出站请求?是否需要额外配置以允许服务连接数据库集群?
一、DocumentDB安全组入站规则检查
Cloud9能连接说明DocumentDB的安全组允许Cloud9实例的安全组访问27017端口,但ECS任务的安全组是否被允许?
- 登录AWS控制台,找到DocumentDB集群关联的安全组,检查入站规则:是否添加了ECS服务安全组的ID,允许27017端口的TCP流量。
- 注意:即使ECS出站全开放,DocumentDB的入站规则必须明确允许ECS任务的来源安全组,否则连接会被阻断。
二、ECS任务的子网路由配置
ECS Fargate任务所在的子网,其路由表是否配置了VPC内网路由?
- 确认子网的路由表中,针对VPC CIDR范围的流量是通过
local路由转发,而非指向互联网网关(IGW)。DocumentDB的私有DNS解析后是VPC内网IP,若路由错误会导致流量走公网,进而被阻断。
三、Service Connect的代理配置影响
Service Connect的sidecar代理默认不会阻止所有出站请求,但需要确认以下两点:
- 出站流量是否被代理拦截并需要配置允许规则:
- Service Connect默认只管理服务间通过Cloud Map发现的流量,直接访问外部(如DocumentDB)的流量默认不受代理影响,但需检查是否自定义了代理的出站规则。
- 若使用了Service Connect的
outboundConfiguration,需确保未限制对DocumentDB端口27017的访问。
- 代理是否占用或干扰了MongoDB驱动的网络连接:
- 检查Spring Boot容器的网络模式:ECS Fargate使用
awsvpc网络模式,sidecar代理与主容器共享网络命名空间,需确认代理未占用27017端口(但MongoDB驱动是出站连接,这点概率较低)。
- 检查Spring Boot容器的网络模式:ECS Fargate使用
四、MongoDB驱动的DocumentDB兼容性配置
DocumentDB与标准MongoDB存在部分兼容性差异,需确认Spring Boot的MongoDB驱动是否配置了适配参数:
- 检查是否添加了
spring.data.mongodb.uri参数,明确指定ssl=true(DocumentDB默认要求SSL连接),例如:spring.data.mongodb.uri=mongodb://<username>:<password>@foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com:27017/?ssl=true&sslInvalidHostNameAllowed=true - 注意:若仅配置了
host和port,可能未启用SSL,导致连接被DocumentDB拒绝(表现为超时)。
五、Secrets Manager的凭证是否正确注入
虽然主机地址正确,但需确认数据库用户名和密码是否正确注入到Spring Boot容器中:
- 查看ECS任务的环境变量,确认是否包含
SPRING_DATA_MONGODB_USERNAME和SPRING_DATA_MONGODB_PASSWORD,且值与Secrets Manager中的一致。 - 若凭证错误,也可能导致连接超时(部分数据库会静默阻断错误凭证的连接请求)。
内容的提问来源于stack exchange,提问作者Garret Wilson

