[server] 다른 물리적 네트워크 인터페이스 및 기본 게이트웨이를 사용하여 도커 컨테이너에서 라우팅

배경 정보

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.210.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


답변