针对在尝试连接 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) 通过建立套接字连接来确认网络连接。
tracepath 和 traceroute 等工具可能无济于事,因为 RDS 目前会丢弃 ICMP 流量。
通过尝试在端口 3306(mysql 或 postgres 的 5432)上建立与 RDS 实例的套接字连接来测试端口连接。首先找到 RDS 实例的 IP 并使用 telnet 或 nc(如果从 AWS 内部连接,请务必使用内部/私有 IP):
telnet x.x.x.x 3306
nc -vz x.x.x.x 3306
a) 如果您的连接尝试不成功并立即失败,则该端口可能被阻塞或远程主机未在该端口上运行服务。您可能需要与 AWS 支持联系以进一步排除故障。如果从 AWS 外部连接,请先尝试从 AWS 内部的另一个实例连接(因为您的防火墙可能会阻止这些连接)。
b) 如果您的连接不成功并且出现超时,则可能是数据包被防火墙丢弃/忽略了,或者数据包正在不同的网络路径上返回。您可以通过运行 netstat -an | grep SYN 来确认这一点(在等待 telnet/nc 命令超时时从不同的 ssh 会话)。
处于 SYN 状态的连接意味着您已发送连接请求,但尚未收到任何回复(SYN_ACK 或拒绝/阻止)。通常这意味着防火墙或安全组正在忽略或丢弃数据包。
这也可能是 NAT 路由或来自多个接口的多个路径的问题。检查以确保您没有在主机和 RDS 实例之间使用 iptables 或 NAT 网关。如果您在 VPC 中,还请确保您允许来自源主机的出站/出站流量。
c) 如果你的socket连接测试成功了,但是你无法连接mysql客户端(CLI、workbench、app等),看看netstat的输出查看连接处于什么状态(将 x.x.x.x 替换为 RDS 实例的实际 IP 地址):
netstat -an | grep x.x.x.x
如果您在使用 telnet 或 NC 时建立了连接,但在使用 mysql 客户端时看到“SYN”状态,则您可能遇到了 MTU 问题。
在编写本文时,RDS 可能不支持用于 PMTUD (https://en.wikipedia.org/wiki/Path_MTU_Discovery#Problems_with_PMTUD) 的 ICMP 数据包。如果您尝试通过 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 限制。
如果它不起作用,请将您的 MTU 设置回默认值并联系 AWS 支持以进行进一步的故障排除。