仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

OpenStackインスタンスでDockerなどを動かすと、コンテナ内でaptなどを実行すると「Connection failed」や「Connection timed out」になる

OpenStackは何かテスト環境を動かすときに便利なので、よく利用しています。

コンテナからの通信がおかしい?

先日Dockerイメージを使ってとあるアプリケーションを実行しようと思ってインスタンスの中でDockerを動かしてみたら、ネットワークがなんかおかしい様子。 当然、aptコマンドなんかもうまく動いてくれませんでした。

下記はDebian 10のものですが、Debian 11,Ubuntuなどでも同じような感じでした。「Connection failed」もしくは「Connection timed out」と表示されました。

root@8317927d7711:/# apt update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [122 kB]                                                                                                 
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:3 http://security.debian.org/debian-security buster/updates/main amd64 Packages [329 kB]                                                                 
Err:2 http://deb.debian.org/debian buster InRelease                                                                                                          
  Connection failed [IP: 151.101.110.132 80]
Get:4 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]             
Get:3 http://security.debian.org/debian-security buster/updates/main amd64 Packages [329 kB]
Err:4 http://deb.debian.org/debian buster-updates InRelease                                                                                                  
  Connection failed [IP: 151.101.110.132 80]
Fetched 200 kB in 2min 30s (1334 B/s)
Reading package lists... Done
Building dependency tree       
Reading state information... Done
All packages are up to date.
W: Failed to fetch http://deb.debian.org/debian/dists/buster/InRelease  Connection failed [IP: 151.101.110.132 80]
W: Failed to fetch http://deb.debian.org/debian/dists/buster-updates/InRelease  Connection failed [IP: 151.101.110.132 80]
W: Some index files failed to download. They have been ignored, or old ones used instead.

MTUが原因でした

原因はOpenStackインスタンスでお馴染みのMTU問題が原因でした。検索したらこの情報を見つけました。 そのものズバリですね。

https://platform9.com/kb/openstack/no-connectivity-to-docker-containers-within-instance

問題の回避方法

インスタンスにDockerをインストールしたあと、DockerブリッジのMTUを適切に設定すれば回避できるようです。

先ほどのサイトの例は/etc/docker/daemon.jsonにMTU 1450を設定していますが、私の環境ではMTU 1412まで落とさないとうまくいきませんでした(理由はこのあと)。

$ cat /etc/docker/daemon.json
{ "mtu": 1412 }

$ sudo systemctl daemon-reload 
$ sudo systemctl restart docker

MTUの値はpingを使って最適値を調べました。

$ ping -M do -s1500 -c1 172.16.0.1
PING 172.16.0.1 (172.16.0.1) 1500(1528) bytes of data.
ping: local error: Message too long, mtu=1442

--- 172.16.0.1 ping statistics ---
1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms
...
$ ping -M do -s1412 -c1 172.16.0.1
PING 172.16.0.1 (172.16.0.1) 1412(1440) bytes of data.
1420 bytes from 172.16.0.1: icmp_seq=1 ttl=254 time=5.64 ms

--- 172.16.0.1 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 5.638/5.638/5.638/0.000 ms

MTU 1412まで下げる必要があった理由

なぜMTU 1412までの変更が必要だったかですが、この環境はmicrostackを使って構築していました。 microstackは現在VXLANではなくて、Geneveを使っているようです(ネットワークはOVNを使っています)。

opendev.org

microstackを実行するホストのネットワークインターフェイスを確認すると、次のようなインターフェイスが見つかりました。 tapインターフェイスはMACアドレスからインスタンスに提供されているインターフェイスであることがわかりました。

  • ovs-system MTU1500
  • br-ex MTU1500
  • br-int MTU1442
  • tapd9ebe01f-ab MTU1442
  • tapcf80881a-69 MTU1442

Dockerのdocker0ブリッジのデフォルトはMTU 1500みたいです。これは物理マシンでDockerを動かす場合はうまくいきます。仮想マシンでも「普通の」仮想マシンではうまくいくと思います。今回はOpenStackインスタンスでの話です。OpenStackはコンピュートこそLinux KVMを使ってはいますが、ネットワークについてはOVNという仮想ネットワークを使っています。 結果、インスタンスに割り当てられたインターフェイスのMTUは1442ですから、デフォルトのままだとコンテナから外へ通信ができなかったというわけです。そりゃあ、DNSの名前解決やaptコマンドなどが実行できないわけですね。

docs.docker.com

ちなみにこちらの情報によると、VXLANだとMTU 1450、GREだと1458、GeneveだとMTU 1442になるようです。

docs.openstack.org

特にインスタンスの中でアプリケーションを実行するだけならMTUを変更しないでも動きますが、インスタンスの中で入れ子みたいな感じでDockerを動かすなどする場合は、MTUの調整が必要だったというわけですね。

CentOS Stream 9だと...

CentOS Stream 9でこの回避方法を設定しようとすると、なぜかDockerサービスが起動しなくなりました。うまく動くこともありますが、起動しなくなると設定を全部消しても起動しなくなります。 メッセージを見てもよくわからないので諦めました。

設定変更後は正常に動作するように

適切なMTUをDocker Daemonに対して設定してあげると、コンテナの中で問題なくaptが通りました。

$ sudo docker container run --rm -it debian:10 bash
root@f0097cd828f0:/# apt update
Get:1 http://security.debian.org/debian-security buster/updates InRelease [65.4 kB]
Get:2 http://deb.debian.org/debian buster InRelease [122 kB]
Get:3 http://deb.debian.org/debian buster-updates InRelease [51.9 kB]
Get:4 http://deb.debian.org/debian buster/main amd64 Packages [7911 kB]
Get:5 http://deb.debian.org/debian buster-updates/main amd64 Packages [8788 B]
Get:6 http://security.debian.org/debian-security buster/updates/main amd64 Packages [329 kB]
Fetched 8488 kB in 2s (4003 kB/s)                         
Reading package lists... Done
Building dependency tree       
Reading state information... Done
All packages are up to date.

microstackは結構長く使っていたのに、よく今までMTUの問題にはまらなかったなあ。それだけが謎です。