3

目前,AWS ECS 与内部 NLB 相结合,不可能进行系统间通信。意思是容器 1(在实例 1 上)-> 内部 NLB -> 容器 2(在实例 1 上)。由于源 IP 地址不会更改并且与目标地址保持相同,因此 ECS 实例会丢弃此流量。

我在 AWS 论坛上找到了一个帖子https://forums.aws.amazon.com/message.jspa?messageID=806936#806936解释了我的问题。

我已经联系了 AWS Support,他们表示要在他们的路线图上进行修复,但他们无法告诉我什么时候会修复,所以我正在寻找自己解决问题的方法,直到 AWS 永久修复它。

它必须可以通过更改 ECS iptables 来修复,但我没有足够的知识来完全阅读他们的 iptables 设置并了解需要更改什么来解决这个问题。

iptabels-保存输出:

:DOCKER - [0:0]
:DOCKER-ISOLATION - [0:0]
:DOCKER-USER - [0:0]
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 5000 -j ACCEPT
-A DOCKER -d 172.17.0.5/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 8086 -j ACCEPT
-A DOCKER-ISOLATION -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Wed Jan 31 22:19:47 2018
# Generated by iptables-save v1.4.18 on Wed Jan 31 22:19:47 2018
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [38:2974]
:POSTROUTING ACCEPT [7147:429514]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A PREROUTING -d 169.254.170.2/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:51679
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -d 169.254.170.2/32 -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 51679
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 5000 -j MASQUERADE
-A POSTROUTING -s 172.17.0.5/32 -d 172.17.0.5/32 -p tcp -m tcp --dport 8086 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32769 -j DNAT --to-destination 172.17.0.3:5000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32777 -j DNAT --to-destination 172.17.0.2:5000
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 32792 -j DNAT --to-destination 172.17.0.5:8086
COMMIT
# Completed on Wed Jan 31 22:19:47 2018

ip一个:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
   valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
   valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0a:b4:86:0b:c0:c4 brd ff:ff:ff:ff:ff:ff
    inet 10.12.80.181/26 brd 10.12.80.191 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::8b4:86ff:fe0b:c0c4/64 scope link
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ca:cf:36:ae brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:caff:fecf:36ae/64 scope link
       valid_lft forever preferred_lft forever
7: vethbd1da82@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 36:6d:d6:bd:d5:d8 brd ff:ff:ff:ff:ff:ff link-netnsid 1
    inet6 fe80::346d:d6ff:febd:d5d8/64 scope link
       valid_lft forever preferred_lft forever
27: vethc65a98f@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether e6:cf:79:d4:aa:7a brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::e4cf:79ff:fed4:aa7a/64 scope link
       valid_lft forever preferred_lft forever
57: veth714e7ab@if56: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether 1e:c2:a5:02:f6:ee brd ff:ff:ff:ff:ff:ff link-netnsid 3
    inet6 fe80::1cc2:a5ff:fe02:f6ee/64 scope link
       valid_lft forever preferred_lft forever
4

1 回答 1

2

我没有关于即将推出的解决方案的信息,但我怀疑任何解决方法都将涉及阻止实例连接到自身,而是始终连接到不同的实例......或者可能使用平衡器的源地址而不是原始地址进行发夹连接。

根本问题是这样的:平衡器通过与网络基础设施集成工作,并进行网络地址转换,在退出时更改原始目标地址,在返回时更改源地址,以便目标组中的实例看到客户端的真实源地址,但不是相反......但这与非对称路由不兼容。当实例最终与自己对话时,路由是相当不对称的。

假设平衡器为 172.30.1.100,实例为 172.30.2.200。

从 172.30.2.200(实例)到 172.30.1.100(平衡器)发起 TCP 连接。端口并不重要,但我们假设源端口是 49152(临时),平衡器目标端口是 80,实例目标端口是 8080。

172.30.2.200:49152 > 172.30.1.100:80 SYN

NLB 是一个 NAT 设备,因此翻译如下:

172.30.2.200:49152 > 172.30.2.200:8080 SYN

这将被发送回实例。

这已经没有意义了,因为实例只是从它自己、来自外部的东西那里得到了一个传入的请求,即使它没有发出那个请求。

假设它响应,而不是丢弃已经是无意义的数据包,现在你有这个:

172.30.2.200:8080 > 172.30.2.200:49152 SYN+ACK

如果 172.30.2.200:49152 实际上已经向 172.20.2.200:8080 发送了一个数据包,它将以 ACK 响应并建立连接。

但它没有。

接下来发生的事情应该是这样的:

172.30.2.200:49152 > 172.30.2.200:8080 RST

同时,172.30.2.200:49152 没有收到来自 172.30.1.100:80 的任何回复,所以它会重试然后最终放弃:Connection timed out.

当源机器和目标机器不同时,NLB 可以工作,因为它不像 ELB/ALB 提供的那样是真正的(虚拟)机器——它是由网络本身完成的。这是唯一可能的解释,因为那些具有转换地址的数据包确实会返回到原始机器,而 NAT 发生在相反的方向上,并且只有在 VPC 网络保留这些连接的状态表并对其进行转换时才会发生这种情况。

请注意,在 VPC 中,默认网关不是真实的。事实上,子网不是真实的。以太网不是真实的。(这些都不是批评。这里有一些非常出色的工程证据。)所有这些都是由 VPC 网络基础设施中的软件模拟的。当同一子网中的两台机器直接相互通信时......好吧,它们不会。¹它们通过软件定义的网络进行通信。因此,网络可以看到这些数据包并执行 NLB 所需的转换,即使机器位于同一子网中也是如此。

但不是在机器自言自语时,因为当这种情况发生时,流量永远不会出现在网络上——它保留在单个 VM 内,超出 VPC 网络基础设施的范围。

我不相信基于实例的解决方法是可能的。


¹他们没有。 一个非常有趣的例子是使用 Wireshark 监控同一子网上的两个实例的流量。打开安全组,然后从另一个实例 ping 一个实例。源机器发送一个 ARP 请求,并且似乎从目标获得了 ARP 响应......但是没有证据表明目标上存在这种 ARP 交互。那是因为它不会发生。网络处理目标实例的 ARP 响应。这是不可能从另一个实例中欺骗一个实例的部分原因——伪造的数据包不会被网络转发,因为它们显然是无效的,并且网络知道这一点。ARP 发生后,ping 正常。根据第 2 层标头,流量似乎直接从一个实例传递到另一个实例,但实际情况并非如此。

于 2018-02-03T06:11:41.047 回答