无法从EC2实例连接到RDS实例

72

从EC2实例i-78a8df00,我正在尝试连接到RDS实例mysql.************.us-east-1.rds.amazonaws.com。它们都位于美国东部地区。我将EC2实例的安全组(sg-********)添加到了RDS安全组中,但这并没有帮助解决问题。当运行此命令时,似乎存在防火墙/DNS问题,因为它会超时:

ubuntu@ip-10-195-189-237:~$ mysql -h mysql.************.us-east-1.rds.amazonaws.com

错误2003(HY000):无法连接到'mysql.************.us-east-1.rds.amazonaws.com'上的MySQL服务器(110)

我可以使用与上述相同的语句从本地计算机成功连接到RDS实例。 我尝试了各种论坛解决方案,但这些都没有帮助。


1
安全组的端口是否已打开,以允许EC2实例连接到RDS? - David
是的,我将 EC2 实例的安全组 (sg-**) 添加到了 RDS 安全组中。 - Mark Shust at M.academy
如果我从EC2到RDS主机名进行traceroute,则会超时: traceroute mysql..us-east-1.rds.amazonaws.com traceroute至mysql..us-east-1.rds.amazonaws.com(10.206.**.***),最大30个跳数,60字节数据包^C 1 * * * 2 * * * 3 * * * 4 * * * 5 * * * 这使我相信这是DNS /防火墙问题。但是,我为RDS安全组制定了一项规则,允许来自此EC2安全组的连接。 - Mark Shust at M.academy
我还将CIDR 0.0.0.0/0添加到RDS安全组中,以确认所有人都可以访问该MySQL数据库。但仍然无法连接。这告诉我DNS没有正确路由到我的EC2实例的正确RDS主机名。还有其他人遇到这个问题吗? - Mark Shust at M.academy
2
所以我在 AWS 外部和 EC2 实例内部对主机名进行了“dig”操作。从 EC2 实例中,它似乎正确地路由到其内部 IP,但从外部则是外部 IP。是否有任何诊断标志可以添加到 mysql 连接字符串中,以查看实际发生的情况或其他详细日志记录?这非常令人沮丧。 - Mark Shust at M.academy
这明显与防火墙有关。尝试直接telnet到主机名,但连接超时了。从我的本地开发机可以正常连接,但从EC2实例中出现了这种情况: telnet mysql.****.us-east-1.rds.amazonaws.com 3306 正在尝试连接10.206..*... telnet: 无法连接到远程主机:连接超时 - Mark Shust at M.academy
10个回答

122

我也遇到过类似的问题,当我创建一个新的EC2实例时,忘了在RDS安全组的入站IP地址选项中更改允许连接到我的RDS实例的3306端口的设置。

令人困惑的是RDS仪表板中的一个选项,称为"安全组"。但你不需要它来解决问题。

你真正需要做的是:

  • 进入RDS实例列表
  • 点击你尝试连接的实例
  • 点击“安全组规则”部分

enter image description here

这应该会打开一个新的浏览器标签页或窗口,显示安全组的详细信息。 在底部找到几个选项卡,选择“入站规则”选项卡,然后点击“编辑”按钮。

enter image description here

将值更改为你的EC2实例的IP地址或IPv4 CIDR块,例如:

174.33.0.0/16

要获取此值,你可以通过ssh进入实例并运行ip addr命令,或者在浏览器中运行EC2 Manager并查找实例详细信息中的“私有IP”值。


2
谢谢,这个完美地解决了!不过我不明白为什么只是创建新的安全组对我来说行不通。我想我可能误解了安全组的实际作用。 - Abs
哇!!!非常感谢你,我的朋友。在花费了数小时处理这个问题却毫无进展之后,我按照你的建议尝试了一下,结果“哇啦”,它终于可以工作了!!!谢谢你!!我会保存你的答案,这样当我再次遇到这个问题时,我就有了解决方案 :) - Francisco Souza
正是我所需要的。现在我的网络应用程序已经连接到数据库了。 - st_stefanov
5
对我来说,重点是使用私有 IP 而不是公网 IP 进行连接,这将通过 VPC 内部进行连接而不是通过公网流量。 - Michael Davidson
我想从本地的MySqlWorkbench连接我的mysql rds。我已经添加了入站规则以允许互联网流量,但是仍然无法从我的本地计算机telnet。它一直显示“正在尝试65.1.164.97...”。 - harshit2811

