对于在尝试连接到 RDS 或 RedShift 时可能遇到类似问题的人的其他信息:
1)检查安全组
验证 RDS 实例的安全组是否允许从您的源服务器所属的安全组(或者如果在 AWS 外部,则直接添加其 IP)进行访问。您应该查看的安全组是在 RDS 控制台 UI 的 RDS 实例属性中指定的安全组(名为“安全组”)。
注意:数据库安全组可能与 AWS EC2 安全组不同。如果您的 RDS 实例在经典/公共 EC2 中,您应该检查 RDS UI 的“数据库安全组”部分。对于 VPC 用户,安全组将是一个普通的 VPC 安全组(名称 sg-xxx 将列在 RDS 实例的属性中)。
2) 确认 DNS 不是问题。
Amazon 使用拆分 DNS,因此 AWS 外部的 DNS 查找将返回公共 IP,而 AWS 内部的查找将返回私有 IP。如果您怀疑是 DNS 问题,您是否确认从不同的可用区返回不同的 IP?如果不同的 AZ 获得不同的 IP,您将需要联系 AWS 支持。
3) 通过建立套接字连接来确认网络连接。
由于 RDS 当前会丢弃 ICMP 流量,因此 tracepath 和 traceroute 之类的工具可能无济于事。
通过尝试在端口 3306(mysql 或 5432 用于 postgres)上建立与 RDS 实例的套接字连接来测试端口连接。首先查找 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)如果你的socket连接测试成功了,但是不能连接mysql客户端(CLI、workbench、app等),看一下netstat的输出,看看连接处于什么状态(替换xxxx使用 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 支持以进行进一步的故障排除。