Pod の sysctl でエラー: net.netfilter.nf_conntrack_max を Kubernetes 環境で扱うポイント
sysctl -w net.netfilter.nf_conntrack_max=262000 を Pod の initContainer で実行したらエラーになった。
sysctl: error setting key 'net.netfilter.nf_conntrack_max': Permission denied
同じ net.* でも、net.core.somaxconn はエラーにならない。
https://kubernetes.io/docs/tasks/administer-cluster/sysctl-cluster に原因が書かれているのだが、なかなか読み解くのに時間がかかったので、簡単にまとめておく。
結論
net.netfilter.nf_conntrack_max は node-level sysctls に分類される特殊なパラメーターで、 Node 上で直接設定するか、DaemonSet を利用する必要がある。
sysctl を Kubernetes で使うには
基本ルール
- sysctl インターフェースを使えば、カーネルパラメーターを変更できる。Kubernetes では、Pod から変更可能なパラメーターとそうでないものがある。
- Kubernetes はこれらのカーネルパラメーターを以下の2つの軸で分類している
- safe / unsafe
- Kubernetes が「安全」と判断したパラメーターのみ、Pod から変更可能
- unsafe な sysctl パラメーターを変更したい場合、
allowed-unsafe-sysctlsフラグで明示的に許可を与える必要がある
- namespaced / unnamespaced
- namespaced: Pod 内でスコープが閉じる(他のPodに影響しない)。
- unnamespaced: Node 全体に影響を与えるため、
node-level sysctlsと呼ばれ、Pod からの変更はできない。
- safe / unsafe
なぜ net.netfilter.nf_conntrack_max は変更できないのか?
net.netfilter.nf_conntrack_maxはnode-level sysctlsに分類されていて、Node 全体で共有されるパラメーターなので、Pod から変更できない。
読み解くのが難しかった記述
Kubernetes ドキュメントには以下の記述がある:
The following sysctls are known to be namespaced.
Those
net.*that can be set in container networking namespace. However, there are exceptions (e.g., net.netfilter.nf_conntrack_max and net.netfilter.nf_conntrack_expect_max can be set in container networking namespace but are unnamespaced before Linux 5.12.2).
最初、ここの意味がわからなかったので変更経緯を見た。 この記述を最初に読んだとき、「namespaced に見えるけど実際は違う」 という部分が直感的に理解しにくかったので、Linux カーネルの変更履歴を確認した。
Linux 5.12.2 より前
net.netfilter.nf_conntrack_maxにはバグがあり、Pod からは変更できるが、Node 全体に影響を与えるunnamespacedな挙動をしていた。- この挙動を修正するために パッチ が適用された。
Linux 5.12.2 以降
- このパッチにより、
net.netfilter.nf_conntrack_maxは Pod から変更できなくなり、一貫したunnamespacedパラメーターとして扱われるようになった。 - 結果、現在の環境では、Pod から操作しようとするとエラーになる
ドキュメントが間違っているわけではないけど、もう少し言葉を足してもいいかなと思うのでした。終わり。