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


13

배경 정보

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

컨테이너를 가져 오면이 작업을 수행 한 후 컨테이너에서 전혀 핑을 할 수 없습니다. 브리지 인터페이스가 이러한 종류의 라우팅에 물리적 인터페이스와 동일한 방식으로 처리되는지 확실하지 않으며, 단순성 태스크를 수행하는 방법에 대한 팁뿐만 아니라 온 전성 검사를 원합니다.


NAT에 대한 귀하의 의견이 옳지 않습니다. 출력 인터페이스가 docker0이 아닌 172.17.0.0/16 소스 주소에서 가장하도록 설정되어 있습니다. 즉 -A POSTROUTING -s 172.17.0.0/16! -o docker0 -j MASQUERADE. 즉, 도커 컨테이너에서 시작된 패킷이 eth0 또는 eth1을 통해 종료되면 172.17.xx IP가 아닌 해당 인터페이스 IP 주소를 사용합니다.
Matt

귀하의 의견에 감사드립니다. 그러면 특정 인터페이스에서 라우팅하는 방식이 변경 될 것입니다. 맞습니까? 내가 이걸 어떻게 달성 할 수 있는지 아세요? Docker는 호스트 시스템의 기본 게이트웨이를 사용하는 것처럼 보이며 이것이 바람직한 동작은 아닙니다. Docker가 모든 것을 특정 인터페이스 밖으로 라우팅하기를 원합니다.

왜 내가 제안한 것이 작동하지 않는지 잘 모르겠습니다. 그러나 또 다른 옵션은 파이프를 사용하는 것입니다. github.com/jpetazzo/pipework 또한 docker 도움말의 고급 네트워킹 섹션을 읽는 것이 유용 할 수 있습니다. docs.docker.com/articles/networking
Matt

@Matt 이것에 대한 제안에 감사드립니다. 내가 읽은 내용에서 컨테이너는 컨테이너가 보안 취약점처럼 보이는 올바른 게이트웨이에 액세스하기 시작한 후에 추가 명령이 필요합니다. 원래 여러 컨테이너에서 컨테이너를 함께 연결하기 위해 만들어졌지만 실제로는 내 목표가 아닙니다. Docker 고급 네트워킹 문서는 다시 한 번 살펴볼 것이지만 지금까지는 도움이되지 않았습니다 (이 글을 게시하기 전에 읽었습니다). Docker Github Issues 페이지 에이 게시물에 대한 링크를 게시하고 그 게시물이 어떻게 진행되는지 확인합니다.

다음은 Github 이슈에 대한 링크입니다. github.com/docker/docker/issues/13762

답변:


1

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

실제로 그것은 출력 인터페이스로 마스 쿼 레이드합니다. 해당 대상 부분은 소스 서브넷에서 임의의 대상으로 발생하는 모든 트래픽이 가장 될 것이라고 말하고 있습니다.
Matt

불행히도 이것은 작동하지 않았습니다. 내 전체 프로세스는 다음과 같이 실행되었습니다 ip rule add from 172.17.0.0/16 table docker ip route add default via 192.168.1.2 dev eth1 table docker ip route flush cache iptables -t nat -D POSTROUTING 1 iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT --to-source 192.168.1.2 /etc/init.d/docker restart. 그런 다음 컨테이너에서 Ping과 Traceroute를 실행하려고했지만 아무것도 도달하지 못했습니다.

비슷한 요구 사항이 있었고 호스트는 공용 IP에 연결하기 위해 보조 IP 설정이 있습니다. 도커 컨테이너가 동일하게 따르기를 원했습니다. "iptables -t nat -I POSTROUTING 1 -s 172.17.0.0/16 -d PUBIP / 32 -j SNAT --to-source SECONDARYIP"
Ram

1

친구와 나는도 커가 요청을 처리하는 여러 네트워크 인터페이스를 지원하도록하려는이 정확한 문제에 부딪쳤다. 우리는 추가 인터페이스를 연결 / 구성 / 가동하는 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하는 것을 막지는 않지만 라우팅 규칙을 추가하여이를 방지 할 수 있다고 생각합니다.


@stuntmachine 당신이 이것을 시도 할 기회가 있다면 궁금하십니까? 이미 스스로 알아 낸 것이 있다면 솔루션을 공유 할 수 있습니까?
williamsbdev

안녕 @ williamsbdev-오래된 게시물과 긴 샷이지만이 솔루션이 내 문제에 대해서도 효과가 있다고 생각합니까? stackoverflow.com/questions/51312310/…
졸리 로저

2
Jolly Roger-문제가 해결 될 것이라고 생각합니다. 나는 최근에 다른 팀 이이 블로그 게시물 (본질적으로 동일한 솔루션)에 대해 나에게 물어 보았습니다. williamsbdev.com/posts/docker-connection-marking
williamsbdev

0

가장 무도회는 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

불행히도 이것은 작동하지 않았습니다. 컨테이너가 여전히 호스트와 동일한 기본 게이트웨이로 라우팅되었습니다. 내가 한 일은 다음과 같습니다. ip rule add from 172.17.0.0/16 table docker ip route add default via 192.168.1.2 dev eth1 table docker ip route flush cache /etc/init.d/docker restart 나는 경로 추적을 실행하고 첫 번째 홉 그것이 192.168.1.1 있었어야 할 때 10.1.1.1이었다 컨테이너에서
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.