本地通过EC2隧道连接AWS DocDB报错,求排查方案
问题描述
我有一台EC2实例(EC2_VM),可从该实例连接MongoDB(MONGO_HOST)。使用以下Python代码通过SSH隧道从本地连接:
with sshtunnel.open_tunnel( (EC2_VM, 22), ssh_username="ec2-user", ssh_pkey=EC2_KEY, remote_bind_address=(MONGO_HOST, 27017), local_bind_address=("0.0.0.0", 27017), ) as tunnel: print(tunnel.local_bind_port) # list database names client = MongoClient( "mongodb://%s:%s@%s" % (MONGO_USER, MONGO_PASSWORD, "127.0.0.1"), port=tunnel.local_bind_port, ) names = client.list_database_names() print(names)
运行后出现超时错误:
File "/lib/python3.11/site-packages/pymongo/topology.py", line 269, in _select_servers_loop raise ServerSelectionTimeoutError( pymongo.errors.ServerSelectionTimeoutError: 127.0.0.1:27017: timed out, Timeout: 30s, Topology Description: <TopologyDescription id: 6530a0a24577402c25f1997e, topology_type: Unknown, servers: [<ServerDescription ('127.0.0.1', 27017) server_type: Unknown, rtt: None, error=NetworkTimeout('127.0.0.1:27017: timed out')>]>
隧道看似成功建立,但无法连接MongoDB。另外想请教:有AWS DocDB部署经验的话,如何从本地通过脚本连接?MongoDB Compass的GUI隧道功能可正常使用,但pymongo脚本无法连接,盼解答。
解决方案
一、EC2 SSH隧道连接MongoDB的问题排查
1. 修复端口匹配问题
你设置了local_bind_address=("0.0.0.0", 27017),但如果本地27017端口已被占用,隧道会自动分配其他随机端口。代码中打印了tunnel.local_bind_port,但连接时仍指定27017,导致端口不匹配。
修正后的代码(自动分配端口):
with sshtunnel.open_tunnel( (EC2_VM, 22), ssh_username="ec2-user", ssh_pkey=EC2_KEY, remote_bind_address=(MONGO_HOST, 27017), # 移除local_bind_address,让系统自动分配可用端口 ) as tunnel: print(f"本地绑定端口: {tunnel.local_bind_port}") client = MongoClient( f"mongodb://{MONGO_USER}:{MONGO_PASSWORD}@127.0.0.1:{tunnel.local_bind_port}" ) names = client.list_database_names() print(names)
2. 验证EC2到MongoDB的连通性
登录EC2实例,执行以下命令确认EC2能访问MongoDB的27017端口:
telnet MONGO_HOST 27017 # 或 nc -zv MONGO_HOST 27017
如果这一步不通,说明EC2安全组或MongoDB防火墙限制了访问,需先调整规则打通这层连接。
3. 开启隧道调试日志排查
添加日志输出,确认隧道是否真的成功建立:
import logging logging.basicConfig(level=logging.DEBUG) with sshtunnel.open_tunnel( (EC2_VM, 22), ssh_username="ec2-user", ssh_pkey=EC2_KEY, remote_bind_address=(MONGO_HOST, 27017), ) as tunnel: # 原有连接代码
通过日志可排查SSH连接、远程端口绑定是否存在异常。
二、本地脚本连接AWS DocDB的方法
DocDB兼容MongoDB协议,但强制要求SSL连接,需注意以下配置:
1. 完整连接脚本示例
import sshtunnel from pymongo import MongoClient # 替换为你的实际参数 EC2_VM = "ec2-xxx-xxx-xxx-xxx.compute-1.amazonaws.com" EC2_KEY = "/path/to/your/ec2-key.pem" DOCDB_HOST = "docdb-cluster-xxx.cluster-xxx.us-east-1.docdb.amazonaws.com" DOCDB_USER = "admin" DOCDB_PASSWORD = "your-password" DOCDB_PORT = 27017 CA_CERT_PATH = "/path/to/rds-combined-ca-bundle.pem" # AWS官方RDS CA证书路径 with sshtunnel.open_tunnel( (EC2_VM, 22), ssh_username="ec2-user", ssh_pkey=EC2_KEY, remote_bind_address=(DOCDB_HOST, DOCDB_PORT), ) as tunnel: client = MongoClient( f"mongodb://{DOCDB_USER}:{DOCDB_PASSWORD}@127.0.0.1:{tunnel.local_bind_port}", ssl=True, ssl_ca_certs=CA_CERT_PATH, ssl_match_hostname=False # 生产环境建议开启,调试阶段可临时关闭 ) # 测试连接 print(client.list_database_names())
2. 关键注意事项
- CA证书获取:从AWS官网下载RDS组合CA证书,保存到本地指定路径。
- 安全组配置:确保DocDB的安全组允许EC2实例的IP访问27017端口。
- 版本兼容性:DocDB仅兼容特定版本的MongoDB,需确保pymongo版本与DocDB版本匹配(例如DocDB 5.0兼容pymongo 4.x)。
内容的提问来源于stack exchange,提问作者ealeon
相关产品推荐
相关产品推荐

