在AWS中,我有一个Sping Boot 应用程序在Docker容器中的ECS Fargate中运行,我使用CloudFormation部署了它。在同一个VPC(具有两个子网)中,我部署了一个带有单个示例的DocumentDB集群。当使用MongoDB(内存中和Docker映像)在本地运行时,Spring Boot应用程序连接良好(分别在IDE和使用Docker Compose)。
在CloudFormation中,我将DocumentDB示例作为Sping Boot 环境参数注入ECS容器定义中:
- Name: SPRING_DATA_MONGODB_HOST
Value: !GetAtt DbCluster.Endpoint
- Name: SPRING_DATA_MONGODB_PORT
Value: !GetAtt DbCluster.Port
当我部署CloudFormation堆栈时,我可以在控制台中转到DocumentDB集群,并看到它显示数据库集群主机如下所示:foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com
密码存储在Secrets Manager中并附加到数据库;该密钥显示相同的主机名。
我可以转到同一VPC中的Cloud9示例,并使用mongosh
连接到foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com
。
当我的Sping Boot 示例启动时,它的日志显示: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, …
请注意,数据库集群主机Sping Boot 使用的是我从Cloud9连接到的同一个。
但最终Sping Boot 应用程序超时: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任务,以为数据库可能还没有初始化,但结果还是一样。
在Cloud 9中,nslookup foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com
解析为VPC内的IP地址。与ECS服务关联的安全组(AWS::EC2::SecurityGroup
)没有定义出口,因此默认允许所有出口在任何端口上的任何位置(我刚刚通过控制台确认)。
如果Sping Boot 、Document DB和Cloud9都在同一个VPC中运行,那么为什么Cloud9可以很好地连接到foo-bar-xxxxxxxxxxxx.us-east-1.docdb.amazonaws.com
,但Spring Boot ECS Fargate示例却不能?我应该在哪里寻找?
我还应该提到我正在使用Service Connect,其中,我设置了Cloud Map命名空间example.internal
,并为ECS服务启用了Service Connect,端口名称为my-service
。我知道Service Connect设置了某种sidecar“代理”容器,与我的任务容器一起运行。此Service Connect代理是否以某种方式阻止了我的服务传出请求?我是否需要做进一步的操作来允许服务连接到数据库集群?
2条答案
按热度按时间1l5u6lss1#
超时错误表示ECS无法连接到DocumentDB,因此需要检查DocumentDB安全组的Ingress规则是否允许ECS连接
mum43rcc2#
简单的答案是DocumentDB示例被配置为使用SSL/TLS,但Sping Boot Data MongoDB显然默认不支持SSL/TLS。(我很感谢https://stackoverflow.com/a/66807514提醒我这种可能性。)
最好的办法是在Sping Boot 中启用SSL/TLS,但我不知道如何在AWS中使用CloudFormation以完全自动化的方式做到这一点。(如果你知道如何做到这一点,请让我知道,但我想我必须花几天时间自己研究它,因为到目前为止我看到的例子都是“手动做这个做那个”,这是不可接受的。因此,在此期间,您可以使用CloudFormation在DocumentDB集群上关闭SSL/TLS。
如果你走这条路,请确保你的DocumentDB集群没有公共入口。(没有双关语。)最好是将Sping Boot 应用程序和DocumentDB集群放在私有子网中。(当然,更好的是在Spring Boot应用程序中启用SSL/TLS。)
首先,你不能使用自动创建的
default.docdb4.0
,因为它启用了TLS。创建一个自定义的AWS::DocDB::DBClusterParameterGroup
:然后在
AWS::DocDB::DBCluster
中引用它: