2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[docker][AWS] docker コンテナの起動/停止を繰り返すと EC2 間でネットワークが繋がらなくなる

Posted at

docker コンテナの起動/停止を繰り返していると、EC2 へ接続できなくなる現象でハマったので覚え書き。

現象

elasticsearch と連動するアプリケーションを docker コンテナで動かしている環境で、コンテナの起動/停止をしているとあるタイミングで EC2 への接続が切れてしまう現象が発生しました。

  • docker-compose でコンテナ起動/停止
  • 一定の確率で発生する
  • EC2 への ssh 接続がつながらなくなる
  • EC2 再起動しても復旧しない
  • EC2 再起動中に ping をかけておくと、起動直後に一瞬疎通するが、その後ダンマリになる

アプリケーションの実行環境は以下のような構成。
アプリ用の VPC へピア接続された保守用 VPC 内の踏台 EC2 からアクセスしています。

fig-docker-network-conflict-env.png

解析

EC2 起動直後、しばらくしてからネットワークがつながらなくなるため、EC2 起動時にコンテナを自動起動していた(restart=always) のを廃止してみたが、現象変わらず。
なので、アプリケーション自体の線は除外しました。

問題発生時の EC2 の状態が確認できないと何も分からないため、Elastic IP を割り当てて接続したところ、無事 ssh 接続成功。
ということは、踏台 EC2 からの接続のみの問題となりそうです。

問題のサーバに入れたので、いろいろ状態の情報を収集してみます。

# ネットワークインターフェースの状態
$ ifconfig
$ ip route

# ブリッジの状態
$ brctl show

# iptables の状態
$ sudo iptables -L
$ sudo iptables -L -t nat

# docker network の状態
$ docker network ls
$ docker network inspect xxxxxx_default

# docker コンテナの状態
$ docker ps
$ docker inspect xxxxxx

原因

上記のコマンドによる取得結果を、正常時と問題発生時で比較していると、コンテナの起動/停止の繰り返しで、docker-compose が作るネットワークのアドレスが一つずつ変わっていくのが分かりました。
それで、あるアドレスが設定された場合に問題が発生しているようです。

172.31.0.0/16

原因は、アクセス元である保守用 VPC のアドレスと、docker network でブリッジに設定したアドレスがかぶってしまったときに、ルーティングがおかしくなってしまうというものでした。

docker network は内部で iptables を書き換えるので(★)、この影響を受けていたことになります。

$ sudo iptables -L -t nat
    :
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  ip-172-31-0-0.ap-northeast-1.compute.internal/16  anywhere ★
MASQUERADE  all  --  ip-172-17-0-0.ap-northeast-1.compute.internal/16  anywhere

docker のネットワークは、デフォルトでは 172.18.0.0/16 から順番に 172.19.0.0/16172.20.0.0/16、と採番するようで、これがたまたまアクセス元の VPC とかぶってました。アクセス元の VPC は AWS のデフォルト VPC だったので、デフォルト設定で動かしていると案外遭遇してしまうかも。

docker network のアドレス設定については、以下のサイトが参考になりました。

Dockerはネットワークを31個しか作れない
https://ashphy.hateblo.jp/entry/2020/05/23/223354

デフォルトで以下のアドレスがプールされていて、順番に利用されるようです。

  • "172.17.0.0/16"
  • "172.18.0.0/16"
  • "172.19.0.0/16"
  • "172.20.0.0/16"
  • "172.21.0.0/16"
  • "172.22.0.0/16"
  • "172.23.0.0/16"
  • "172.24.0.0/16"
  • "172.25.0.0/16"
  • "172.26.0.0/16"
  • "172.27.0.0/16"
  • "172.28.0.0/16"
  • "172.29.0.0/16"
  • "172.30.0.0/16"
  • "172.31.0.0/16"
  • "192.168.0.0/20"
  • "192.168.16.0/20"
  • "192.168.32.0/20"
  • "192.168.48.0/20"
  • "192.168.80.0/20"
  • "192.168.96.0/20"
  • "192.168.112.0/20"
  • "192.168.128.0/20"
  • "192.168.144.0/20"
  • "192.168.160.0/20"
  • "192.168.176.0/20"
  • "192.168.192.0/20"
  • "192.168.208.0/20"
  • "192.168.224.0/20"
  • "192.168.240.0/20"

※結構、大きな帯域使ってますね。。

対処

docker network で利用するアドレスプールを指定できるようなので、これをアクセス元 VPC にかぶらないように設定しました。

/etc/docker/daemon.json
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "10"
  },
  "live-restore": true,
  "default-address-pools": [
    { "base":"192.168.0.0/16", "size":24 }  
  ],
  "max-concurrent-downloads": 10
}

分かってしまえば単純な問題ですが、これはなかなか気づきにくいなと思います。
最初にアプリケーションの原因を考えていたので、だいぶ遠回りしました。。
(docker ネットワークの勉強になったのでヨシとします)

// EOF

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?