web-dev-qa-db-ja.com

別の物理ネットワークインターフェイスとデフォルトゲートウェイを使用したDockerコンテナーからのルーティング

背景情報

Dockerを実行している2つのネットワークインターフェイスを備えたサーバーがあります。 Dockerは、一部の仮想化ツールと同様に、docker0というLinuxブリッジインターフェースを作成します。このインターフェースはデフォルトで172.17.42.1のIPで構成され、すべての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|       |
                                          +------------+            

問題

Dockerコンテナーとの間のすべてのトラフィックを2番目のeth1192.168.1.2インターフェースから192.168.1.1のデフォルトゲートウェイにルーティングし、ホストマシンとの間のすべてのトラフィックを送信したいeth0のデフォルトゲートウェイへの10.1.1.210.1.1.1インターフェイス。私はこれまでさまざまなことを試みましたが、役に立たなかったのですが、正しいことに最も近いと思うのは、次のようにiproute2を使用することです。

# 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

コンテナを立ち上げると、これを実行してもコンテナからpingを実行できません。ブリッジインターフェイスが物理インターフェイスがこの種のルーティングと同じ方法で処理されるかどうかは不明ですが、サニティチェックと、この一見単純なタスクを実行する方法に関するヒントが必要です。

13
user81598

友人と私は、Dockerがリクエストを処理する複数のネットワークインターフェイスをサポートするようにしたいというまさにこの問題に遭遇しました。私たちは特にAWS EC2サービスで作業しており、追加のインターフェイスの接続/構成/準備も行っていました。この project では、必要なものだけではありません。ここでは、必要なものだけを含めるようにします。

まず、eth1用の個別のルートテーブルを作成しました。

ip route add default via 192.168.1.2 dev eth1 table 1001

次に、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

最後に、すべてのfwmarksにこのルールを追加して、作成した新しいテーブルを使用します。

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へのリクエストへのサービスの提供を停止しませんが、ルーティングルールを追加してそれを防ぐことができると思います。

1
williamsbdev

Iptablesの設定についても詳しく調べる必要があるかもしれません。 Dockerは、コンテナサブネット(172.17.0.0/16など)から発信されたすべてのトラフィックを0.0.0.0に見せかけます。 iptables -L -n -t natを実行すると、これを実行するnatテーブルの下にPOSTROUTINGチェーンが表示されます-

チェーンPOSTROUTING(ポリシーACCEPT)
 target prot opt source destination 
 MASQUERADE all-172.17.0.0/16 0.0.0.0/0

これで、このルールを削除して、コンテナのサブネットから2番目のインターフェースの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 --to-source 192.168.1.2 
1
Daniel t.

マスカレードは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
0
Matt