本記事は、Red Hat Advent Calendar 2023の12日目です。
Red Hatの林と申します。
今日はこれまでのCNIとこれからのCNIというテーマで昨今のCNIの状況を紹介したいと思います。
CNIは'Container Networking Interface'の略でKubernetes等のコンテナランタイムにおいて、コンテナにネットワークインターフェイスを作成するための機能をプラグインとして提供するCNCFのプロジェクトです。このプロジェクトでは主に以下の活動を行なっています。
- プラグインの仕様(Specification)の規定
この仕様を使って様々なベンダーがプラグインを提供しています - リファレンス実装としての基本的なプラグインの提供
CNIプロジェクトも同様に参考実装としてプラグインを提供しています - 仕様に基いたランタイムライブラリ・プラグイン用ライブラリの提供
今回はその中のプラグインの仕様について、現在の状況を紹介します。
仕様について
CNIは2015年に最初の仕様(0.1.0)を作成し、それ以降複数回の仕様のバージョンアップを行なってきました。ここでは現在最新の仕様である1.0.0と、今後出る予定の1.1.0、また現在議論されている2.0について紹介していきます。
ちなみに今回はCNIの仕様についての詳細な説明はしませんが、仕様については以下の場所にあります。また日本語のCNIの紹介記事もいろいろありますので基本的な情報はそちらを参考にして頂ければ幸いです。
- https://github.com/containernetworking/cni/blob/main/SPEC.md (現在策定中の仕様)
- https://github.com/containernetworking/cni/blob/main/CONVENTIONS.md (拡張仕様)
今の仕様についての変更点 (CNI Spec Version 1.0.0)
現在CNIの仕様の最新バージョンは2021年に作成された1.0.0となります。1.0.0では主に以下の変更がありました。
-
"plugins"
以外のコンフィグの廃止
"plugins"以外のコンフィグの廃止 (またはconfファイルの廃止)
0.4.0以前でサポートしていた下記のような、JSONのトップレベルに"type"
を宣言するコンフィグは廃止されました。
# 例: /etc/cni/net.d/01-sample031.conf
{
"cniVersion": "0.3.1",
"name": "sampleConfig031",
"type": "macvlan",
"ipam": {
"type": "dhcp"
}
}
1.0.0からは0.3.0で導入されたplugins
を使用したplugin chainingという形でのコンフィグのみになりました。この場合、CNIコンフィグのファイル名の拡張子はconfではなくconflistになります。
# 例: /etc/cni/net.d/01-sample100.conflist
{
"cniVersion": "1.0.0",
"name": "sampleConfig100",
"plugins": {
"type": "macvlan",
"ipam": {
"type": "dhcp"
}
}
}
しかし、confの拡張子は使えなくなった訳ではありません。ここで注意しておきたいのは"cniVersion"
を使うことでユーザ側で使うCNIの仕様バージョンを指定できることです。つまりconfの拡張子のファイルを使っていても"cniVersion": "0.3.1"
(または"cniVersion":"0.4.0"
)とコンフィグに書くことで古いバージョンのCNIの仕様を使えるので、conflistに必ずしも変更する必要はありません。ですので、厳密に言うと"cniVersion": "1.0.0"
とCNI 1.0.0の仕様を使用するように指定している場合、confの拡張子のファイルは使えないこととなります。
また、この他の変更点としてはCNIプラグインがコンテナランタイムに返す値に変更がありました("ips"
から"version"
の削除)が、ユーザ側には特に影響がないものなので、ここでは省略します。
これからの仕様についての変更点 (CNI Spec Version 1.1.0)
CNIコミュニティでは'master'ブランチのSPEC.mdが"次回リリースされる予定のCNIの仕様"となっており、更新が行なわれています。現在の予定だと次のCNIの仕様のバージョンは"1.1.0"の予定であり、以下の機能が追加される予定です。
- "STATUS"コマンドの追加
- "GC"コマンドの追加
これらのコマンドはプラグイン実装としてはオプショナルな機能であり、実装されるかされないかは各種CNIプラグイン側に委ねられることになります。
STATUSコマンド
STATUSコマンドはCNIプラグインが提供するネットワークの使用可能性(readiness)をコンテナランタイムに知らせるためのコマンドです。現在Kubernetesの場合、コンテナランタイムはCNIのコンフィグファイルがCNIのディレクトリ(主に/etc/cni/net.d)に置かれたことを確認すると、ネットワークが使用可能と考えています。
またCNIのディレクトリからCNIのコンフィグファイルが消えるとコンテナランタイムはネットワークが使用不可能と判断しています。
ですが、実際のところオーバーレイネットワークを提供しているネットワークプラグインの場合コンフィグファイルの生成タイミングとネットワークの使用可能のタイミングは必ずしも一致しません。またKubernetesの運用中に一時的にネットワークが使えない場合にそれをコンテナランタイムに伝えるといったユースケースも存在します。
"STATUS"コマンドはそういった目的の為に導入されました。
ちなみにこれらのコマンドは仕様として定義されるだけであり、実際にユーザが使うためには以下の実装が必要となるため、直ちに使用可能になる訳ではないことにお気をつけ下さい。
- CNIプラグイン側のコマンド実装
- コンテナランタイム側でのコマンド利用
- Kubernetes/コンテナランタイム間での通知
GCコマンド
GCコマンドは何らかのエラーでコンテナが異常終了した際にクリーンアップできなかったリソースをCNIで回収するようにするために導入されたコマンドです。
例としてコンテナランタイムが異常終了したり、コンテナを動かしているノード自身が再起動を行なった際、以前動かしていたコンテナが使っているIPアドレスが使用中のままになってしまうことがあります。現在ではいくつかのCNIプラグインは自身でそういったリソースを回収する方法を実装しているのですが、それをよりシンプルに実装するためにGCコマンドが導入されました。
GCといえば、Garbege Collectの略であり、ガーベージコレクトといったらマーク&スイープ方式を連想する方もいらっしゃると思うのですが、だいたい同じような形でGCコマンドは実行されます。つまり、GCコマンドに現在使用中のリソース一覧が渡されるので、その一覧に無いリソースを削除することが可能になるという方式です。
これからの仕様のその先…?
現在CNIコミュニティでは、1.1.0の先、次のメジャーバージョンである2.0についても議論が行なわれています。まだ議論も始まったばかりではあるので決まったことがないのですが以下のような点が議論にあがっています。
- CNIプラグインとランタイム間の通信にgRPCの導入
- Kubernetesをよりフォーカスした形でのフレームワークの変更
CNIプラグインとランタイム間の通信にgRPCの導入
多くのCNCFプロジェクトが採用しているgRPCをCNIでも導入すべきではないかという議論です。つまりCNIのプラグインはgRPCのサーバとなって動くことが想定されます。まだユースケースの議論でまだgRPCのスキームまで議論は進んでいません。
Kubernetesを意識した形でのフレームワークの拡張
現在のCNIの仕様では対象がコンテナランタイム(コンテナを動かすノード単位)を対象にネットワークを提供することをスコープとしていました。ですが、現在CNIが多く使われるケースはやぱりKubernetesであり、Kubernetesは複数のノードからなるクラスタで動作しています。 つまりCNIのスコープとKubernetesのスコープが異なる為、CNIではできないことが存在します(例:クラスタネットワークの初期化の完了イベント通知)。そのため次回のCNI2.0ではそういった、クラスタというスコープを使えるように変更していきたいという議論が行なわれています。
CNI2.0についてはまだ議論は始まったばかりであり、これから時間をかけて議論やデザインが進んでいくと思われます。