プロダクション環境のセットアップ

イントロダクション

あなたは LXD live online か、 なんらかのサーバで LXD を試してみました。結果に満足して、今度は LXD で 本格的な作業を試してみたいと思います。

何万ものファイル操作を必要とするコンテナーを使用する際の典型的な落とし穴を 避けるために、 Ubuntu Server 18.04 の素のインストール状態では、サーバ設定に いくつかの設定変更が必要です。

よく遭遇するエラー

Failed to allocate directory watch: Too many open files

<Error> <Error>: Too many open files

failed to open stream: Too many open files in...

neighbour: ndisc_cache: neighbor table overflow!

サーバの変更

/etc/security/limits.conf

ドメイン 種別 項目 デフォルト 説明
* soft nofile 1048576 未設定 オープンするファイルの最大数
* hard nofile 1048576 未設定 オープンするファイルの最大数
root soft nofile 1048576 未設定 オープンするファイルの最大数
root hard nofile 1048576 未設定 オープンするファイルの最大数
* soft memlock unlimited 未設定 ロックされたメモリ内の最大のアドレス空間 (KB)
* hard memlock unlimited 未設定 ロックされたメモリ内の最大のアドレス空間 (KB)

/etc/sysctl.conf

パラメータ デフォルト 説明
fs.inotify.max_queued_events 1048576 16384 これは対応する ionotify のインスタンスにキューイングされるイベント数の上限を指定します。 1
fs.inotify.max_user_instances 1048576 128 これは実ユーザー ID 毎に作成可能な ionotify のインスタンス数の上限を指定します。 1
fs.inotify.max_user_watches 1048576 8192 これは実ユーザー ID 枚に作成可能な watch 数の上限を指定します。 1
vm.max_map_count 262144 65530 このファイルはプロセスが持つメモリマップ領域の最大数を含みます。malloc の呼び出しの副作用として、 直接的にはmmap と mprotect によって、また、共有ライブラリーをロードすることによって、メモリマップ領域を使います。
kernel.dmesg_restrict 1 0 この設定を有効にするとコンテナーがカーネルのリングバッファー内のメッセージにアクセスするのを拒否します。この設定はホスト・システム上の非 root ユーザーへのアクセスも拒否することに注意してください。
net.ipv4.neigh.default.gc_thresh3 8192 1024 これは ARP テーブル (IPv4) 内のエントリーの最大数です。1024 個を超えるコンテナーを作成するなら増やすべきです。増やさなければ ARP テーブルがフルになったときに neighbour: ndisc_cache: neighbor table overflow! というエラーが発生し、コンテナーがネットワーク設定を取得できなくなります。 2
net.ipv6.neigh.default.gc_thresh3 8192 1024 これは ARP テーブル (IPv6) 内のエントリーの最大数です。1024 個を超えるコンテナーを作成するなら増やすべきです。増やさなければ ARP テーブルがフルになったときに neighbour: ndisc_cache: neighbor table overflow! というエラーが発生し、コンテナーがネットワーク設定を取得できなくなります。 2
net.core.bpf_jit_limit 3000000000 264241152 eBPF JIT アロケーションのサイズの上限値で、通常は PAGE_SIZE * 40000 に設定されます。カーネルが CONFIG_BPF_JIT_ALWAYS_ON=y の設定でコンパイルされている場合は /proc/sys/net/core/bpf_jit_enable1 に設定され変更できません。そのようなカーネルでは eBPF JIT コンパイラーは seccomp のような bpf のプログラムを JIT コンパイルする際の失敗を他のカーネルでは続行可能なエラーとして扱う場合でも致命的なエラーとして扱います。そのようなカーネルでは eBPF の JIT コンパイルされたプログラムのサイズの上限値は大幅に増やす必要があります。
kernel.keys.maxkeys 2000 200 非 root ユーザーが使用できるキーの最大数で、コンテナー数より大きくなければなりません
kernel.keys.maxbytes 2000000 20000 非 root ユーザーが使用できる keyring の最大サイズ <!-- This is the maximum size of the keyring non-root users can use ->

設定後、サーバの再起動が必要です。

ネットワーク帯域の調整

大量の (コンテナー・コンテナー間、あるいはホスト・コンテナー間の) ローカル・アクティビティを持つ LXD ホスト上に 1GbE 以上の NIC をお持ちか、 LXD ホストに 1GbE 以上のインターネット接続を お持ちでしたら、 txqueuelen を調整する価値があります。これらの設定は 10GbE NIC ではさらに よく機能します。

サーバの変更

txqueuelen

(あなたにとっての最適な値はわかりませんが) あなたの実 NIC の txqueuelen を 10000 に変える必要がある場合、 lxdbr0 インタフェースの txqueuelen も 10000 に 変更してください。

Debian ベースのディストリビューションでは /etc/network/interfaces 内で txqueuelen を恒久的に変更できます。 例えば up ip link set eth0 txqueuelen 10000 という設定を加えることで 起動時にインタフェースの txqueuelen の値を設定できます。

/etc/sysctl.conf

net.core.netdev_max_backlog の値も増やす必要があります。 /etc/sysctl.confnet.core.netdev_max_backlog = 182757 という設定を加えれば (再起動後に) 恒久的に設定できます。 (テストの目的で) netdev_max_backlog を一時的に設定するには echo 182757 > /proc/sys/net/core/netdev_max_backlog と実行します。 注意: この値が大きすぎると思うかもしれません。多くの人は netdev_max_backlog = net.ipv4.tcp_mem の最小値と設定することを好んでいます。 例えば私は net.ipv4.tcp_mem = 182757 243679 365514 という値を使用しています。

コンテナーの変更

コンテナー内のイーサネット・インタフェース全ての txqueuelen の値を変更する必要も あります。 Debian ベースのディストリビューションでは /etc/network/interfaces 内で恒久的に txqueuelen を変更できます。 例えば up ip link set eth0 txqueuelen 10000 という設定を加えることで 起動時にインタフェースの txqueuelen の値を設定できます。

この変更についての注意

10000 という txqueuelen の値は 10GbE NIC ではよく使われます。基本的には、 小さな txqueuelen の値は高レイテンシで低速なデバイスと低レイテンシで高速なデバイスで 使われます。個人的にはこれらの設定で (ホスト・コンテナー間、コンテナー・コンテナー間の) ローカル通信とインターネット接続が 3〜5% 改善しています。 txqueuelen の値の調整の良いところは、使用するコンテナー数が増えれば増えるほど、この 調整の恩恵を受けられることです。そして、この値はいつでも一時的に変更することができ、 あなたの環境で LXD ホストの再起動無しに変更の結果を確認することができます。