48

针对可能遇到连接RDS或RedShift的类似问题的人提供额外信息:

1) 检查安全组

验证RDS实例的安全组是否允许来自源服务器所属的安全组(或其直接添加的IP)的访问。您应该查看的安全组是从RDS控制台UI中指定的RDS实例属性的安全组(命名为“安全组”)。

注意:数据库安全组与AWS EC2安全组可能不同。如果您的RDS实例在classic/public EC2中,则应该在RDS UI的“数据库安全组”部分进行检查。对于VPC用户,安全组将是一个普通的VPC安全组(名称sg-xxx将在RDS实例的属性中列出)。

2) 确认DNS不是问题。

亚马逊使用分裂DNS,因此在AWS外部进行DNS查找将返回公共IP,而在AWS内部进行查找将返回私有IP。如果您怀疑这是DNS问题,那么您是否确认不同可用区返回不同的IP?如果不同AZ获取不同的IP,则需要联系AWS支持。

3) 通过建立套接字连接来确认网络连接。

像tracepath和traceroute这样的工具可能没有帮助,因为RDS当前会丢弃ICMP流量。

尝试通过在端口3306(mysql)或5432(postgres)上建立套接字连接来测试端口连接。首先找到RDS实例的IP,然后使用telnet或nc:

telnet x.x.x.x 3306
nc -vz x.x.x.x 3306

a) 如果您的连接尝试不成功并立即失败,则端口可能被阻止或远程主机未在该端口上运行服务。您可能需要联系AWS支持进行进一步故障排除。如果从AWS之外连接,请先尝试从AWS内的另一个实例进行连接(因为您的防火墙可能会阻止这些连接)。

b) 如果您的连接不成功并出现超时,则可能是防火墙丢弃/忽略数据包或数据包返回的网络路径不同。您可以通过运行netstat -an | grep SYN来确认此问题(从不同的CLI窗口/会话中运行并等待telnet / nc命令超时)。处于SYN状态的连接意味着您已发送连接请求,但没有收到任何回应(SYN_ACK或拒绝/阻止)。通常,这意味着防火墙或安全组正在忽略或丢弃数据包。

请检查是否在主机和RDS实例之间使用iptables或NAT网关。如果您在VPC中,请确保允许源主机的出站流量。

c) 如果套接字连接测试成功,但您无法使用mysql客户端(CLI、工作台、应用程序等)连接,请查看netstat的输出以查看连接状态(将x.x.x.x替换为RDS实例的实际IP地址):

netstat -an | grep x.x.x.x

如果使用telnet或NC时正在建立连接,但是在使用mysql客户端时看到“SYN”状态,则可能遇到MTU问题。

