Dockerのpool重複エラーはVPNルートの問題ではない
一方のエラーは割り当て中に、もう一方はルート変更後に起こる。コンテナのアドレスやトンネルに触る前にIPAMのサブネットを読め。
Dockerは、このアドレス空間でpoolが別のものと重複しているというメッセージとともにネットワークの作成を拒否する。すると、VPNルートが原因に違いないと誰かが決める。そうではありえない。このエラーはpoolの割り当て中、ひとつのパケットも存在する前に発生し、手動のカーネルルートはそれに何の影響も与えない。VPNが関係するのはその一歩後、すでにアドレスを持つコンテナが、ルートが現れた後に到達できなくなるときだ。二つの問題、二組の証拠であり、混ぜるとどちらも直らない変更になる。
似て見える二つのエラー
割り当てのエラーは算術だ。Dockerは要求されたサブネットを、すでに管理しているサブネットと比較し、交差を見つけて拒否する。まだ何も動いていないので、ルートもコンテナも、調べるべきトラフィックもない。
実行時の症状は到達性の問いだ。昨日は応答していたコンテナが今は応答せず、ホストのルーティングテーブルで何かが変わった。コンテナは依然として自分のアドレスを保持している。問題は、そのアドレスがどの経路を取るかだ。
どちらもアドレス計画の問題だ。Dockerの問題であるのは、そのうち片方だけだ。
まず割り当て済みのpoolを読む
ネットワークを一覧し、交差しうるものを調べる。サブネットはIPAM構成にあり、接続されたコンテナは別に一覧される。
docker network ls
docker network inspect EXISTING_NETWORK
そのサブネットを、新しいネットワークが要求するpoolと比較せよ。Composeはプロジェクトごとに独自の既定ネットワークを作ることを忘れないこと。忘れていたプロジェクトとの衝突は、デーモンとの衝突とまったく同じに見える。
サービス上の静的ipv4_addressはひとつのコンテナのアドレスであり、poolの定義ではない。それを変えても重複は消えない。重複はコンテナ間ではなく、ネットワークのサブネット間で起きるからだ。Dockerのnetwork-createリファレンスは、通常のブリッジ割り当てに重複しないサブネットを要求し、ひとつを明示的に選ぶ方法を記している。
VPNを生き延びるプレフィックスを選ぶ
目の前の衝突と将来のルートは同じ選択で決まる。だから一度だけ決めよ。候補の範囲をLAN、ホストが到達できるすべてのVPN宛先、使用中の他のあらゆるoverlayと比較する。
Dockerを満たしつつリモートネットワークと衝突するプレフィックスは、きれいに起動し、トンネルが上がった瞬間に到達不能になるコンテナを与える。これがこの記事の二つ目のエラーであり、後から診断するより今避けるほうがはるかに楽だ。
選んだ範囲は次のプロジェクトが読める場所に書き留めておく。割り当て済みプレフィックスの一行台帳は、説明のつかないタイムアウトの一週間より安い。
ネットワークを意図的に退役させるか変更する
新しいComposeネットワークでは、ネットワークのIPAM構成に未使用のプレフィックスを設定する。既存プロジェクトでは、再採番を計画する。固定アドレス、依存サービス、ネットワーク再作成の手順をすべて織り込む必要がある。YAMLを編集しても、稼働中のネットワークは再採番されないからだ。
使われなくなったネットワークが競合する割り当てを持っているなら、削除する前に誰が接続しているかを調べる。docker network rmはアクティブなエンドポイントがある間は拒否し、docker stopはネットワーク名ではなくコンテナ名かIDを取る。コンテナを止めても、poolを保持するネットワーク定義は消えない。
広範なpruneは診断ツールではない。無関係なプロジェクトにまで届き、これから集めようとしていた証拠を壊す。
既定のpoolは次の割り当てにしか役立たない
デーモンの既定アドレスpool設定は、予約した範囲の外に将来の自動割り当てを保つことで改善する。それはすでに存在するネットワークを遡って再アドレス指定しないし、別の明示的なサブネットと重複する明示的なサブネットも解決しない。
その設定は、独自の再起動を伴う別個の計画変更として扱い、ひとつのプロジェクトの修理の一部にしない。両者を混ぜると、デーモンの再起動が無関係な調査の最中に落ちる。独自の時間枠で予定を組む。そのうえで、新しい自動割り当てが実際に予約した範囲の外に落ちることを確認する。
作成が成功したら、実際に動いているサブネットを検証し、VPNを意図した状態にして本物のアプリケーションリクエストを一度行う。poolが有効でアクセスがまだ失敗するなら、残る作業はルート選択、フィルタリング、戻り経路だ。それは実行時の調査であり、割り当てエラーを遡って無意味にするものではない。
作業の順序は、割り当て済みpoolを読み、DockerとVPN宛先の両方をかわすプレフィックスを選び、ネットワークを意図的に作り直し、トンネルを上げた状態でひとつのリクエストを試すことだ。