배경 정보
Docker를 실행하는 두 개의 네트워크 인터페이스가있는 서버가 있습니다. Docker는 일부 가상화 도구와 같은 Linux 브리지 인터페이스를 만듭니다 docker0
. 이 인터페이스는 기본적으로 IP로 구성되며 172.17.42.1
모든 Docker 컨테이너는이 인터페이스와 게이트웨이로 통신하며 동일한 /16
범위의 IP 주소가 할당됩니다 . 내가 알기로 컨테이너로 들어오고 나가는 모든 네트워크 트래픽은 NAT를 통과하므로 아웃 바운드는에서 오는 것으로 보이며 172.17.42.1
인바운드는로 전송됩니다 172.17.42.1
.
내 설정은 다음과 같습니다.
+------------+ /
| | |
+-------------+ Gateway 1 +-------
| | 10.1.1.1 | /
+------+-------+ +------------+ |
| eth0 | /
| 10.1.1.2 | |
| | |
| DOCKER HOST | |
| | | Internet
| docker0 | |
| (bridge) | |
| 172.17.42.1 | |
| | |
| eth1 | |
| 192.168.1.2 | \
+------+-------+ +------------+ |
| | | \
+-------------+ Gateway 2 +-------
| 192.168.1.1| |
+------------+
문제
호스트 시스템과의 모든 트래픽 이의 기본 게이트웨이 로 나가는 동안 두 번째 eth1
192.168.1.2
인터페이스 의 모든 Docker 컨테이너 192.168.1.1
와의 모든 트래픽을 기본 게이트웨이 로 라우팅하고 싶습니다 . 나는 지금까지 쓸모없는 다양한 것들을 시도했지만 내가 가장 가까운 것으로 생각하는 것은 iproute2를 다음과 같이 사용하는 것입니다.eth0
10.1.1.2
10.1.1.1
# Create a new routing table just for docker
echo "1 docker" >> /etc/iproute2/rt_tables
# Add a rule stating any traffic from the docker0 bridge interface should use
# the newly added docker routing table
ip rule add from 172.17.42.1 table docker
# Add a route to the newly added docker routing table that dictates all traffic
# go out the 192.168.1.2 interface on eth1
ip route add default via 192.168.1.2 dev eth1 table docker
# Flush the route cache
ip route flush cache
# Restart the Docker daemon so it uses the correct network settings
# Note, I do this as I found Docker containers often won't be able
# to connect out if any changes to the network are made while it's
# running
/etc/init.d/docker restart
컨테이너를 가져 오면이 작업을 수행 한 후 컨테이너에서 전혀 핑을 할 수 없습니다. 브리지 인터페이스가 이러한 종류의 라우팅에 물리적 인터페이스와 동일한 방식으로 처리되는지 확실하지 않으며, 단순성 태스크를 수행하는 방법에 대한 팁뿐만 아니라 온 전성 검사를 원합니다.
답변
iptables 설정에서 더 많은 것을보아야 할 수도 있습니다. Docker는 컨테이너 서브넷 (예 : 172.17.0.0/16)에서 발생하는 모든 트래픽을 0.0.0.0으로 가장합니다. 를 실행 iptables -L -n -t nat
하면 nat 테이블 아래에서 POSTROUTING 체인을 볼 수 있습니다.
체인 POSTROUTING (정책 수락) 대상 단백질 소스 대상 선택 MASQUERADE all-172.17.0.0/16 0.0.0.0/0
이제이 규칙을 제거하고 컨테이너 서브넷에서 발생하는 모든 트래픽을 원하는 두 번째 인터페이스의 IP-192.168.1.2로 가장하는 규칙으로 바꿀 수 있습니다. 삭제 규칙은 POSTROUTING 체인의 첫 번째 규칙 인 것으로 가정합니다.
iptables -t nat -D POSTROUTING 1
그런 다음이 맞춤 규칙을 추가합니다.
iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT-소스 192.168.1.2
답변
친구와 나는도 커가 요청을 처리하는 여러 네트워크 인터페이스를 지원하도록하려는이 정확한 문제에 부딪쳤다. 우리는 추가 인터페이스를 연결 / 구성 / 가동하는 AWS EC2 서비스와 특별히 협력하고있었습니다. 이 프로젝트 에는 필요한 것 이상이 있으므로 여기에 필요한 것만 포함 시키려고합니다.
먼저 우리가 한 일은 다음에 대한 별도의 라우팅 테이블을 만드는 것입니다 eth1
.
ip route add default via 192.168.1.2 dev eth1 table 1001
다음으로 mangle 테이블을 구성하여 다음과 같은 연결 표시를 설정합니다 eth1
.
iptables -t mangle -A PREROUTING -i eth1 -j MARK --set-xmark 0x1001/0xffffffff
iptables -t mangle -A PREROUTING -i eth1 -j CONNMARK --save-mark --nfmask 0xffffffff --ctmask 0xffffffff
마지막으로 우리는 모든 fwmark
새로운 테이블을 사용 하기 위해이 규칙을 추가합니다 .
ip rule add from all fwmark 0x1001 lookup 1001
아래 iptables
명령은 연결 표시를 복원 한 다음 라우팅 규칙이 올바른 라우팅 테이블을 사용할 수 있도록합니다.
iptables -w -t mangle -A PREROUTING -i docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j CONNMARK --restore-mark --nfmask 0xffffffff --ctmask 0xffffffff
나는 이것이 프로젝트가 eth1
부팅 할 때 인터페이스를 연결 / 구성 / 활성화하는보다 복잡한 예제에서 필요한 전부라고 생각합니다 .
이제이 예제는 연결이 eth0
요청을 처리 docker0
하는 것을 막지는 않지만 라우팅 규칙을 추가하여이를 방지 할 수 있다고 생각합니다.
답변
가장 무도회는 172.17.42.1이 아니라 오히려
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
이는이 규칙이 제대로 작동하지 않음을 의미합니다.
ip rule add from 172.17.42.1 table docker
대신 시도하십시오
ip rule add from 172.17.0.0/16 table docker