こちらはITRC Advent Calendar 2020の4日目の記事です。
前の記事: @chaya2zさんのeBPF入門する
次の記事: 私のNetworkManagerで802.1xプロトコルを使用したwifiのホットスポットに機器を繋げたい
エラー文
failed to create endpoint [コンテナ名]
on network bridge: failed to add the host ([linuxの仮想インターフェイス名]
) <=> sandbox ([dockerの仮想インターフェイス名]
) pair interfaces: operation not supported
環境
Arch Linux
原因
カーネルアップデート後に正常に情報を受け取れなかった。
解決方法
再起動する
詳しくやる
今回のエラーで私はdockerがlinuxのカーネルで動いていると実感できたので、もっと詳しく原因を探ってみたいと思った。
詳細な原因
archlinuxではカーネルをアップデートすると/usr/lib/modules/[カーネルのバージョン]
にあるディレクトリが古いバージョンが削除されアップデートしたバージョンが入れ替わる。
dockerはここにあるモジュールを使っているのでディレクトリ名が変わり呼び出せなくなるのが原因。
今回必要としているモジュールはTUNモジュールでこれはネットワーク層をシミュレートし、IPパケットなどを操作できるものであり、今回はホスト(linux)とコンテナ(docker)間でvethによるL2のトンネルを張るために必要。
以上のことから
- TUNモジュールのロードが出来ていなく、ホスト(linux)とコンテナ(docker)間でネットワークを張れていない。
- 理由は
/usr/lib/modules/[カーネルのバージョン]
がカーネルアップデート前後でディレクトリ名が異なるから。 - 解決方法はカーネルを再読込みしてモジュールをロード出来るようにする
- よって、再起動する必要がある
どうしても再起動したくない場合
個人的に再起動して解決するとなんか負けた感があったので悪あがきとしての解決方法。
kexec
を使用する。kexec
は現在動作中のカーネルから他のカーネルをロードして起動でき、手動で更新することもsystemdを使用して更新することも出来る。詳細はこちら。
感想
とても恥ずかしい話なのですが前々からdockerはlinuxのカーネルを使って動いているという大雑把の理解しかしておらず、実感が湧かずに何となく使っていました。
それもその通りで書いて字の如く「実」際に「感」じてやっと動作していることを認識出来ました...
今回は再起動すれば直るエラーでしたが仕組みを知るのにとっつきやすそうだったので挑戦してみました。linuxカーネルの方ばかりになりdockerとの関係性を得られるようなエラーではありませんでしたが興味を持つきっかけになったので今度も関係性を探っていきたいです。
参考
- Docker: failed to add the pair interfaces (operation not supported) Serverfault
- TUN/TAP Wiki
- Kexec ArchWiki
失敗
私の知識不足で起きた失敗例を戒めのために記述しておく。
modprobeでモジュールをリロードする
そもそも古いカーネルバージョンのディレクトリが削除されて入れ替わっているので存在しないとエラーが出る。
-
modprobe
: カーネルモジュールをロードするコマンド -
depmod
: モジュールの依存関係リストを更新するコマンド -
lsmod
: ロード済みのカーネルモジュールを表示するコマンド
-
lsmod
で現在のモジュールを確認する -
modprobe
を使うためにdepmod
でモジュールの依存関係リストであるmodules.depファイルを更新する -
modprobe
でモジュールを更新する -
lsmod
でモジュールが更新された事を確認する