当撰写本文时,RDS可能不支持用于PMTUD的ICMP数据包(https://en.wikipedia.org/wiki/Path_MTU_Discovery#Problems_with_PMTUD)。如果您尝试通过ClassicLink从经典EC2实例访问位于VPC中的RDS或RedShift,则可能会出现问题。请尝试使用以下方法降低MTU,然后再次测试:

sudo ip link show
# take note of the current MTU (likely 1500 or 9001)
sudo ip link set dev eth0 mtu 1400

如果较低的MTU可行,请务必跟进AWS客户支持以寻求帮助,并提及在连接到您的RDS实例时遇到了MTU问题。如果TCP数据包被封装进行隧道传输,则会导致数据包/有效负载的可用MTU降低。将源服务器上的MTU降低,允许封装的数据包仍适合限制范围内。

如果不起作用,请将MTU设置回默认值并联系AWS支持进行进一步故障排除。


19

虽然 Mark 的问题似乎与多AZ路由和 EC2 经典有关,但我今天也遇到了完全相同的问题。

为了解决这个问题,我通过添加我的 EC2 实例的两个私有IP地址来修改了自动创建的 RDS 实例的安全组。

向我的RDS实例添加入站规则

这是一个相当明显的问题,但我对AWS整体都比较新,希望像我这样的其他人能从中受益。


我在自定义IP下面找到了一个选项,名为“我的IP”,选择后获取了我的IP地址,解决了问题。感谢@sapenove之前提供的提示。 - Yoku
谢谢回答,我在RDS安全组的入站规则中添加了EC2私有IP,对我来说有效。 - Piyush Patel

8
显然,多AZ会引起一系列问题。由于默认的多AZ配置将我的数据库放在了us-east-1d地区,而我的EC2实例位于us-east-1a地区,DNS没有正确地路由。我重新创建了一个非多AZ的RDS实例,并使其处于us-east-1a地区,现在一切都很顺畅。
如果有任何关于使用AWS中的RDS、ELB和多AZ功能的DNS路由方面的超级天才,那么知道如何做这些事情将是非常棒的,因为这在亚马逊网络服务文档中没有记录。

2
我甚至在2019年今天仍然遇到这个问题! - Chad Van De Hey
1
@ChadVanDeHey 哈哈,这不让我惊讶! :P - Mark Shust at M.academy
1
2023年了,问题仍然存在。 - Kevin Kopf
是的,这真的很令人沮丧。 - Chris Johnson
是的,这真的很令人沮丧。 - undefined

5

我挣扎了三天后,终于发现为什么我的连接没有成功...

在您的EC2实例上添加端口3306的出站规则,并在您的RDS服务器上添加端口3306的入站规则。入站值应该是EC2实例的安全性。

例如:

  • 您的EC2安全组是 - sg.ec2
  • 而RDS安全组是 - sg.rds

因此,请转到编辑sg.ec2的出站规则,并添加端口3306的自定义TCP和目标为0.0.0.0/0

然后,转到编辑sg.rds的入站规则,并添加一个源为sg.ec2的3306端口的入站规则。


2
今天我遇到了类似的问题,我的EC2实例突然失去了对RDS实例的访问,WordPress停止工作。安全组是正确的,我甚至可以从EC2实例的控制台连接到MySQL,但无法通过PHP连接。不知何故,重新启动EC2服务器帮助了我。

1
解决方法: 我需要调整RDS实例安全组的入站规则,以允许来自我的EC2实例IP地址的连接。 详细说明: 创建AWS RDS实例时,我选择了通过公共IP地址连接到它的选项。这样做,我认为我可以从任何IP地址连接到它,但事实并非如此。实际上,当实例被创建/配置时,它采用了我的笔记本电脑的公共IP地址,并将RDS安全组的入站规则设置为仅接受来自该IP地址的连接。因此,我必须手动添加一条规则,以允许来自EC2实例IP地址的MYSQL / Aurora连接。

1

看起来在最后一次发布和这次发布之间,亚马逊解决了DNS路由问题,因为现在多可用区RDS的一切都正常工作...


1
当我使用Multi-AZ时,我仍然遇到与你相同的问题,即它无法公开访问。 - Neo

0

我遇到了同样的问题,我无法从EC2实例连接到RDS,这两个资源都在同一个VPC和多AZ设置中。

对我来说,多AZ设置不是问题。

我只是缺少了从我的EC2实例安全组到我的RDS安全组的出站规则3306。


-3
根据亚马逊文档,我们应该使用:
PROMPT> mysql -h <endpoint> -P 3306 -u <mymasteruser> -p

其中endpointmymasteruser(用户名)来自您的RDS实例。

我通过直接使用IP公共地址(端点的)而不是端点(****.us-east-1.rds.amazonaws.com)解决了这个问题。您可以使用“ping”命令(ping ****.us-east-1.rds.amazonaws.com)获取IP公共地址。


如果您的RDS数据库实例位于私有子网中,您会怎么做? - Kumaresh Babu N S

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接