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


13

背景情報

Dockerを実行している2つのネットワークインターフェイスを持つサーバーがあります。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|       |
                                          +------------+            

問題

Dockerコンテナからのすべてのトラフィックを2番目のeth1 192.168.1.2インターフェイスからデフォルトゲートウェイ192.168.1.1のにルーティングし、ホストマシンからのすべてのトラフィックをeth0 10.1.1.2インターフェイスからデフォルトゲートウェイのに送ります10.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を実行できません。ブリッジインターフェイスがこの種のルーティングの物理インターフェイスと同じ方法で処理されるかどうかはわかりませんが、この一見単純なタスクを達成するためのヒントだけでなく、健全性チェックだけが必要です。


NATに関するあなたのコメントは正しくありません。出力インターフェイスがdocker0ではない172.17.0.0/16ソースアドレスをマスカレードするように設定されています。すなわち-A POSTROUTING -s 172.17.0.0/16!-o docker0 -jマスカレード。つまり、Dockerコンテナから発信されたパケットがeth0またはeth1のいずれかを経由して終了する場合、172.17.xx IPではなく、そのインターフェイスのIPアドレスが使用されます。
マット

ご意見をありがとうございます。それで、特定のインターフェイスからルーティングするための私のアプローチが変わりますか?これを達成する方法を知っていますか?現状では、Dockerはホストシステムのデフォルトゲートウェイを使用しているだけで、これは望ましい動作ではありません。Dockerに特定のインターフェイスからルーティングするすべてのものが欲しい。

私が提案したことがうまくいかない理由はわかりません。しかし、もう1つの選択肢はパイプワークを使用することです。 github.com/jpetazzo/pipework また、Dockerヘルプの高度なネットワークセクションも読むと便利です。docs.docker.com/articles/networking
マット・

@Mattこれに関するあなたの提案に感謝します。私がパイプワークを読んだことから、コンテナが開始された後に追加のコマンドが必要になります。これは、セキュリティの脆弱性のように見える正しいゲートウェイにアクセスするためです。もともとは、複数のホスト間でコンテナを接続するために作成されましたが、ここでの目標ではありません。Dockerの高度なネットワーキングドキュメントについては、もう一度見ていきますが、この状況ではこれまで役に立ちませんでした(ここに投稿する前に読みました)。この投稿へのリンクをdocker Github Issuesページに投稿し、そこからどうなるかを確認します。

Githubの問題に戻るリンクを次に示します。github.com

回答:


1

また、iptablesのセットアップについても詳しく調べる必要があります。Dockerは、172.17.0.0 / 16などのコンテナーサブネットから発信されるすべてのトラフィックを0.0.0.0にマスカレードします。実行するとiptables -L -n -t nat、これを行うnatテーブルの下にPOSTROUTINGチェーンが表示されます-

チェーンPOSTROUTING(ポリシーACCEPT)
ターゲットprot optソースdestination
すべてマスカレード-172.17.0.0/16 0.0.0.0/0

これで、このルールを削除して、コンテナのサブネットから2番目のインターフェイスのIP 192.168.1.2へのすべてのトラフィックをマスカレードするルールに置き換えることができます。削除ルールは、それがPOSTROUTINGチェーンの下の最初のルールであると仮定します-

iptables -t nat -Dポストルーティング1

次に、このカスタムルールを追加します-

iptables -t nat -A POSTROUTING -s 172.17.0.0/16 -j SNAT --to-source 192.168.1.2

実際には、出力インターフェイスにマスカレードします。その宛先部分は、ソースサブネットから任意の宛先へのトラフィックはすべてマスカレードされると言っているだけです。
マット

残念ながら、これは機能しませんでした。私の完全なプロセスは実行することでした: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設定があります。そして、Dockerコンテナにも同じことを望んでいました。これは、そのような場合で働いていた: "iptablesの-t NAT -I POSTROUTING 1 -s 172.17.0.0/16 -d PUBIP / 32 -j SNAT --to-ソースSECONDARYIP"
ラム

1

友人と私は、ドッカーがリクエストを処理する複数のネットワークインターフェイスをサポートすることを望んでいたこの正確な問題に遭遇しました。具体的には、AWS EC2サービスと連携し、追加のインターフェイスを追加/設定/起動していました。このプロジェクトでは、必要なもの以上のものがあるので、ここに必要なものだけを含めるようにします。

最初に、私たちが行ったのは、次のために別のルートテーブルを作成することでした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

最後に、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-古い投稿とロングショットですが、この解決策はSOの私の問題にも役立つと思いますか? stackoverflow.com/questions/51312310/...
ジョリーロジャー

2
ジョリー・ロジャー-これはあなたの問題を解決すると信じています。最近、別のチームからこのブログ投稿(基本的にここと同じソリューション)について質問を受けましたが、彼らはそれがうまくいったと言いました。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 コンテナからtracerouteを実行し、最初のホップは10.1.1.1
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.