これは、このセクションの複数ページの印刷可能なビューです。 印刷するには、ここをクリックしてください.
Kubernetesブログ
- Kubernetesの10年間の歴史
- Kubernetes v1.30をそっと覗く
- CRI-O: OCIレジストリからのseccompプロファイルの適用
- Kubernetesブッククラブを覗く
- Kubernetesでコンテナを別ファイルシステムに格納する設定方法
- SIG Releaseスポットライト(リリース・チーム・サブプロジェクト)
- フォレンジックコンテナ分析
- Kubernetes 1.26: PodDisruptionBudgetによって保護された不健全なPodに対する退避ポリシー
- Kubernetesにおけるフォレンジックコンテナチェックポイント処理
- 更新: dockershimの削除に関するFAQ
- Don't Panic: Kubernetes and Docker
Kubernetesの10年間の歴史
翻訳者: Junya Okabe (University of Tsukuba), Daiki Hayakawa(bells17) (3-shake Inc.), Kaito Ii (Hewlett Packard Enterprise)
10年前の2014年6月6日、Kubernetesの最初のコミットがGitHubにプッシュされました。 Go、Bash、Markdownで書かれた250のファイルと47,501行のコードを含むその最初のコミットが、今日のKubernetesプロジェクトの始まりでした。 それから10年後の今日、Kubernetesが44か国から8,000社以上の企業、88,000人以上のコントリビューターを有する、これまでで最大のオープンソースプロジェクトの一つに成長するとは誰が予想したでしょうか。

このマイルストーンはKubernetesだけでなく、そこから生まれたクラウドネイティブエコシステムにとっても重要なものです。 CNCFには約200のプロジェクトがあり、240,000人以上のコントリビューターからのコントリビューションがあります。 また、より広いエコシステムの中でも数千人のコントリビューターがいます。 Kubernetesが今日の姿になれたのは、彼らや700万人以上の開発者、さらに多くのユーザーコミュニティがエコシステムを形作る手助けをしてくれたおかげです。
Kubernetesの始まり - 技術の収束
Kubernetesの元となるアイディアは、(2013年に登場した)最初のコミットや最初のプロトタイプの前から存在していました。 2000年代初頭、ムーアの法則が有効に機能していました。 コンピューティングハードウェアは非常に速い速度でますます強力になり、それに対応してアプリケーションもますます複雑化していきました。 このハードウェアのコモディティ化とアプリケーションの複雑化の組み合わせにより、ソフトウェアをハードウェアからさらに抽象化する必要が生じ、解決策が現れ始めました。
当時の多くの企業と同様にGoogleも急速に拡大しており、同社のエンジニアたちはLinuxカーネル内での隔離の形態を作り出すというアイデアに興味を持っていました。 Googleのエンジニア、Rohit Sethはそのコンセプトを2006年のメールで説明しました。
ワークロードのメモリやタスクなどのシステムリソースの使用を追跡し、課金する構造を示すためにコンテナという用語を使用します。

2013年3月、PyConでSolomon Hykesが行った5分間のライトニングトークThe future of Linux Containersでは、Linuxコンテナを作成および使用するためのオープンソースツールである「Docker」が紹介されました。 DockerはLinuxコンテナに使いやすさをもたらし、これまで以上に多くのユーザーが利用できるようになりました。 Dockerの人気が急上昇し、Linuxコンテナの抽象化を誰もが利用できるようにしたことで、アプリケーションをより移植性が高く、再現性のある方法で実行できるようになりました。 しかし、依然としてスケールの問題は残っていました。
Googleのアプリケーションオーケストレーションをスケールで管理するBorgシステムは、2000年代半ばにLinuxコンテナを採用しました。 その後、GoogleはOmegaと呼ばれるシステムの新バージョンの開発も開始しました。 BorgとOmegaシステムに精通していたGoogleのエンジニアたちは、Dockerによって駆動するコンテナ化の人気を目の当たりにしました。 そしてBrendan Burnsのブログで説明されているように、オープンソースのコンテナオーケストレーションシステムの必要性だけでなく、その「必然性」を認識しました。 この認識は2013年秋にJoe Beda、Brendan Burns、Craig McLuckie、Ville Aikas、Tim Hockin、Dawn Chen、Brian Grant、Daniel Smithを含む小さなチームにKubernetesのプロジェクトを始めるインスピレーションを与えました。
Kubernetesの10年間

Kubernetesの歴史は2014年6月6日のその歴史的なコミットと、2014年6月10日のDockerCon 2014でのGoogleエンジニアEric Brewerによる基調講演(およびそれに対応するGoogleブログ)でのプロジェクト発表から始まります。
その後の1年間で、主にGoogleとRed Hatからのコントリビューターによる小さなコミュニティがプロジェクトに取り組み、2015年7月21日にバージョン1.0のリリースに至りました。 1.0と同時に、GoogleはKubernetesをLinux Foundationの新たに設立された部門であるCloud Native Computing Foundation (CNCF)に寄贈することを発表しました。
1.0に到達したものの、Kubernetesプロジェクトは依然として使いにくく理解しにくいものでした。 KubernetesのコントリビューターであるKelsey Hightowerはプロジェクトの使いやすさの欠点に特に注目し、2016年7月7日に彼の有名な"Kubernetes the Hard Way"ガイドの最初のコミットをプッシュしました。
プロジェクトは最初の1.0リリース以来大きく変わり、いくつかの大きな成果を経験しました。 たとえば、1.16でのCustom Resource Definition (CRD)のGAや、1.23での完全なデュアルスタックサポートの開始などです。 また、1.22での広く使用されているベータ版APIの削除や、Dockershimの廃止から学んだコミュニティの「教訓」もあります。
1.0以降の注目すべきアップデート、マイルストーン、およびイベントには以下のものがあります。
- 2016年12月 - Kubernetes 1.5でCRIの最初のサポートとアルファ版Windowsノードサポートによるランタイムプラグイン機能が導入されました。また、OpenAPIが初めて登場し、クライアントが拡張されたAPIを認識できるようになりました。
- このリリースでは、StatefulSetとPodDisruptionBudgetがベータ版で導入されました。
- 2017年4月 - ロールベースアクセス制御(RBAC)の導入。
- 2017年6月 - Kubernetes 1.7でThirdPartyResource (TPR)がCustomResourceDefinition (CRD)に置き換えられました。
- 2017年12月 - Kubernetes 1.9ではWorkload APIがGA(一般提供)となりました。リリースブログには「Kubernetesで最もよく使用されるオブジェクトの一つであるDeploymentとReplicaSetは、1年以上の実際の使用とフィードバックを経て安定しました」と書かれています。
- 2018年12月 - Kubernetes 1.13でContainer Storage Interface (CSI)がGAに達しました。また最小限のクラスターをブートストラップするためのkubeadmツールがGAに達し、CoreDNSがデフォルトのDNSサーバーとなりました。
- 2019年9月 - Kubernetes 1.16でCustom Resource DefinitionがGAに達しました。
- 2020年8月 - Kubernetes 1.19でリリースのサポート期間が1年に延長されました。
- 2020年12月 - Kubernetes 1.20でDockershimが廃止されました。
- 2021年4月 - Kubernetesのリリース頻度が変更され、年間4回から3回に減少されました。
- 2021年7月 - 広く使用されているベータ版APIがKubernetes 1.22で削除されました。
- 2022年5月 - Kubernetes 1.24でベータ版APIがデフォルトで無効にされ、アップグレードの競合を減らすとともにDockershimが削除されました。その結果、多くのユーザーの混乱を引き起こしました(その後、コミュニケーションを改善しました)。
- 2022年12月 - Kubernetes 1.26ではAI/ML/バッチワークロードのサポートを強化するための大規模なバッチおよびJob APIのオーバーホールが行われました。
PS: プロジェクトがどれだけ進化したか自分で見てみたいですか? コミュニティメンバーのCarlos Santana、Amim Moises Salum Knabben、James Spurinが作成したKubernetes 1.0クラスターを立ち上げるためのチュートリアルをチェックしてみてください。
Kubernetesには数え切れないほどの拡張するポイントがあります。 もともとはDocker専用に設計されていましたが、現在ではCRI標準に準拠する任意のコンテナランタイムをプラグインできます。 他にもストレージ用のCSIやネットワーキング用のCNIなどのインターフェースがあります。 そしてこれはできることのほんの一部に過ぎません。 過去10年間で新しいパターンがいくつも登場しました。 例えば、Custom Resource Definition (CRD)を使用してサードパーティのコントローラーをサポートすることができます。 これは現在Kubernetesエコシステムの大きな一部となっています。
このプロジェクトを構築するコミュニティも、この10年間で非常に大きくなりました。 DevStatsを使用すると、この10年間でKubernetesを世界で2番目に大きなオープンソースプロジェクトにした驚異的なコントリビューションの量を確認できます。
- 88,474人のコントリビューター
- 15,121人のコードコミッター
- 4,228,347件のコントリビューション
- 158,530件のIssue
- 311,787件のPull Request
今日のKubernetes

初期の頃からこのプロジェクトは技術的能力、利用状況、およびコントリビューションの面で驚異的な成長を遂げてきました。 プロジェクトは今もなおユーザーにより良いサービスを提供するために積極的に改善に取り組んでいます。
次回の1.31リリースでは、長期にわたる重要なプロジェクトの完成を祝います。 それはインツリークラウドプロバイダーのコードの削除です。 このKubernetesの歴史上最大のマイグレーションでは、約150万行のコードが削除され、コアコンポーネントのバイナリサイズが約40%削減されました。 プロジェクトの初期には、拡張性が成功の鍵であることは明らかでした。 しかし、その拡張性をどのように実現するかは常に明確ではありませんでした。 このマイグレーションにより、Kubernetesの核となるコードベースからさまざまなベンダー固有の機能が削除されました。 ベンダー固有の機能は、今後はCustom Resource Definition (CRD)やGateway APIなどの他のプラグイン拡張機能やパターンによってよりよく提供されるようになります。
Kubernetesは、膨大なユーザーベースにサービスを提供する上で新たな課題にも直面しており、コミュニティはそれに適応しています。 その一例が、新しいコミュニティ所有のregistry.k8s.ioへのイメージホスティングの移行です。 ユーザーに事前コンパイル済みのバイナリイメージを提供するためのエグレスの帯域幅とコストは非常に大きなものとなっています。 この新しいレジストリの変更により、コミュニティはこれらの便利なイメージをよりコスト効率およびパフォーマンス効率の高い方法で提供し続けることができます。 必ずブログ記事をチェックし、registry.k8s.ioを使用するように更新してください!
Kubernetesの未来

10年が経ち、Kubernetesの未来は依然として明るく見えます。 コミュニティはユーザー体験の改善とプロジェクトの持続可能性を向上させる変更を優先しています。 アプリケーション開発の世界は進化し続けており、Kubernetesもそれに合わせて変化していく準備ができています。
2024年にはAIの登場がかつてニッチなワークロードタイプを重要なものへと変えました。 分散コンピューティングとワークロードスケジューリングは常に人工知能(AI)、機械学習(ML)、および高性能コンピューティング(HPC)ワークロードのリソース集約的なニーズと密接に関連してきました。 コントリビューターは、新しく開発されたワークロードのニーズとそれらにKubernetesがどのように最適に対応できるかに注目しています。 新しいServing Working Groupは、コミュニティがこれらのワークロードのニーズに対処するためにどのように組織化されているかの一例です。 今後数年でKubernetesがさまざまな種類のハードウェアを管理する能力や、ハードウェア全体でチャンクごとに実行される大規模なバッチスタイルのワークロードのスケジューリング能力に関して改善が見られるでしょう。
Kubernetesを取り巻くエコシステムは成長し続け、進化していきます。 将来的にはインツリーベンダーコードのマイグレーションやレジストリの変更など、プロジェクトの持続可能性を維持するための取り組みがますます重要になるでしょう。
Kubernetesの次の10年は、ユーザーとエコシステム、そして何よりもそれに貢献する人々によって導かれるでしょう。 コミュニティは新しいコントリビューターを歓迎しています。 コントリビューションに関する詳細は、新しいコントリビューター向けのガイドで確認できます。
Kubernetesの未来を一緒に築いていくことを楽しみにしています!

Kubernetes v1.30をそっと覗く
著者: Amit Dsouza, Frederick Kautz, Kristin Martin, Abigail McCarthy, Natali Vlatko
Kubernetes v1.30のおもしろい変更点をざっと見る
新しい年であり、新しいKubernetesのリリースです。 リリースサイクルの半分が終了し、v1.30ではかなりの数の興味深くおもしろい機能強化が行われます。 アルファ版の真新しい機能から、安定版へと進む既存の機能、そして待望の改良まで、このリリースには誰もが注目するものがあります!
正式リリースまでのつなぎとして、このリリースで我々がもっとも期待している機能強化をそっと覗いてみましょう!
Kubernetes v1.30の主な変更点
動的なリソース割り当てのための構造化パラメーター (KEP-4381)
動的なリソース割り当て(DRA)はv1.26でアルファ機能としてKubernetesに追加されました。 これは、サードパーティリソースへのアクセスを要求するための従来のデバイスプラグインAPIに代わるものを定義しています。 設計上、動的なリソース割り当て(DRA)では、Kubernetesの中心部に完全に不透明なリソースのパラメーターが使用されます。 このアプローチは、クラスターオートスケーラーや、Podのグループ(Jobスケジューラーなど)に対して決定を下す必要がある上位コントローラーにとって問題となります。 時間経過に伴う要求(claim)の割り当てや割り当て解除の効果をシミュレートできないのです。 これを行うための情報は、サードパーティのDRAドライバーのみが保有しています。
動的なリソース割り当て(DRA)の構造化パラメーターは、これらの要求(claim)パラメーターの不透明さがより少ないフレームワークを構築することによって、この問題に対処するための従来の実装の拡張になります。 すべての要求(claim)パラメーターのセマンティクスを自分で処理する代わりに、ドライバーはKubernetesによって事前定義された特定の"構造化モデル"を使用してリソースを記述し、管理できます。 これにより、この"構造化モデル"を認識しているコンポーネントは、サードパーティのコントローラーに委託することなく、これらのリソースに関する意思決定を行えます。 たとえば、スケジューラーは動的なリソース割り当て(DRA)ドライバーとやり取りを行うことなく、要求(claim)を迅速に割り当てることができます。 今回のリリースでは、さまざまな"構造化モデル"を実現するために必要なフレームワークの定義と"名前付きリソース"モデルの実装を中心に作業が行われました。 このモデルでは、個々のリソース・インスタンスをリストアップすることができ、従来のデバイスプラグインAPIと比較して、属性によってそれらのインスタンスを個別に選択する機能が追加されています。
Nodeのメモリスワップのサポート (KEP-2400)
Kubernetes v1.30では、Linux Nodeにおけるメモリスワップのサポートが、システムの安定性を向上させることに重点を置いて、その動作方法に大きな変更が加えられました。
以前のKubernetesバージョンでは、NodeSwap
フィーチャーゲートはデフォルトで無効化されており、有効化された場合、デフォルトの動作としてUnlimitedSwap
動作が使用されていました。
より良い安定性を達成するために、(Nodeの安定性を損なう可能性のある)UnlimitedSwap
動作はv1.30で削除されます。
更新された、まだベータ版のLinux Nodeでのスワップのサポートは、デフォルトで利用できるようになります。
ただし、デフォルトの動作は、NoSwap
(UnlimitedSwap
ではない)モードに設定されたNodeを実行することになります。
NoSwap
モードでは、kubeletはスワップ領域が有効化されたNodeでの実行をサポートしますが、Podはページファイルを一切使用しません。
そのNodeでkubeletを実行するには、--fail-swap-on=false
を設定する必要があります。
ただ、大きな変更とはこのことではなく、もう1つのモードであるLimitedSwap
です。
このモードでは、kubeletは実際にそのNodeのページファイルを使用し、Podが仮想メモリの一部をページアウトできるようにします。
コンテナ(およびその親Pod)はメモリ制限を超えてスワップにアクセスすることはできませんが、利用可能な場合はスワップ領域を使用できます。
KubernetesのNode Special Interest Group (SIG Node)は、エンドユーザー、貢献者、およびより広いKubernetesコミュニティからのフィードバックに基づいて、改訂された実装の使用方法を理解できるようにドキュメントも更新します。
KubernetesにおけるLinux Nodeのスワップ・サポートの詳細については、前回のブログ記事またはNodeのスワップ・ドキュメントを読んでください。
Podでユーザー名前空間のサポート (KEP-127)
ユーザー名前空間は、2024年1月に公開されたCVE-2024-21626を含むHigh/Criticalと評価された複数のCVEを防止、または緩和するために、Podをより適切に分離するLinux専用の機能です。 Kubernetes 1.30では、ユーザー名前空間のサポートがベータ版に移行し、ボリュームのあるPodとないPod、カスタムUID/GID範囲などがサポートされるようになりました!
構造化された認可設定 (KEP-3221)
構造化された認可設定のサポートはベータ版に移行し、デフォルトで有効になります。 この機能は、失敗時に明示的に拒否するなどのきめ細かな制御を可能にしたり、特定の順序でリクエストを検証する明確に定義されたパラメーターを持つ複数のWebhookによる認可チェーンの作成を可能にします。 設定ファイルのアプローチでは、リクエストがWebhookへ渡される前にCELルールを指定して事前にフィルタリングすることも可能で、不要なリクエストを防ぐのに役立ちます。 また、設定ファイルが変更されると、APIサーバーは自動的に認可チェーンを再読み込みします。
--authorization-config
コマンドライン引数を使用して、その認可設定へのパスを指定する必要があります。
設定ファイルの代わりにコマンドラインフラグを使い続けたい場合、そのまま機能し続けます。
複数のWebhook、失敗ポリシー、事前フィルタールールなどの新しい認可Webhook機能にアクセスするには、--authorization-config
ファイルにオプションを記述するように切り替えます。
Kubernetes 1.30からは、設定ファイルのフォーマットがベータ段階であり、フィーチャーゲートがデフォルトで有効になっているため、--authorization-config
を指定する必要があるだけです。
すべての可能な値を含む設定例は、認可ドキュメントで提供されています。
詳細については、認可ドキュメントを読んでください。
コンテナリソースをもとにしたPodの自動スケーリング (KEP-1610)
ContainerResource
メトリクスに基づく水平Pod自動スケーリングは、v1.30で安定版に移行します。
HorizontalPodAutoscalerのこの新しい動作により、Pod全体のリソース使用量ではなく、個々のコンテナのリソース使用量に基づいて自動スケーリングを設定できるようになります。
詳細については以前の記事を参照するか、コンテナリソースメトリクスを読んでください。
アドミッション・コントロールに対するCEL (KEP-3488)
Kubernetesのアドミッション・コントロールにCommon Expression Language (CEL)を統合することで、アドミッション・リクエストを評価するよりダイナミックで表現力豊かな方法が導入されます。 この機能により、複雑できめ細かなポリシーがKubernetes APIを通じて直接定義・適用できるようになり、パフォーマンスや柔軟性を損なうことなく、セキュリティとガバナンスの機能が強化されます。
CELがKubernetesのアドミッション・コントロールに追加されたことで、クラスター管理者はWebhookベースのアクセス・コントローラーに頼ることなく、クラスターの望ましい状態やポリシーに対してAPIリクエストの内容を評価できる複雑なルールを作成できます。 このレベルの制御は、クラスター運用の効率性、セキュリティ、整合性を維持するために極めて重要であり、Kubernetes環境をより堅牢にし、さまざまなユースケースや要件へ適応できるようにします。 アドミッション・コントロールにCELを使用する詳細については、ValidatingAdmissionPolicyのAPIドキュメントを参照してください。
私たちと同じようにこのリリースを楽しみにしていただければ幸いです。数週間後の公式のリリース記事で、さらなるハイライトをお見逃しなく!
CRI-O: OCIレジストリからのseccompプロファイルの適用
著者: Sascha Grunert
翻訳者: Taisuke Okamoto (IDC Frontier Inc), atoato88 (NEC Corporation), Junya Okabe (University of Tsukuba)
seccompはセキュアなコンピューティングモードを意味し、Linuxカーネルのバージョン2.6.12以降の機能として提供されました。 これは、プロセスの特権をサンドボックス化し、ユーザースペースからカーネルへの呼び出しを制限するために使用できます。 Kubernetesでは、ノードに読み込まれたseccompプロファイルをPodやコンテナに自動的に適用することができます。
しかし、Kubernetesでseccompプロファイルを配布することは大きな課題です。 なぜなら、JSONファイルがワークロードが実行可能なすべてのノードで利用可能でなければならないからです。 Security Profiles Operatorなどのプロジェクトは、クラスター内でデーモンとして実行することでこの問題を解決しています。 この設定から、コンテナランタイムがこの配布プロセスの一部を担当できるかどうかが興味深い点です。
通常、ランタイムはローカルパスからプロファイルを適用します。たとえば:
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: container
image: nginx:1.25.3
securityContext:
seccompProfile:
type: Localhost
localhostProfile: nginx-1.25.3.json
プロファイルnginx-1.25.3.json
はkubeletのルートディレクトリ内にseccomp
ディレクトリを追加して利用可能でなければなりません。
これは、ディスク上のプロファイルのデフォルトの場所が/var/lib/kubelet/seccomp/nginx-1.25.3.json
になることを指しています。
プロファイルが利用できない場合、ランタイムは次のようにコンテナの作成に失敗します。
kubectl get pods
NAME READY STATUS RESTARTS AGE
pod 0/1 CreateContainerError 0 38s
kubectl describe pod/pod | tail
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 117s default-scheduler Successfully assigned default/pod to 127.0.0.1
Normal Pulling 117s kubelet Pulling image "nginx:1.25.3"
Normal Pulled 111s kubelet Successfully pulled image "nginx:1.25.3" in 5.948s (5.948s including waiting)
Warning Failed 7s (x10 over 111s) kubelet Error: setup seccomp: unable to load local profile "/var/lib/kubelet/seccomp/nginx-1.25.3.json": open /var/lib/kubelet/seccomp/nginx-1.25.3.json: no such file or directory
Normal Pulled 7s (x9 over 111s) kubelet Container image "nginx:1.25.3" already present on machine
Localhost
プロファイルを手動で配布する必要があるという大きな障害は、多くのエンドユーザーがRuntimeDefault
に戻るか、さらにはUnconfined
(seccompが無効になっている)でワークロードを実行することになる可能性が高いということです。
CRI-Oが救世主
KubernetesのコンテナランタイムCRI-Oは、カスタムアノテーションを使用してさまざまな機能を提供しています。
v1.30のリリースでは、アノテーションの新しい集合であるseccomp-profile.kubernetes.cri-o.io/POD
とseccomp-profile.kubernetes.cri-o.io/<CONTAINER>
のサポートが追加されました。
これらのアノテーションを使用すると、以下を指定することができます:
- 特定のコンテナ用のseccompプロファイルは、次のように使用されます:
seccomp-profile.kubernetes.cri-o.io/<CONTAINER>
(例:seccomp-profile.kubernetes.cri-o.io/webserver: 'registry.example/example/webserver:v1'
) - Pod内のすべてのコンテナに対するseccompプロファイルは、コンテナ名の接尾辞を使用せず、予約された名前
POD
を使用して次のように使用されます:seccomp-profile.kubernetes.cri-o.io/POD
- イメージ全体のseccompプロファイルは、イメージ自体がアノテーション
seccomp-profile.kubernetes.cri-o.io/POD
またはseccomp-profile.kubernetes.cri-o.io/<CONTAINER>
を含んでいる場合に使用されます
CRI-Oは、ランタイムがそれを許可するように構成されている場合、およびUnconfined
として実行されるワークロードに対してのみ、そのアノテーションを尊重します。
それ以外のすべてのワークロードは、引き続きsecurityContext
からの値を優先して使用します。
アノテーション単体では、プロファイルの配布にはあまり役立ちませんが、それらの参照方法が役立ちます! たとえば、OCIアーティファクトを使用して、通常のコンテナイメージのようにseccompプロファイルを指定できるようになりました。
apiVersion: v1
kind: Pod
metadata:
name: pod
annotations:
seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2
spec: …
イメージquay.io/crio/seccomp:v2
には、実際のプロファイル内容を含むseccomp.json
ファイルが含まれています。
ORASやSkopeoなどのツールを使用して、イメージの内容を検査できます。
oras pull quay.io/crio/seccomp:v2
Downloading 92d8ebfa89aa seccomp.json
Downloaded 92d8ebfa89aa seccomp.json
Pulled [registry] quay.io/crio/seccomp:v2
Digest: sha256:f0205dac8a24394d9ddf4e48c7ac201ca7dcfea4c554f7ca27777a7f8c43ec1b
jq . seccomp.json | head
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"defaultErrno": "ENOSYS",
"archMap": [
{
"architecture": "SCMP_ARCH_X86_64",
"subArchitectures": [
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
# イメージのプレーンマニフェストを調べる
skopeo inspect --raw docker://quay.io/crio/seccomp:v2 | jq .
{
"schemaVersion": 2,
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"config":
{
"mediaType": "application/vnd.cncf.seccomp-profile.config.v1+json",
"digest": "sha256:ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
"size": 3,
},
"layers":
[
{
"mediaType": "application/vnd.oci.image.layer.v1.tar",
"digest": "sha256:92d8ebfa89aa6dd752c6443c27e412df1b568d62b4af129494d7364802b2d476",
"size": 18853,
"annotations": { "org.opencontainers.image.title": "seccomp.json" },
},
],
"annotations": { "org.opencontainers.image.created": "2024-02-26T09:03:30Z" },
}
イメージマニフェストには、特定の必要な構成メディアタイプ(application/vnd.cncf.seccomp-profile.config.v1+json
)への参照と、seccomp.json
ファイルを指す単一のレイヤー(application/vnd.oci.image.layer.v1.tar
)が含まれています。
それでは、この新機能を試してみましょう!
特定のコンテナやPod全体に対してアノテーションを使用する
CRI-Oは、アノテーションを利用する前に適切に構成する必要があります。
これを行うには、ランタイムの allowed_annotations
配列にアノテーションを追加します。
これは、次のようなドロップイン構成/etc/crio/crio.conf.d/10-crun.conf
を使用して行うことができます:
[crio.runtime]
default_runtime = "crun"
[crio.runtime.runtimes.crun]
allowed_annotations = [
"seccomp-profile.kubernetes.cri-o.io",
]
それでは、CRI-Oを最新のmain
コミットから実行します。
これは、ソースからビルドするか、静的バイナリバンドルを使用するか、プレリリースパッケージを使用することで行うことができます。
これを実証するために、local-up-cluster.sh
を使って単一ノードのKubernetesクラスターをセットアップし、コマンドラインからcrio
バイナリを実行しました。
クラスターが起動して実行されているので、seccomp Unconfined
として実行されているアノテーションのないPodを試してみましょう:
cat pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod
spec:
containers:
- name: container
image: nginx:1.25.3
securityContext:
seccompProfile:
type: Unconfined
kubectl apply -f pod.yaml
ワークロードが起動して実行中です:
kubectl get pods
NAME READY STATUS RESTARTS AGE
pod 1/1 Running 0 15s
crictl
を使用してコンテナを検査しても、seccompプロファイルが適用されていないことがわかります:
export CONTAINER_ID=$(sudo crictl ps --name container -q)
sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp
null
では、Podを変更して、コンテナにプロファイルquay.io/crio/seccomp:v2
を適用します:
apiVersion: v1
kind: Pod
metadata:
name: pod
annotations:
seccomp-profile.kubernetes.cri-o.io/container: quay.io/crio/seccomp:v2
spec:
containers:
- name: container
image: nginx:1.25.3
新しいseccompプロファイルを適用するには、Podを削除して再作成する必要があります。 再作成のみが新しいseccompプロファイルを適用するためです:
kubectl delete pod/pod
pod "pod" deleted
kubectl apply -f pod.yaml
pod/pod created
CRI-Oのログには、ランタイムがアーティファクトを取得したことが示されます:
WARN[…] Allowed annotations are specified for workload [seccomp-profile.kubernetes.cri-o.io]
INFO[…] Found container specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io/container=quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=26ddcbe6-6efe-414a-88fd-b1ca91979e93 name=/runtime.v1.RuntimeService/CreateContainer
And the container is finally using the profile:
そして、コンテナは最終的にプロファイルを使用しています:
export CONTAINER_ID=$(sudo crictl ps --name container -q)
sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
ユーザーが接尾辞/container
を予約名/POD
に置き換えると、Pod内のすべてのコンテナに対して同じことが機能します。
たとえば:
apiVersion: v1
kind: Pod
metadata:
name: pod
annotations:
seccomp-profile.kubernetes.cri-o.io/POD: quay.io/crio/seccomp:v2
spec:
containers:
- name: container
image: nginx:1.25.3
コンテナイメージにアノテーションを使用する
特定のワークロードにOCIアーティファクトとしてseccompプロファイルを指定する機能は素晴らしいですが、ほとんどのユーザーはseccompプロファイルを公開されたコンテナイメージに関連付けたいと考えています。 これは、コンテナイメージ自体に適用されるメタデータであるコンテナイメージアノテーションを使用して行うことができます。 たとえば、Podmanを使用して、イメージのビルド中に直接イメージアノテーションを追加することができます:
podman build \
--annotation seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 \
-t quay.io/crio/nginx-seccomp:v2 .
プッシュされたイメージには、そのアノテーションが含まれます:
skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2 |
jq '.annotations."seccomp-profile.kubernetes.cri-o.io"'
"quay.io/crio/seccomp:v2"
そのイメージを使用して、CRI-OのテストPod定義に組み込む場合:
apiVersion: v1
kind: Pod
metadata:
name: pod
# Podのアノテーションが設定されていません
spec:
containers:
- name: container
image: quay.io/crio/nginx-seccomp:v2
その後、CRI-Oのログには、イメージのアノテーションが評価され、プロファイルが適用されたことが示されます:
kubectl delete pod/pod
pod "pod" deleted
kubectl apply -f pod.yaml
pod/pod created
INFO[…] Found image specific seccomp profile annotation: seccomp-profile.kubernetes.cri-o.io=quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Pulling OCI artifact from ref: quay.io/crio/seccomp:v2 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Retrieved OCI artifact seccomp profile of len: 18853 id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
INFO[…] Created container 116a316cd9a11fe861dd04c43b94f45046d1ff37e2ed05a4e4194fcaab29ee63: default/pod/container id=c1f22c59-e30e-4046-931d-a0c0fdc2c8b7 name=/runtime.v1.RuntimeService/CreateContainer
export CONTAINER_ID=$(sudo crictl ps --name container -q)
sudo crictl inspect $CONTAINER_ID | jq .info.runtimeSpec.linux.seccomp | head
{
"defaultAction": "SCMP_ACT_ERRNO",
"defaultErrnoRet": 38,
"architectures": [
"SCMP_ARCH_X86_64",
"SCMP_ARCH_X86",
"SCMP_ARCH_X32"
],
"syscalls": [
{
コンテナイメージの場合、アノテーションseccomp-profile.kubernetes.cri-o.io
はseccomp-profile.kubernetes.cri-o.io/POD
と同様に扱われ、Pod全体に適用されます。
さらに、この機能は、イメージにコンテナ固有のアノテーションを使用する場合にも機能します。
たとえば、コンテナの名前がcontainer1
の場合:
skopeo inspect --raw docker://quay.io/crio/nginx-seccomp:v2-container |
jq '.annotations."seccomp-profile.kubernetes.cri-o.io/container1"'
"quay.io/crio/seccomp:v2"
この機能の素晴らしい点は、ユーザーが特定のコンテナイメージ用のseccompプロファイルを作成し、同じレジストリ内に並べて保存できることです。 イメージをプロファイルにリンクすることで、アプリケーション全体のライフサイクルを通じてそれらを維持する柔軟性が提供されます。
ORASを使用してプロファイルをプッシュする
OCIオブジェクトを作成してseccompプロファイルを含めるには、ORASを使用する場合、もう少し作業が必要です。
将来的には、Podmanなどのツールが全体のプロセスをより簡略化することを期待しています。
現時点では、コンテナレジストリがOCI互換である必要があります。
これはQuay.ioの場合も同様です。
CRI-Oは、seccompプロファイルオブジェクトがコンテナイメージメディアタイプ(application/vnd.cncf.seccomp-profile.config.v1+json
)を持っていることを期待していますが、ORASはデフォルトでapplication/vnd.oci.empty.v1+json
を使用します。
これを実現するために、次のコマンドを実行できます:
echo "{}" > config.json
oras push \
--config config.json:application/vnd.cncf.seccomp-profile.config.v1+json \
quay.io/crio/seccomp:v2 seccomp.json
結果として得られるイメージには、CRI-Oが期待するmediaType
が含まれています。
ORASは単一のレイヤーseccomp.json
をレジストリにプッシュします。
プロファイルの名前はあまり重要ではありません。
CRI-Oは最初のレイヤーを選択し、それがseccompプロファイルとして機能するかどうかを確認します。
将来の作業
CRI-OはOCIアーティファクトを通常のファイルと同様に内部で管理しています。
これにより、それらを移動したり、使用されなくなった場合に削除したり、seccompプロファイル以外のデータを利用したりする利点が得られます。
これにより、OCIアーティファクトをベースにしたCRI-Oの将来の拡張が可能になります。
また、OCIアーティファクトの中に複数のレイヤーを持つことを考える上で、seccompプロファイルの積層も可能になります。
v1.30.xリリースではUnconfined
ワークロードのみがサポートされているという制限は、将来CRI-Oが解決したい課題です。
セキュリティを損なうことなく、全体的なユーザーエクスペリエンスを簡素化することが、コンテナワークロードにおけるseccompの成功の鍵となるようです。
CRI-Oのメンテナーは、新機能に関するフィードバックや提案を歓迎します! このブログ投稿を読んでいただき、ぜひKubernetesのSlackチャンネル#crioを通じてメンテナーに連絡したり、GitHubリポジトリでIssueを作成したりしてください。
Kubernetesブッククラブを覗く
著者: Frederico Muñoz (SAS Institute)
Kubernetesとそれを取り巻く技術のエコシステム全体を学ぶことは、課題がないわけではありません。 このインタビューでは、AWSのCarlos Santanaさんに、コミュニティベースの学習体験を利用するために、彼がどのようにしてKubernetesブッククラブを作ったのか、その会がどのような活動をするのか、そしてどのようにして参加するのかについて伺います。
Frederico Muñoz (FSM): こんにちはCarlosさん、時間をとってくれてありがとう。 まずはじめに、ご自身のことを少し教えていただけますか?
Carlos Santana (CS): もちろんです。 6年前に本番環境でKubernetesをデプロイした経験が、Knativeに参加するきっかけとなり、その後リリースチームを通じてKubernetesに貢献しました。 アップストリームのKubernetesでの作業は、私がオープンソースで得た最高の経験のひとつです。 過去2年間、AWSのシニア・スペシャリスト・ソリューション・アーキテクトとしての役割で、私は大企業がKubernetes上に内部開発者プラットフォーム(IDP)を構築することを支援してきました。 今後、私のオープンソースへの貢献は、ArgoやCrossplane、BackstageのようなCNCFのプロジェクトやCNOEを対象にしています。
ブッククラブの創設
FSM: それであなたがKubernetesに辿り着いたわけですが、その時点でブッククラブを始めた動機は何だったのでしょうか?
CS: Kubernetesブッククラブのアイデアは、TGIKのライブ配信での何気ない提案から生まれました。 私にとって、それは単に本を読むということ以上に、学習コミュニティを作るということでした。 このプラットフォームは知識の源であるだけでなく、特にパンデミックの困難な時期にはサポートシステムでもありました。 この取り組みが、メンバーたちの対処と成長に役立っていることを目の当たりにして、喜ばしいと思っています。 最初の本Production Kubernetesは、2021年3月5日に始めて36週間かかりました。 現在は、1冊の本をカバーするのにそれほど時間はかからず、1週間に1章か2章です。
FSM: Kubernetesブッククラブの仕組みについて教えてください。どのように本を選び、どのように読み進めるのですか?
CS: 私たちは、グループの関心とニーズに基づいて本を共同で選んでいます。 この実践的なアプローチは、メンバー、とくに初心者が複雑な概念をより簡単に理解するのに役立ちます。 毎週2つのシリーズがあり、EMEAのタイムゾーンのものと、私がUSで組織しているものです。 各オーガナイザーは共同ホストと協力してSlack上で本を選び、各章の議論するために、数週間に渡りホストのラインナップを整えます。
FSM: 私の記憶が間違っていなければ、Kubernetesブッククラブは17冊目に突入しています。 物事を活発に保つための秘密のレシピがあるのですか?
CS: ブッククラブを活発で魅力的なものに保つ秘訣は、いくつかの重要な要素にあります。
まず、一貫性が重要です。 休みの日やKubeConのような大きなイベントの時だけミーティングをキャンセルして、定期的なスケジュールを維持するよう努力しています。 この規則性は、メンバーの参加を維持し、信頼できるコミュニティを築くのに役立っています。
次に、セッションを面白く、対話式のものにすることが重要です。 たとえば、ミートアップ中にポップアップ・クイズを頻繁に導入します。これはメンバーの理解度をテストするだけでなく、楽しみの要素も加えています。 このアプローチによって内容の関連性が維持され、理論的な概念が実社会のシナリオでどのように適用されるかをメンバーが理解するのに役立ちます。
ブッククラブで扱うトピック
FSM: 書籍の主なトピックは、Kubernetes、GitOps、セキュリティ、SRE、オブザーバビリティになっています。 これはとくに人気という観点で、Cloud Native Landscapeの反映でしょうか?
CS: 私たちの旅は『Production Kubernetes』から始まり、実用的な本番環境向けのソリューションに焦点を当てる方向性を設定しました。 それ以来、私たちはCNCF Landscapeのさまざまな側面を掘り下げ、異なるテーマに沿って本を揃えています。 各テーマは、それがセキュリティであれ、オブザーバビリティであれ、サービスメッシュであれ、コミュニティ内の関連性と需要にもとづいて選択されています。 たとえば、Kubernetes認定に関する最近のテーマでは、書籍の著者を積極的なホストとして参加させ、彼らの専門知識で議論を充実させました。
FSM: プロジェクトに最近変化があったことは知っています。Cloud Native Community GroupとしてCNCFに統合されたことです。 この変更について少しお話いただけますか?
CS: CNCFはブッククラブをCloud Native Community Groupとして快く受け入れてくれました。 これは私たちの運営を合理化し、影響範囲を拡大する重要な進展です。 この連携はKubernetes Community Days (KCD)のミートアップで使用されているものと同様に、管理機能の強化に役立っています。 現在では、メンバーシップ、イベントのスケジューリング、メーリングリスト、Webカンファレンスの開催、セッションの記録など、より強固な体制が整っています。
FSM: CNCFとの関わりは、この半年間のKubernetesブッククラブの成長やエンゲージメントにどのような影響を与えましたか?
CS: 半年前にCNCFコミュニティの一員になって以来、Kubernetesブッククラブでは大きな定量的な変化を目の当たりにしてきました。 会員数は600人以上に急増し、この間に40以上のイベントを企画・実施することに成功しました。 さらに期待されるのは、1回のイベントに平均30人が参加するという安定した動員数です。 この成長とエンゲージメントは、コミュニティにおける影響やKubernetesブッククラブの影響範囲に関して、私たちのCNCF加盟が肯定的な影響である明確な指標です。
ブッククラブに参加する
FSM: 参加を希望する人は、どうすればいいのでしょうか?
CS: 参加するためには3つの段階があります。
- まず、Kubernetesブッククラブコミュニティに参加します
- 次に、コミュニティページ上のイベントに出欠連絡をします
- 最後に、CNCFのSlackチャンネル#kubernetes-book-clubに参加します
FSM: 素晴らしい、ありがとうございます!最後に何かコメントをお願いします。
CS: Kubernetesブッククラブは、単に本について議論する専門家のグループというだけではなく、それ以上です。 それは、Neependra Khareさん、Eric Smallingさん、Sevi Karakulakさん、Chad M. Crowellさん、そしてWalid (CNJ) Shaariさんの主催と企画を手伝ってくれる素晴らしいボランティアであり、活気のあるコミュニティです。 KubeConで私たちを見て、Kubernetesブッククラブのステッカーをゲットしてください!
Kubernetesでコンテナを別ファイルシステムに格納する設定方法
著者: Kevin Hannon (Red Hat)
翻訳者: Taisuke Okamoto (IDC Frontier Inc), Junya Okabe (University of Tsukuba), nasa9084 (LY Corporation)
Kubernetesクラスターの稼働、運用する上でよくある問題は、ディスク容量が不足することです。
ノードがプロビジョニングされる際には、コンテナイメージと実行中のコンテナのために十分なストレージスペースを確保することが重要です。
通常、コンテナランタイムは/var
に書き込みます。
これは別のパーティションとして、ルートファイルシステム上に配置できます。
CRI-Oはデフォルトで、コンテナとイメージを/var/lib/containers
に書き込みますが、containerdはコンテナとイメージを/var/lib/containerd
に書き込みます。
このブログ記事では、コンテナランタイムがデフォルトのパーティションとは別にコンテンツを保存する方法に注目したいと思います。 これにより、Kubernetesの設定をより柔軟に行うことができ、デフォルトのファイルシステムはそのままに、コンテナストレージ用に大きなディスクを追加する方法が提供されます。
もう少し説明が必要な領域は、Kubernetesがディスクに書き込む場所/内容です。
Kubernetesディスク使用状況を理解する
Kubernetesには永続(persistent)データと一時(ephemeral)データがあります。
kubeletとローカルのKubernetes固有ストレージのベースパスは設定可能ですが、通常は/var/lib/kubelet
と想定されています。
Kubernetesのドキュメントでは、これは時々ルートファイルシステムまたはノードファイルシステムと呼ばれます。
このデータの大部分は、次のようにカテゴリー分けされます。
- エフェメラルストレージ
- ログ
- コンテナランタイム
ルート/ノード・ファイルシステムは/
ではなく、/var/lib/kubelet
があるディスクのため、ほとんどのPOSIXシステムとは異なります。
エフェメラルストレージ
Podやコンテナは、動作に一時的または短期的なローカルストレージを必要とする場合があります。 エフェメラルストレージの寿命は個々のPodの寿命を超えず、エフェメラルストレージはPod間で共有することはできません。
ログ
デフォルトでは、Kubernetesは各実行中のコンテナのログを/var/log
内のファイルとして保存します。
これらのログは一時的であり、ポッドが実行されている間に大きくなりすぎないようにkubeletによって監視されます。
各ノードのログローテーション設定をカスタマイズしてこれらのログのサイズを管理し、ノードローカルストレージに依存しないためにログの配信を設定することができます(サードパーティーのソリューションを使用)。
コンテナランタイム
コンテナランタイムには、コンテナとイメージのための2つの異なるストレージ領域があります。
-
読み取り専用レイヤー:イメージは通常、コンテナが実行されている間に変更されないため、読み取り専用レイヤーとして表されます。読み取り専用レイヤーには、複数のレイヤーが組み合わされて単一の読み取り専用レイヤーになることがあります。コンテナがファイルシステムに書き込んでいる場合、コンテナの上にはエフェメラルストレージを提供する薄いレイヤーがあります。
-
書き込み可能レイヤー:コンテナランタイムによっては、ローカルの書き込みがレイヤー化された書き込みメカニズム(たとえば、Linux上の
overlayfs
やWindows上のCimFS)として実装されることがあります。これは書き込み可能レイヤーと呼ばれます。ローカルの書き込みは、コンテナイメージの完全なクローンで初期化された書き込み可能なファイルシステムを使用する場合もあります。これは、ハイパーバイザ仮想化に基づく一部のランタイムで使用されます。
コンテナランタイムのファイルシステムには、読み取り専用レイヤーと書き込み可能レイヤーの両方が含まれます。これはKubernetesドキュメントではimagefs
と見なされています。
コンテナランタイムの構成
CRI-O
CRI-Oは、コンテナランタイムが永続データと一時データをどのように保存するかを制御するためのTOML形式のストレージ構成ファイルを使用します。
CRI-Oはストレージライブラリを利用します。
一部のLinuxディストリビューションには、ストレージに関するマニュアルエントリ(man 5 containers-storage.conf
)があります。
ストレージの主な設定は、/etc/containers/storage.conf
にあり、一時データの場所やルートディレクトリを制御することができます。
ルートディレクトリは、CRI-Oが永続データを保存する場所です。
[storage]
# Default storage driver
driver = "overlay"
# Temporary storage location
runroot = "/var/run/containers/storage"
# Primary read/write location of container storage
graphroot = "/var/lib/containers/storage"
graphroot
- コンテナランタイムから保存される永続データを指します
- SELinuxが有効になっている場合、これは
/var/lib/containers/storage
と一致させる必要があります
runroot
- コンテナに対する一時的な読み書きアクセスを提供します
- これは一時ファイルシステムに配置することを推奨します
ここでは、/var/lib/containers/storage
に合うようにgraphrootディレクトリのラベルを変更する簡単な方法を紹介します:
semanage fcontext -a -e /var/lib/containers/storage <YOUR-STORAGE-PATH>
restorecon -R -v <YOUR-STORAGE-PATH>
containerd
コンテナランタイムであるcontainerdは、永続データと一時データの保存先を制御するためのTOML形式の構成ファイルを使用します。構成ファイルのデフォルトパスは、/etc/containerd/config.toml
にあります。
containerdストレージの関連フィールドは、root
とstate
です。
root
- containerdのメタデータのルートディレクトリ
- デフォルトは
/var/lib/containerd
です - また、OSがそれを要求する場合は、ルートにSELinuxラベルも必要です
state
- containerdの一時データ
- デフォルトは、
/run/containerd
です
Kubernetesノードの圧迫による退避
Kubernetesは、コンテナファイルシステムがノードファイルシステムと分離されているかどうかを自動的に検出します。 ファイルシステムを分離する場合、Kubernetesはノードファイルシステムとコンテナランタイムファイルシステムの両方を監視する責任があります。 Kubernetesドキュメントでは、ノードファイルシステムとコンテナランタイムファイルシステムをそれぞれnodefsとimagefsと呼んでいます。 nodefsまたはimagefsのいずれかがディスク容量不足になると、ノード全体がディスク圧迫があると見なされます。 Kubernetesは、まず未使用のコンテナやイメージを削除してスペースを回収し、その後にポッドを追い出すことでスペースを再利用します。 nodefsとimagefsの両方を持つノードでは、kubeletはimagefs上の未使用のコンテナイメージをガベージコレクトし、nodefsからは終了したポッドとそれらのコンテナを削除します。 nodefsのみが存在する場合、Kubernetesのガベージコレクションには、終了したコンテナ、ポッド、そして未使用のイメージが含まれます。
Kubernetesでは、ディスクがいっぱいかどうかを判断するためのより多くの構成が可能です。
kubelet内の退避マネージャーには、関連する閾値を制御するいくつかの構成設定があります。
ファイルシステムの場合、関連する測定値はnodefs.available
、nodefs.inodesfree
、imagefs.available
、およびimagefs.inodesfree
です。
コンテナランタイム用に専用のディスクがない場合、imagefsは無視されます。
ユーザーは、既存のデフォルト値を使用できます:
memory.available
< 100MiBnodefs.available
< 10%imagefs.available
< 15%nodefs.inodesFree
< 5% (Linuxノード)
Kubernetesでは、kubeletの構成ファイル内のEvictionHard
とEvictionSoft
にユーザー定義の値を設定することができます。
EvictionHard
限界値を定義します。これらの限界値を超えると、Grace Periodなしでポッドが追い出されます。
EvictionSoft
限界値を定義します。これらの限界値を超えると、Grace Periodが設定されたシグナルごとにポッドが追い出されます。
EvictionHard
の値を指定すると、デフォルト値が置き換えられます。
したがって、すべてのシグナルを設定することが重要です。
たとえば、次に示すkubeletの設定は、退避シグナルと猶予期間オプションを設定するために使用できます。
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
address: "192.168.0.8"
port: 20250
serializeImagePulls: false
evictionHard:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
imagefs.inodesFree: "5%"
evictionSoft:
memory.available: "100Mi"
nodefs.available: "10%"
nodefs.inodesFree: "5%"
imagefs.available: "15%"
imagefs.inodesFree: "5%"
evictionSoftGracePeriod:
memory.available: "1m30s"
nodefs.available: "2m"
nodefs.inodesFree: "2m"
imagefs.available: "2m"
imagefs.inodesFree: "2m"
evictionMaxPodGracePeriod: 60s
問題点
Kubernetesプロジェクトでは、退避のデフォルト設定を使用するか、退避に関連するすべてのフィールドを設定することをお勧めしています。
デフォルト設定を使用するか、独自のevictionHard
設定を指定できます。
シグナルの設定を忘れると、Kubernetesはそのリソースを監視しません。
管理者やユーザーが遭遇する可能性のある一般的な設定ミスの1つは、新しいファイルシステムを/var/lib/containers/storage
または/var/lib/containerd
にマウントすることです。
Kubernetesは別のファイルシステムを検出するため、これを行った場合はimagefs.inodesfree
とimagefs.available
が必要に応じて設定に一致していることを確認する必要があります。
もう一つの混乱の領域は、イメージファイルシステムをノードに定義した場合でも、エフェメラルストレージの報告が変わらないことです。
イメージファイルシステム(imagefs
)は、コンテナイメージのレイヤーを保存するために使用されます。
コンテナが自分自身のルートファイルシステムに書き込む場合、そのローカルな書き込みはコンテナイメージのサイズには含まれません。
コンテナランタイムがこれらのローカルな変更を保存する場所は、ランタイムによって定義されますが、通常はイメージファイルシステムです。
Pod内のコンテナがファイルシステムをバックエンドとするemptyDir
ボリュームに書き込んでいる場合、これはノードファイルシステムからスペースを使用します。
kubeletは常に、nodefs
で表されるファイルシステムに基づいてエフェメラルストレージの容量と割り当てを報告します。
これは、実際には一時的な書き込みがイメージファイルシステムに行われている場合に混乱の原因となる可能性があります。
今後の課題
KEP-4191に取り組むことで、エフェメラルの報告の制限を解消し、コンテナランタイムにより多くの構成オプションを提供することが期待されています。 この提案では、Kubernetesは書き込み可能なレイヤーが読み取り専用のレイヤー(イメージ)と分離されているかどうかを検出します。 これにより、書き込み可能なレイヤーを含むすべてのエフェメラルストレージを同じディスクに配置することが可能になります。 また、イメージ用に別のディスクを使用することも可能になります。
参加するためにはどうすればよいですか?
参加したい場合は、KubernetesのSIG Nodeに参加することができます。
フィードバックを共有したい場合は、Slackチャンネルの#sig-nodeで行うことができます。 まだそのSlackワークスペースに参加していない場合は、https://slack.k8s.io/から招待状を取得できます。
素晴らしいレビューを提供し、貴重な洞察を共有し、トピックのアイデアを提案してくれたすべてのコントリビューターに特別な感謝を捧げます。
- Peter Hunt
- Mrunal Patel
- Ryan Phillips
- Gaurav Singh
SIG Releaseスポットライト(リリース・チーム・サブプロジェクト)
筆者: Nitish Kumar
リリース・スペシャル・インタレスト・グループ(SIG Release)は、Kubernetesが4ヶ月ごとに最先端の機能とバグ修正でその刃を研ぐ場所です。Kubernetesのような大きなプロジェクトが、新バージョンをリリースするまでのタイムラインをどのように効率的に管理しているのか、またリリースチームの内部はどのようになっているのか、考えたことはありますか?このような疑問に興味がある方、もっと知りたい方、SIG Releaseの仕事に関わりたい方は、ぜひ読んでみてください!
SIG ReleaseはKubernetesの開発と進化において重要な役割を担っています。その主な責任は、Kubernetesの新バージョンのリリースプロセスを管理することです。通常3〜4ヶ月ごとの定期的なリリースサイクルで運営されています。このサイクルの間、Kubernetesリリースチームは他のSIGやコントリビューターと密接に連携し、円滑でうまく調整されたリリースを保証します。これには、リリーススケジュールの計画、コードフリーズとテストフェーズの期限の設定、バイナリ、ドキュメント、リリースノートなどのリリース成果物の作成が含まれます。
さらに読み進める前に、SIG Releaseにはリリース・エンジニアリングとリリース・チームという2つのサブプロジェクトがあることに注意してください。
このブログ記事では、Nitish KumarがSIG Releaseのテクニカル・リーダーであるVerónica López (PlanetScale)にインタビューし、Release Teamサブプロジェクトにスポットライトを当て、リリース・プロセスがどのように見えるか、そして参加する方法について説明します。
-
最初の計画から最終的なリリースまで、Kubernetesの新バージョンの典型的なリリースプロセスはどのようなものですか?スムーズなリリースを保証するために使用している特定の方法論やツールはありますか?
Kubernetesの新バージョンのリリースプロセスは、十分に構造化されたコミュニティ主導の取り組みです。私たちが従う特定の方法論やツールはありませんが、物事を整理しておくための一連の手順を記載したカレンダーはあります。完全なリリースプロセスは次のようになります:
-
リリースチームの立ち上げ: 新しいリリースのさまざまなコンポーネントの管理を担当するKubernetesコミュニティのボランティアを含むリリースチームの結成から始めます。これは通常、前のリリースが終了する前に行われます。チームが結成されると、リリースチームリーダーとブランチマネージャーが通常の成果物のカレンダーを提案する間に、新しいメンバーがオンボードされます。例として、SIG Releaseのリポジトリに作成されたv1.29チーム結成のissueを見てください。コントリビューターがリリースチームの一員になるには、通常リリースシャドウプログラムを通りますが、それがSIG Releaseに参加する唯一の方法というわけではありません。
-
初期段階: 各リリースサイクルの最初の数週間で、SIG ReleaseはKubernetes機能強化提案(KEPs)で概説された新機能や機能強化の進捗を熱心に追跡します。これらの機能のすべてがまったく新しいものではありませんが、多くの場合、アルファ段階から始まり、その後ベータ段階に進み、最終的には安定したステータスに到達します。
-
機能の成熟段階: 通常、コミュニティからのフィードバックを集めるため、実験的な新機能を含むアルファ・リリースを2、3回行い、その後、機能がより安定し、バグの修正が中心となるベータ・リリースを2、3回行います。この段階でのユーザーからのフィードバックは非常に重要で、この段階で発生する可能性のあるバグやその他の懸念に対処するために、追加のベータ・リリースを作成しなければならないこともあります。これがクリアされると、実際のリリースの前にリリース候補(RC)を作成します。このサイクルを通じて、リリースノートやユーザーガイドなどのドキュメントの更新や改善に努めます。
-
安定化段階: 新リリースの数週間前にコードフリーズを実施し、この時点以降は新機能の追加を禁止します。メインリリースと並行して、私たちはKubernetesの古い公式サポートバージョンのパッチを毎月作成し続けているので、Kubernetesバージョンのライフサイクルはその後数ヶ月に及ぶと言えます。完全なリリースサイクル全体を通して、リリースノートやユーザーガイドを含むドキュメントの更新と改善に努めます。
-
各リリースで安定性と新機能の導入のバランスをどのように扱っていますか?どのような基準で、どの機能をリリースに含めるかを決定するのですか?
終わりのないミッションですが、重要なのは私たちのプロセスとガイドラインを尊重することだと考えています。私たちのガイドラインは、このプロジェクトに豊富な知識と経験をもたらしてくれるコミュニティの何十人ものメンバーから、何時間にもわたって議論とフィードバックを重ねた結果です。もし厳格なガイドラインがなかったら、私たちの注意を必要とするもっと生産的な議題に時間を使う代わりに、同じ議論を何度も繰り返してしまうでしょう。すべての重要な例外は、チームメンバーの大半の合意を必要とするため、品質を確保することができます。
何がリリースになるかを決定するプロセスは、リリースチームがワークフローを引き継ぐずっと前から始まっています。各SIGと経験豊富なコントリビューターが、機能や変更を含めるかどうかを決定します。その後、リリースチームが、それらの貢献がドキュメント、テスト、後方互換性などの要件を満たしていることを確認し、正式に許可します。同様のプロセスは月例パッチリリースのチェリーピックでも行われ、完全なKEPを必要とするPRや、影響を受けるすべてのブランチを含まない修正は受け入れないという厳しいポリシーがあります。
-
Kubernetesの開発とリリース中に遭遇した最も大きな課題は何ですか?これらの課題をどのように克服しましたか?
リリースのサイクルごとに、さまざまな課題が発生します。新たに発見されたCVE(Common Vulnerabilities and Exposures)のような土壇場の問題に取り組んだり、内部ツール内のバグを解決したり、以前のリリースの機能によって引き起こされた予期せぬリグレッションに対処したりすることもあります。私たちがしばしば直面するもう1つの障害は、私たちのチームは大規模ですが、私たちのほとんどがボランティアベースで貢献していることです。時には人手が足りないと感じることもありますが、私たちは常に組織化し、うまくやりくりしています。
-
新しい貢献者として、SIG Releaseに参加するための理想的な道はどのようなものでしょうか?誰もが自分のタスクに忙殺されているコミュニティで、効果的に貢献するために適切なタスクを見つけるにはどうすればいいのでしょうか?
オープンソースコミュニティへの関わり方は人それぞれです。SIG Releaseは、リリースを出荷できるように自分たちでツールを書くという、自分勝手なチームです。SIG K8s Infraのような他のSIGとのコラボレーションも多いのですが、私たちが使用するツールはすべて、コストを削減しつつ、私たちの大規模な技術的ニーズに合わせて作られたものでなければなりません。このため、「単に」リリースを作成するだけでなく、さまざまなタイプのプロジェクトを手伝ってくれるボランティアを常に探しています。
私たちの現在のプロジェクトでは、Goプログラミング、Kubernetes内部の理解、Linuxパッケージング、サプライチェーンセキュリティ、テクニカルライティング、一般的なオープンソースプロジェクトのメンテナンスなどのスキルが必要です。このスキルセットは、プロジェクトの成長とともに常に進化しています。
理想的な道筋として、私たちはこう提案します:
- どのように機能が管理されているか、リリースカレンダー、リリースチームの全体的な構造など、コードに慣れる。
- Slack(#sig-release)などのKubernetesコミュニティのコミュニケーションチャンネルに参加する。
- コミュニティ全員が参加できるSIG Releaseウィークリーミーティングに参加する。これらのミーティングに参加することは、あなたのスキルセットや興味に関連すると思われる進行中のプロジェクトや将来のプロジェクトについて学ぶ素晴らしい方法です。
経験豊富な貢献者は皆、かつてあなたのような立場にあったことを忘れないでください。遠慮せずに質問し、議論に参加し、貢献するための小さな一歩を踏み出しましょう。
-
リリースシャドウプログラムとは何ですか?また、他の様々なSIGに含まれるシャドウプログラムとの違いは何ですか?
リリースシャドウプログラムは、Kubernetesのリリースサイクルを通して、リリースチームの経験豊富なメンバーをシャドウイングする機会を提供します。これは、Kubernetesのリリースに必要な、サブチームにまたがるすべての困難な仕事を見るまたとないチャンスです。多くの人は、私たちの仕事は3ヶ月ごとにリリースを切ることだけだと思っていますが、それは氷山の一角にすぎません。
私たちのプログラムは通常、特定のKubernetesリリースサイクルに沿っており、それは約3ヶ月の予測可能なタイムラインを持っています。このプログラムではKubernetesの新機能を書くことはありませんが、リリースチームは新リリースと何千人ものコントリビューターとの最後のステップであるため、高い責任感が求められます。
-
一般的に、次のKubernetesリリースのリリースシャドウ/リリースリードとしてボランティアに参加する人に求める資格は何ですか?
どの役割もある程度の技術的能力を必要としますが、Goの実践的な経験やKubernetes APIに精通していることを必要とするものもあれば、技術的な内容を明確かつ簡潔に伝えるのが得意な人を必要とするものもあります。技術的な専門知識よりも、熱意とコミットメントを重視しています。もしあなたが正しい姿勢を持っていて、Kubernetesやリリース・エンジニアリングの仕事を楽しんでいることが伝われば、たとえそれがあなたが余暇を利用して立ち上げた個人的なプロジェクトであったとしても、チームは必ずあなたを指導します。セルフスターターであること、そして質問をすることを恐れないことは、私たちのチームであなたを大きく前進させます。
-
リリースシャドープログラムに何度も不合格になった人に何を勧めますか?
応募し続けることです。
リリースサイクルごとに応募者数が飛躍的に増えているため、選ばれるのが難しくなり、落胆することもありますが、不採用になったからといって、あなたに才能がないというわけではないことを知っておいてください。すべての応募者を受け入れることは現実的に不可能です、しかし、ここに私たちが提案する代替案があります。:
毎週開催されるKubernetes SIGのリリースミーティングに参加して、自己紹介をし、チームや私たちが取り組んでいるプロジェクトに慣れてください。
リリースチームはSIG Releaseに参加する方法の1つですが、私たちは常に手伝ってくれる人を探しています。繰り返しになりますが、一定の技術的な能力に加えて、私たちが最も求めている特性は、信頼できる人であり、それには時間が必要です。
-
リリースチームがKubernetes v1.28に特に期待している進行中の取り組みや今後の機能について教えてください。これらの進歩は、Kubernetesの長期的なビジョンとどのように整合しているのでしょうか?
Kubernetesのパッケージをコミュニティインフラ上でついに公開できることに興奮しています。数年前からやりたいと思っていたことですが、移行する前に整えなければならない技術的な意味合いが多いプロジェクトです。それが終われば、生産性を向上させ、ワークフロー全体をコントロールできるようになります。
最後に
さて、この対談はここで終わりですが、学習はこれで終わりではありません。このインタビューが、SIG Releaseが何をしているのか、そしてどのように手助けを始めたらいいのか、ある程度わかっていただけたと思います。重要なこととして、この記事はSIG Releaseの最初のサブプロジェクトであるリリース・チームを取り上げています。次回のSIG Releaseのスポットライトブログでは、Release Engineeringサブプロジェクトにスポットライトを当て、その活動内容や参加方法について紹介します。最後に、SIG Releaseの運営方法についてより深く理解するために、SIG Release憲章をご覧ください。
フォレンジックコンテナ分析
Authors: Adrian Reber (Red Hat)
前回投稿したKubernetesにおけるフォレンジックコンテナチェックポイント処理では、Kubernetesでのチェックポイントの作成や、それがどのようにセットアップされ、どのように使用されるのかを紹介しました。 機能の名前はフォレンジックコンテナチェックポイントですが、Kubernetesによって作成されたチェックポイントの実際の分析方法については、詳細を説明しませんでした。 この記事では、チェックポイントがどのように分析されるのかについての詳細を提供します。
チェックポイントの作成はまだKubernetesでalpha機能であり、この記事ではその機能が将来どのように動作するのかについてのプレビューを提供します。
準備
チェックポイント作成のサポートを有効にするためのKubernetesの設定方法や、基盤となるCRI実装方法についての詳細はKubernetesにおけるフォレンジックコンテナチェックポイント処理を参照してください。
一例として、この記事内でチェックポイントを作成し分析するコンテナイメージ(quay.io/adrianreber/counter:blog
)を準備しました。
このコンテナはコンテナ内でファイルを作成することができ、後でチェックポイント内で探したい情報をメモリーに格納しておくこともできます。
コンテナを実行するためにはPodが必要であり、この例では下記のPodマニフェストを使用します。
apiVersion: v1
kind: Pod
metadata:
name: counters
spec:
containers:
- name: counter
image: quay.io/adrianreber/counter:blog
この結果、counter
と呼ばれるコンテナがcounters
と呼ばれるPod内で実行されます。
一度コンテナが実行されると、コンテナで下記アクションが行えます。
$ kubectl get pod counters --template '{{.status.podIP}}'
10.88.0.25
$ curl 10.88.0.25:8088/create?test-file
$ curl 10.88.0.25:8088/secret?RANDOM_1432_KEY
$ curl 10.88.0.25:8088
最初のアクセスはコンテナ内でtest-file
という内容でtest-file
と呼ばれるファイルを作成します。
次のアクセスで、コンテナのメモリー内のどこかにシークレット情報(RANDOM_1432_KEY
)を記憶します。
最後のアクセスは内部のログファイルに1行追加するだけです。
チェックポイントを分析する前の最後のステップは、チェックポイントを作成することをKubernetesに指示することです。
前回の記事で説明したように、これにはkubelet限定のチェックポイント
APIエンドポイントへのアクセスを必要とします。
default名前空間内のcountersという名前のPod内のcounterという名前のコンテナに対して、kubelet APIエンドポイントが次の場所で到達可能です。
# Podが実行されているNode上で実行する
curl -X POST "https://localhost:10250/checkpoint/default/counters/counter"
厳密には、kubeletの自己署名証明書を許容しkubelet チェックポイント
APIの使用を認可するために、下記のcurl
コマンドのオプションが必要です。
--insecure --cert /var/run/kubernetes/client-admin.crt --key /var/run/kubernetes/client-admin.key
チェックポイントの作成が終了すると、/var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar
でチェックポイントが利用可能になります。
この記事の後述のステップでは、チェックポイントアーカイブを分析する際にcheckpoint.tar
という名前を使用します。
checkpointctl
を使用したチェックポイントアーカイブの分析
チェックポイントが作成したコンテナに関するいくつかの初期情報を得るためには、このようにcheckpointctlを使用します。
$ checkpointctl show checkpoint.tar --print-stats
+-----------+----------------------------------+--------------+---------+---------------------+--------+------------+------------+-------------------+
| CONTAINER | IMAGE | ID | RUNTIME | CREATED | ENGINE | IP | CHKPT SIZE | ROOT FS DIFF SIZE |
+-----------+----------------------------------+--------------+---------+---------------------+--------+------------+------------+-------------------+
| counter | quay.io/adrianreber/counter:blog | 059a219a22e5 | runc | 2023-03-02T06:06:49 | CRI-O | 10.88.0.23 | 8.6 MiB | 3.0 KiB |
+-----------+----------------------------------+--------------+---------+---------------------+--------+------------+------------+-------------------+
CRIU dump statistics
+---------------+-------------+--------------+---------------+---------------+---------------+
| FREEZING TIME | FROZEN TIME | MEMDUMP TIME | MEMWRITE TIME | PAGES SCANNED | PAGES WRITTEN |
+---------------+-------------+--------------+---------------+---------------+---------------+
| 100809 us | 119627 us | 11602 us | 7379 us | 7800 | 2198 |
+---------------+-------------+--------------+---------------+---------------+---------------+
これによって、チェックポイントアーカイブ内のチェックポイントについてのいくつかの情報が、すでに取得できています。
コンテナの名前やコンテナランタイムやコンテナエンジンについての情報を見ることができます。
チェックポイントのサイズ(CHKPT SIZE
)もリスト化されます。
これは大部分がチェックポイントに含まれるメモリーページのサイズですが、コンテナ内の全ての変更されたファイルのサイズ(ROOT FS DIFF SIZE
)についての情報もあります。
追加のパラメーター--print-stats
はチェックポイントアーカイブ内の情報を復号化し、2番目のテーブル(CRIU dump statistics)で表示します。
この情報はチェックポイント作成中に収集され、CRIUがコンテナ内のプロセスをチェックポイントするために必要な時間と、チェックポイント作成中に分析され書き込まれたメモリーページ数の概要を示します。
より深く掘り下げる
checkpointctl
の助けを借りて、チェックポイントアーカイブについてのハイレベルな情報を得ることができます。
チェックポイントアーカイブをさらに分析するには、それを展開する必要があります。
チェックポイントアーカイブはtarアーカイブであり、tar xf checkpoint.tar
の助けを借りて展開可能です。
チェックポイントアーカイブを展開すると、下記のファイルやディレクトリが作成されます。
bind.mounts
- このファイルにはバインドマウントについての情報が含まれており、復元中に全ての外部ファイルとディレクトリを正しい場所にマウントするために必要になります。checkpoint/
- このディレクトリにはCRIUによって作成された実際のチェックポイントが含まれています。config.dump
とspec.dump
- これらのファイルには、復元中に必要とされるコンテナについてのメタデータが含まれています。dump.log
- このファイルにはチェックポイント作成中に作成されたCRIUのデバッグ出力が含まれています。stats-dump
- このファイルには、checkpointctl
が--print-stats
でダンプ統計情報を表示するために使用するデータが含まれています。rootfs-diff.tar
- このファイルには、コンテナのファイルシステム上で変更された全てのファイルが含まれています。
ファイルシステムの変更 - rootfs-diff.tar
コンテナのチェックポイントをさらに分析するための最初のステップは、コンテナ内で変更されたファイルを見ることです。
これはrootfs-diff.tar
ファイルを参照することで行えます。
$ tar xvf rootfs-diff.tar
home/counter/logfile
home/counter/test-file
これでコンテナ内で変更されたファイルを調べられます。
$ cat home/counter/logfile
10.88.0.1 - - [02/Mar/2023 06:07:29] "GET /create?test-file HTTP/1.1" 200 -
10.88.0.1 - - [02/Mar/2023 06:07:40] "GET /secret?RANDOM_1432_KEY HTTP/1.1" 200 -
10.88.0.1 - - [02/Mar/2023 06:07:43] "GET / HTTP/1.1" 200 -
$ cat home/counter/test-file
test-file
このコンテナのベースになっているコンテナイメージ(quay.io/adrianreber/counter:blog
)と比較すると、コンテナが提供するサービスへの全てのアクセス情報を含んだlogfile
や予想通り作成されたtest-file
ファイルを確認することができます。
rootfs-diff.tar
の助けを借りることで、作成または変更された全てのファイルを、コンテナのベースイメージと比較して検査することが可能です。
チェックポイント処理したプロセスを分析する - checkpoint/
ディレクトリcheckpoint/
はコンテナ内でプロセスをチェックポイントしている間にCRIUによって作成されたデータを含んでいます。
ディレクトリcheckpoint/
の内容は、CRIUの一部として配布されているCRITツールを使用して分析できるさまざまなイメージファイルで構成されています。
まず、コンテナの内部プロセスの概要を取得してみましょう。
$ crit show checkpoint/pstree.img | jq .entries[].pid
1
7
8
この出力はコンテナのPID名前空間の内部に3つのプロセス(PIDが1と7と8)があることを意味しています。
これはコンテナのPID名前空間の内部からの視界を表示しているだけです。 復元中に正確にそれらのPIDが再作成されます。 コンテナのPID名前空間の外部からPIDは復元後に変更されます。
次のステップは、それらの3つのプロセスについての追加情報を取得することです。
$ crit show checkpoint/core-1.img | jq .entries[0].tc.comm
"bash"
$ crit show checkpoint/core-7.img | jq .entries[0].tc.comm
"counter.py"
$ crit show checkpoint/core-8.img | jq .entries[0].tc.comm
"tee"
これは、コンテナ内の3つのプロセスがbash
とcounter.py
(Pythonインタプリター)とtee
であることを意味しています。
プロセスの親子関係についての詳細は、checkpoint/pstree.img
に分析するデータがさらにあります。
ここまでで収集した情報をまだ実行中のコンテナと比較してみましょう。
$ crictl inspect --output go-template --template "{{(index .info.pid)}}" 059a219a22e56
722520
$ ps auxf | grep -A 2 722520
fedora 722520 \_ bash -c /home/counter/counter.py 2>&1 | tee /home/counter/logfile
fedora 722541 \_ /usr/bin/python3 /home/counter/counter.py
fedora 722542 \_ /usr/bin/coreutils --coreutils-prog-shebang=tee /usr/bin/tee /home/counter/logfile
$ cat /proc/722520/comm
bash
$ cat /proc/722541/comm
counter.py
$ cat /proc/722542/comm
tee
この出力では、まずコンテナ内の最初のプロセスのPIDを取得しています。
そしてコンテナを実行しているシステム上で、そのPIDと子プロセスを探しています。
3つのプロセスが表示され、最初のものはコンテナPID名前空間の中でPID 1である"bash"です。
次に/proc/<PID>/comm
を見ると、チェックポイントイメージと正確に同じ値を見つけることができます。
覚えておく重要なことは、チェックポイントはコンテナのPID名前空間内の視界が含まれていることです。 なぜなら、これらの情報はプロセスを復元するために重要だからです。
crit
がコンテナについて教えてくれる最後の例は、UTS名前空間に関する情報です。
$ crit show checkpoint/utsns-12.img
{
"magic": "UTSNS",
"entries": [
{
"nodename": "counters",
"domainname": "(none)"
}
]
}
UTS名前空間内のホストネームがcounters
であることを教えてくれます。
チェックポイント作成中に収集された各リソースCRIUについて、checkpoint/
ディレクトリは対応するイメージファイルを含んでいます。
このイメージファイルはcrit
を使用することで分析可能です。
メモリーページを見る
CRITを使用して復号化できるCRIUからの情報に加えて、CRIUがディスクに書き込んだ生のメモリーページを含んでいるファイルもあります。
$ ls checkpoint/pages-*
checkpoint/pages-1.img checkpoint/pages-2.img checkpoint/pages-3.img
最初にコンテナを使用した際に、メモリー内のどこかにランダムキー(RANDOM_1432_KEY
)を保存しました。
見つけることができるかどうか見てみましょう。
$ grep -ao RANDOM_1432_KEY checkpoint/pages-*
checkpoint/pages-2.img:RANDOM_1432_KEY
そして実際に、私のデータがあります。 この方法で、コンテナ内のプロセスの全てのメモリーページの内容を簡単に見ることができます。 しかし、チェックポイントアーカイブにアクセスできるなら誰でも、コンテナのプロセスのメモリー内に保存された全ての情報にアクセスできることを覚えておくことも重要です。
さらなる分析のためにgdbを使用する
チェックポイントイメージを見るための他の方法はgdb
です。
CRIUリポジトリは、チェックポイントをコアダンプファイルに変換するcoredumpスクリプトを含んでいます。
$ /home/criu/coredump/coredump-python3
$ ls -al core*
core.1 core.7 core.8
coredump-python3
スクリプトを実行すると、チェックポイントイメージがコンテナ内の各プロセスに対し1つのコアダンプファイルに変換されます。
gdb
を使用してプロセスの詳細を見ることもできます。
$ echo info registers | gdb --core checkpoint/core.1 -q
[New LWP 1]
Core was generated by `bash -c /home/counter/counter.py 2>&1 | tee /home/counter/logfile'.
#0 0x00007fefba110198 in ?? ()
(gdb)
rax 0x3d 61
rbx 0x8 8
rcx 0x7fefba11019a 140667595587994
rdx 0x0 0
rsi 0x7fffed9c1110 140737179816208
rdi 0xffffffff 4294967295
rbp 0x1 0x1
rsp 0x7fffed9c10e8 0x7fffed9c10e8
r8 0x1 1
r9 0x0 0
r10 0x0 0
r11 0x246 582
r12 0x0 0
r13 0x7fffed9c1170 140737179816304
r14 0x0 0
r15 0x0 0
rip 0x7fefba110198 0x7fefba110198
eflags 0x246 [ PF ZF IF ]
cs 0x33 51
ss 0x2b 43
ds 0x0 0
es 0x0 0
fs 0x0 0
gs 0x0 0
この例では、チェックポイント中の全てのレジストリの値を見ることができ、コンテナのPID 1のプロセスの完全なコマンドライン(bash -c /home/counter/counter.py 2>&1 | tee /home/counter/logfile
)を見ることもできます。
まとめ
コンテナチェックポイントを作成することで、コンテナを停止することやチェックポイントが作成されたことを知ることなく、実行中のコンテナのチェックポイントを作成することが可能です。
Kubernetesにおいてコンテナのチェックポイントを作成した結果がチェックポイントアーカイブです。
checkpointctl
やtar
、crit
、gdb
のような異なるツールを使用して、チェックポイントを分析できます。
grep
のようなシンプルなツールでさえ、チェックポイントアーカイブ内の情報を見つけることが可能です。
この記事で示したチェックポイントの分析方法のさまざまな例は出発点にすぎません。 この記事ではチェックポイントの分析を始める方法を紹介しましたが、要件によってはかなり詳細に特定の物事を見ることも可能です。
参加するためにはどうすればよいですか?
SIG Nodeにはいくつかの方法でアクセスできます。
- Slack: #sig-node
- Slack: #sig-security
- メーリングリスト
Kubernetes 1.26: PodDisruptionBudgetによって保護された不健全なPodに対する退避ポリシー
著者: Filip Křepinský (Red Hat), Morten Torkildsen (Google), Ravi Gudimetla (Apple)
アプリケーションの中断がその可用性に影響を与えないようにすることは、簡単な作業ではありません。 先月リリースされたKubernetes v1.26では、PodDisruptionBudget (PDB) に 不健全なPodの退避ポリシー を指定して、ノード管理操作中に可用性を維持できるようになりました。 この記事では、アプリケーション所有者が中断をより柔軟に管理できるようにするために、PDBにどのような変更が導入されたのかを詳しく説明します。
これはどのような問題を解決しますか?
APIによって開始されるPodの退避では、PodDisruptionBudget(PDB)が考慮されます。
これは、退避によるPodへの自発的な中断の要求は保護されたアプリケーションを中断してはならず、
PDBの.status.currentHealthy
が.status.desiredHealthy
を下回ってはいけないことを意味します。
Unhealthyな実行中のPodはPDBステータスにはカウントされませんが、
これらの退避はアプリケーションが中断されない場合にのみ可能です。
これにより、中断されたアプリケーションやまだ開始されていないアプリケーションが、退避によって追加のダウンタイムが発生することなく、できるだけ早く可用性を達成できるようになります。
残念ながら、これは手動の介入なしでノードをドレインしたいクラスター管理者にとって問題を引き起こします。
(バグまたは構成ミスにより)PodがCrashLoopBackOff
状態になっているアプリケーション、または単に準備ができていないPodがあるアプリケーションが誤動作している場合、このタスクはさらに困難になります。
アプリケーションのすべてのPodが正常でない場合、PDBの違反により退避リクエストは失敗します。その場合、ノードのドレインは進行できません。
一方で、次の目的で従来の動作に依存するユーザーもいます。
- 基盤となるリソースまたはストレージを保護しているPodの削除によって引き起こされるデータ損失を防止する
- アプリケーションに対して可能な限り最高の可用性を実現する
Kubernetes 1.26では、PodDisruptionBudget APIに新しい実験的フィールド.spec.unhealthyPodEvictionPolicy
が導入されました。
このフィールドを有効にすると、これらの要件の両方をサポートできるようになります。
どのように機能しますか?
APIによって開始される退避は、Podの安全な終了をトリガーするプロセスです。
このプロセスは、APIを直接呼び出すか、kubectl drain
コマンドを使用するか、クラスター内の他のアクターを使用して開始できます。
このプロセス中に、十分な数のPodが常にクラスター内で実行されていることを確認するために、すべてのPodの削除が適切なPDBと照合されます。
次のポリシーにより、PDBの作成者は、プロセスが不健全なPodを処理する方法をより詳細に制御できるようになります。
IfHealthyBudget
とAlwaysAllow
の2つのポリシーから選択できます。
前者のIfHealthyBudget
は、従来の動作に従って、デフォルトで得られる最高の可用性を実現します。
不健全なPodは、アプリケーションが利用可能な最小数の.status.desiredHealthy
だけPodがある場合にのみ中断できます。
PDBのspec.unhealthyPodEvictionPolicy
フィールドをAlwaysAllow
に設定することにより、アプリケーションにとってベストエフォートの可用性を選択することになります。
このポリシーを使用すると、不健全なPodをいつでも削除できます。これにより、クラスターの保守とアップグレードが容易になります。
多くの場合、AlwaysAllow
がより良い選択であると考えられますが、一部の重要なワークロードでは、
不健全なPodであってもノードドレインやAPIによって開始される他の形式の退避から保護する方が望ましい場合もあります。
どのように利用できますか?
これはアルファ機能であるため、kube-apiserverに対してコマンドライン引数--feature-gates=PDBUnhealthyPodEvictionPolicy=true
を指定して
PDBUnhealthyPodEvictionPolicy
フィーチャーゲートを有効にする必要があります。
ここに例を示します。クラスターでフィーチャーゲートを有効にし、プレーンなWebサーバーを実行するDeploymentをすでに定義していると仮定します。
そのDeploymentのPodにapp: nginx
というラベルを付けました。
回避可能な中断を制限したいと考えており、このアプリにはベストエフォートの可用性で十分であることがわかっています。
WebサーバーのPodが不健全な場合でも、退避を許可することにしました。
不健全なPodを排除するためのAlwaysAllow
ポリシーを使用して、このアプリケーションを保護するPDBを作成します。
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: nginx-pdb
spec:
selector:
matchLabels:
app: nginx
maxUnavailable: 1
unhealthyPodEvictionPolicy: AlwaysAllow
もっと学ぶには?
- KEPを読んでください: Unhealthy Pod Eviction Policy for PDBs
- PodDisruptionBudgetについてのドキュメントを読んでください: Unhealthy Pod Eviction Policy
- PodDisruptionBudget、draining of NodesおよびevictionsについてKubernetesドキュメントを確認してください
どうすれば参加できますか?
フィードバックがある場合は、Slackの#sig-apps チャンネル(必要な場合は https://slack.k8s.io/ にアクセスして招待を受けてください)、またはSIG Appsメーリングリストにご連絡ください。kubernetes-sig-apps@googlegroups.com
Kubernetesにおけるフォレンジックコンテナチェックポイント処理
Authors: Adrian Reber (Red Hat)
フォレンジックコンテナチェックポイント処理はCheckpoint/Restore In Userspace (CRIU)に基づいており、コンテナがチェックポイントされていることを認識することなく、実行中のコンテナのステートフルコピーを作成することができます。 コンテナのコピーは、元のコンテナに気づかれることなく、サンドボックス環境で複数回の分析やリストアが可能です。 フォレンジックコンテナチェックポイント処理はKubernetes v1.25でalpha機能として導入されました。
どのように機能しますか?
CRIUを使用してコンテナのチェックポイントやリストアを行うことが可能です。 CRIUはruncやcrun、CRI-O、containerdと統合されており、Kubernetesで実装されているフォレンジックコンテナチェックポイント処理は、既存のCRIU統合を使用します。
なぜ重要なのか?
CRIUと対応する統合機能を使用することで、後でフォレンジック分析を行うために、ディスク上で実行中のコンテナに関する全ての情報と状態を取得することが可能です。 フォレンジック分析は、疑わしいコンテナを停止したり影響を与えることなく検査するために重要となる場合があります。 コンテナが本当に攻撃を受けている場合、攻撃者はコンテナを検査する処理を検知するかもしれません。 チェックポイントを取得しサンドボックス環境でコンテナを分析することは、元のコンテナや、おそらく攻撃者にも検査を認識されることなく、コンテナを検査することができる可能性があります。
フォレンジックコンテナチェックポイント処理のユースケースに加えて、内部状態を失うことなく、あるノードから他のノードにコンテナを移行することも可能です。 特に初期化時間の長いステートフルコンテナの場合、チェックポイントからリストアすることは再起動後の時間が節約されるか、起動時間がより早くなる可能性があります。
コンテナチェックポイント処理を利用するには?
機能はフィーチャーゲートで制限されているため、新しい機能を使用する前にContainerCheckpoint
を有効にしてください。
ランタイムがコンテナチェックポイント処理をサポートしている必要もあります。
- containerd: サポートは現在検討中です。詳細はcontainerdプルリクエスト#6965を見てください。
- CRI-O: v1.25はフォレンジックコンテナチェックポイント処理をサポートしています。
CRI-Oでの使用例
CRI-Oとの組み合わせでフォレンジックコンテナチェックポイント処理を使用するためには、ランタイムをコマンドラインオプション--enable-criu-support=true
で起動する必要があります。
Kubernetesでは、ContainerCheckpoint
フィーチャーゲートを有効にしたクラスターを実行する必要があります。
チェックポイント処理の機能はCRIUによって提供されているため、CRIUをインストールすることも必要となります。
通常、runcやcrunはCRIUに依存しているため、自動的にインストールされます。
執筆時点ではチェックポイント機能はCRI-OやKubernetesにおいてalpha機能としてみなされており、セキュリティ影響がまだ検討中であることに言及することも重要です。
コンテナとPodが実行されると、チェックポイントを作成することが可能になります。
チェックポイント処理はkubeletレベルでのみ公開されています。
コンテナをチェックポイントするためには、コンテナが実行されているノード上でcurl
を実行し、チェックポイントをトリガーします。
curl -X POST "https://localhost:10250/checkpoint/namespace/podId/container"
default名前空間内のcountersと呼ばれるPod内のcounterと呼ばれるコンテナに対し、kubelet APIエンドポイントが次の場所で到達可能です。
curl -X POST "https://localhost:10250/checkpoint/default/counters/counter"
厳密には、kubeletの自己署名証明書を許容し、kubeletチェックポイントAPIの使用を認可するために、下記のcurlコマンドのオプションが必要です。
--insecure --cert /var/run/kubernetes/client-admin.crt --key /var/run/kubernetes/client-admin.key
このkubelet APIが実行されると、CRI-Oからチェックポイントの作成をリクエストします。
CRI-Oは低レベルランタイム(例えばrunc
)からチェックポイントをリクエストします。
そのリクエストを確認すると、runc
は実際のチェックポイントを行うためにcriu
ツールを呼び出します。
チェックポイント処理が終了すると、チェックポイントは/var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar
で利用可能になります。
その後、そのtarアーカイブを使用してコンテナを別の場所にリストアできます。
Kubernetesの外部でチェックポイントしたコンテナをリストアする(CRI-Oを使用)
チェックポイントtarアーカイブを使用すると、CRI-Oのサンドボックスインスタンス内のKubernetesの外部にコンテナをリストア可能です。 リストア中のより良いユーザエクスペリエンスのために、main CRI-O GitHubブランチからCRI-Oのlatestバージョンを使用することを推奨します。 CRI-O v1.25を使用している場合、コンテナを開始する前にKubernetesが作成する特定のディレクトリを手動で作成する必要があります。
Kubernetesの外部にコンテナをリストアするための最初のステップは、crictlを使用してPodサンドボックスを作成することです。
crictl runp pod-config.json
次に、さきほどチェックポイントしたコンテナを新しく作成したPodサンドボックスにリストアします。
crictl create <POD_ID> container-config.json pod-config.json
container-config.json
のレジストリでコンテナイメージを指定する代わりに、前に作成したチェックポイントアーカイブへのパスを指定する必要があります。
{
"metadata": {
"name": "counter"
},
"image":{
"image": "/var/lib/kubelet/checkpoints/<checkpoint-archive>.tar"
}
}
次に、そのコンテナを開始するためにcrictl start <CONTAINER_ID>
を実行すると、さきほどチェックポイントしたコンテナのコピーが実行されているはずです。
Kubernetes内でチェックポイントしたコンテナをリストアする
先ほどチェックポイントしたコンテナをKubernetes内で直接リストアするためには、レジストリにプッシュできるイメージにチェックポイントアーカイブを変換する必要があります。
ローカルのチェックポイントアーカイブを変換するための方法として、buildahを使用した下記のステップが考えられます。
newcontainer=$(buildah from scratch)
buildah add $newcontainer /var/lib/kubelet/checkpoints/checkpoint-<pod-name>_<namespace-name>-<container-name>-<timestamp>.tar /
buildah config --annotation=io.kubernetes.cri-o.annotations.checkpoint.name=<container-name> $newcontainer
buildah commit $newcontainer checkpoint-image:latest
buildah rm $newcontainer
出来上がったイメージは標準化されておらず、CRI-Oとの組み合わせでのみ動作します。
このイメージはalphaにも満たないフォーマットであると考えてください。
このようなチェックポイントイメージのフォーマットを標準化するための議論が進行中です。
これはまだ標準化されたイメージフォーマットではなく、CRI-Oを--enable-criu-support=true
で起動した場合のみ動作することを忘れないでください。
CRIUサポートでCRI-Oを起動することのセキュリティ影響はまだ明確ではなく、そのため、イメージフォーマットだけでなく機能も気を付けて使用するべきです。
さて、そのイメージをコンテナイメージレジストリにプッシュする必要があります。 例えば以下のような感じです。
buildah push localhost/checkpoint-image:latest container-image-registry.example/user/checkpoint-image:latest
このチェックポイントイメージ(container-image-registry.example/user/checkpoint-image:latest
)をリストアするために、イメージはPodの仕様(Specification)に記載する必要があります。
以下はマニフェストの例です。
apiVersion: v1
kind: Pod
metadata:
namePrefix: example-
spec:
containers:
- name: <container-name>
image: container-image-registry.example/user/checkpoint-image:latest
nodeName: <destination-node>
Kubernetesは新しいPodをノード上にスケジュールします。
そのノード上のKubeletは、registry/user/checkpoint-image:latest
として指定されたイメージをもとに、コンテナを作成し開始するようにコンテナランタイム(この例ではCRI-O)に指示をします。
CRI-Oはregistry/user/checkpoint-image:latest
がコンテナイメージでなく、チェックポイントデータへの参照であることを検知します。
その時、コンテナを作成し開始する通常のステップの代わりに、CRI-Oはチェックポイントデータをフェッチし、指定されたチェックポイントからコンテナをリストアします。
Pod内のアプリケーションはチェックポイントを取得しなかったかのように実行し続けます。 コンテナ内では、アプリケーションはチェックポイントからリストアされず通常起動したコンテナのような見た目や動作をします。
これらのステップで、あるノードで動作しているPodを、別のノードで動作している新しい同等のPodに置き換えることができ、そのPod内のコンテナの状態を失うことはないです。
どのように参加すればよいですか?
SIG Nodeにはいくつかの手段でアクセスすることができます。
さらなる読み物
コンテナチェックポイントの分析方法に関する詳細は後続のブログForensic container analysisを参照してください。
更新: dockershimの削除に関するFAQ
この記事は2020年の後半に投稿されたオリジナルの記事Dockershim Deprecation FAQの更新版です。 この記事にはv1.24のリリースに関する更新を含みます。
この文書では、Kubernetesからの dockershim の削除に関するよくある質問について説明します。 この削除はKubernetes v1.20リリースの一部としてはじめて発表されたものです。 Kubernetes v1.24のリリースにおいてdockershimは実際にKubernetesから削除されました。
これが何を意味するかについては、ブログ記事Don't Panic: Kubernetes and Dockerをご覧ください。
dockershim削除の影響範囲を確認するをお読みいただくことで、 dockershimの削除があなたやあなたの組織に与える影響をご判断いただけます。
Kubernetes 1.24リリースに至るまでの間、Kubernetesコントリビューターはこの移行を円滑に行えるようにするために尽力してきました。
- 私たちのコミットメントと次のステップを詳述したブログ記事。
- 他のコンテナランタイムへの移行に大きな障害があるかどうかのチェック。
- dockershimからの移行ガイドの追加。
- dockershimの削除とCRI互換ランタイムの使用に関する記事一覧の作成。 このリストには、上に示した文書の一部が含まれており、また、厳選された外部の情報(ベンダーによるガイドを含む)もカバーしています。
dockershimはなぜKubernetesから削除されたのですか?
Kubernetesの初期のバージョンは、特定のコンテナランタイム上でのみ動作しました。 Docker Engineです。その後、Kubernetesは他のコンテナランタイムと連携するためのサポートを追加しました。 オーケストレーター(Kubernetesなど)と多くの異なるコンテナランタイムの間の相互運用を可能にするため、 CRI標準が作成されました。 Docker Engineはそのインターフェース(CRI)を実装していないため、Kubernetesプロジェクトは移行を支援する特別なコードを作成し、 その dockershim コードをKubernetes自身の一部としました。
dockershimコードは常に一時的な解決策であることを意図されていました(このためshimと名付けられています)。 コミュニティでの議論や計画については、dockershimの削除によるKubernetes改良の提案にてお読みいただけます。
実際、dockershimのメンテナンスはKubernetesメンテナーにとって大きな負担になっていました。
さらに、dockershimとほとんど互換性のなかった機能、たとえばcgroups v2やユーザーネームスペースなどが、 これらの新しいCRIランタイムに実装されています。Kubernetesからdockershimを削除することで、これらの分野でのさらなる開発が可能になります。
Dockerとコンテナは同じものですか?
DockerはLinuxのコンテナパターンを普及させ、その基盤技術の発展に寄与してきましたが、 Linuxのコンテナ技術そのものはかなり以前から存在しています。 また、コンテナエコシステムはDockerを超えてより広範に発展してきました。 OCIやCRIのような標準は、Dockerの機能の一部を置き換えたり、既存の機能を強化したりすることで、 私達のエコシステムの多くのツールの成長と繁栄を助けてきました。
既存のコンテナイメージは引き続き使えるのですか?
はい、docker build
から生成されるイメージは、全てのCRI実装で動作します。
既存のイメージも全く同じように動作します。
プライベートイメージについてはどうでしょうか?
はい、すべてのCRIランタイムはKubernetesで使われているものと同一のpull secretsをサポートしており、 PodSpecまたはService Accountを通して利用できます。
Kubernetes 1.23でDocker Engineを引き続き使用できますか?
はい、1.20で変更されたのは、Docker Engineランタイムを使用している場合に警告ログがkubelet起動時に出るようになったことだけです。 この警告は、1.23までのすべてのバージョンで表示されます。 dockershimの削除はKubernetes 1.24で行われました。
Kubernetes v1.24以降を実行している場合は、Docker Engineを引き続きコンテナランタイムとして利用できますか?をご覧ください。 (CRIがサポートされているKubernetesリリースを使用している場合、dockershimから切り替えることができることを忘れないでください。 リリースv1.24からはKubernetesにdockershimが含まれなくなったため、必ず切り替えなければなりません)。
どのCRIの実装を使うべきでしょうか?
これは難しい質問で、様々な要素に依存します。 もしDocker Engineがうまく動いているのであれば、containerdに移行するのは比較的簡単で、 性能もオーバーヘッドも確実に改善されるでしょう。 しかし、他の選択のほうがあなたの環境により適合する場合もありますので、 CNCF landscapeにあるすべての選択肢を検討されることをおすすめします。
Docker Engineを引き続きコンテナランタイムとして利用できますか?
第一に、ご自身のPCで開発やテスト用途でDockerを使用している場合、何も変わることはありません。 Kubernetesでどのコンテナランタイムを使っていても、Dockerをローカルで使い続けることができます。 コンテナではこのような相互運用性を実現できます。
MirantisとDockerは、Kubernetesから内蔵のdockershimが削除された後も、
Docker Engineの代替アダプターを維持することにコミットしています。
代替アダプターの名前はcri-dockerd
です。
cri-dockerd
をインストールして、kubeletをDocker Engineに接続するために使用することができます。
詳細については、Migrate Docker Engine nodes from dockershim to cri-dockerdを読んでください。
今現在でプロダクション環境に他のランタイムを使用している例はあるのでしょうか?
Kubernetesプロジェクトが生み出したすべての成果物(Kubernetesバイナリ)は、リリースごとに検証されています。
また、kindプロジェクトは以前からcontainerdを使っており、プロジェクトのユースケースにおいて安定性が向上してきています。 kindとcontainerdは、Kubernetesコードベースの変更を検証するために毎日何回も利用されています。 他の関連プロジェクトも同様のパターンを追っており、他のコンテナランタイムの安定性と使いやすさが示されています。 例として、OpenShift 4.xは2019年6月以降、CRI-Oランタイムをプロダクション環境で使っています。
他の事例や参考資料はについては、 containerdとCRI-O(Cloud Native Computing Foundation (CNCF)の2つのコンテナランタイム)の採用例をご覧ください。
OCIという単語をよく見るのですが、これは何ですか?
OCIはOpen Container Initiativeの略で、コンテナツールとテクノロジー間の数多くのインターフェースの標準化を行った団体です。 彼らはコンテナイメージをパッケージするための標準仕様(OCI image-spec)と、 コンテナを実行するための標準仕様(OCI runtime-spec)をメンテナンスしています。 また、runcという形でruntime-specの実装もメンテナンスしており、 これはcontainerdとCRI-Oの両方でデフォルトの下位ランタイムとなっています。 CRIはこれらの低レベル仕様に基づいて、コンテナを管理するためのエンドツーエンドの標準を提供します。
CRI実装を変更する際に注意すべきことは何ですか?
DockerとほとんどのCRI(containerdを含む)において、下位で使用されるコンテナ化コードは同じものですが、 いくつかの細かい違いが存在します。移行する際に考慮すべき一般的な事項は次のとおりです。
- ログ設定
- ランタイムリソースの制限
- ノード構成スクリプトでdockerコマンドやコントロールソケット経由でDocker Engineを使用しているもの
kubectl
のプラグインでdocker
CLIまたはDocker Engineコントロールソケットが必要なもの- KubernetesプロジェクトのツールでDocker Engineへの直接アクセスが必要なもの(例:廃止された
kube-imagepuller
ツール) registry-mirrors
やinsecureレジストリなどの機能の設定- その他の支援スクリプトやデーモンでDocker Engineが利用可能であることを想定していてKubernetes外で実行されるもの(モニタリング・セキュリティエージェントなど)
- GPUまたは特別なハードウェア、そしてランタイムおよびKubernetesとそれらハードウェアの統合方法
あなたがKubernetesのリソース要求/制限やファイルベースのログ収集DaemonSetを使用しているのであれば、それらは問題なく動作し続けますが、
dockerd
の設定をカスタマイズしていた場合は、それを新しいコンテナランタイムに適合させる必要があるでしょう。
他に注意することとしては、システムメンテナンスを実行するようなものや、コンテナ内でイメージをビルドするようなものが動作しなくなります。
前者の場合は、crictl
ツールをdrop-inの置き換えとして使用できます(docker cliからcrictlへのマッピングを参照)。
後者の場合は、img、buildah、kaniko、buildkit-cli-for-kubectlのようなDockerを必要としない新しいコンテナビルドの選択肢を使用できます。
containerdを使っているのであれば、ドキュメントを参照して、移行するのにどのような構成が利用可能かを確認するところから始めるといいでしょう。
containerdとCRI-OをKubernetesで使用する方法に関しては、コンテナランタイムに関するKubernetesのドキュメントを参照してください。
さらに質問がある場合どうすればいいでしょうか?
ベンダーサポートのKubernetesディストリビューションを使用している場合、彼らの製品に対するアップグレード計画について尋ねることができます。 エンドユーザーの質問に関しては、エンドユーザーコミュニティフォーラムに投稿してください。
dockershimの削除に関する決定については、専用のGitHub issueで議論することができます。
変更点に関するより詳細な技術的な議論は、待ってください、DockerはKubernetesで非推奨になったのですか?という素晴らしいブログ記事も参照してください。
dockershimを使っているかどうかを検出できるツールはありますか?
はい!Detector for Docker Socket (DDS)というkubectlプラグインをインストールすることであなたのクラスターを確認していただけます。
DDSは、アクティブなKubernetesワークロードがDocker Engineソケット(docker.sock
)をボリュームとしてマウントしているかを検出できます。
さらなる詳細と使用パターンについては、DDSプロジェクトのREADMEを参照してください。
ハグしていただけますか?
はい、私達は引き続きいつでもハグに応じています。🤗🤗🤗
Don't Panic: Kubernetes and Docker
著者: Jorge Castro, Duffie Cooley, Kat Cosgrove, Justin Garrison, Noah Kantrowitz, Bob Killen, Rey Lejano, Dan “POP” Papandrea, Jeffrey Sica, Davanum “Dims” Srinivas
Kubernetesはv1.20より新しいバージョンで、コンテナランタイムとしてDockerをサポートしません。
パニックを起こす必要はありません。これはそれほど抜本的なものではないのです。
概要: ランタイムとしてのDockerは、Kubernetesのために開発されたContainer Runtime Interface(CRI)を利用しているランタイムを選んだ結果としてサポートされなくなります。しかし、Dockerによって生成されたイメージはこれからも、今までもそうだったように、みなさんのクラスターで使用可能です。
もし、あなたがKubernetesのエンドユーザーであるならば、多くの変化はないでしょう。これはDockerの死を意味するものではありませんし、開発ツールとして今後Dockerを使用するべきでない、使用することは出来ないと言っているのでもありません。Dockerはコンテナを作成するのに便利なツールですし、docker buildコマンドで作成されたイメージはKubernetesクラスター上でこれからも動作可能なのです。
もし、GKE、EKS、AKSといったマネージドKubernetesサービス(それらはデフォルトでcontainerdを使用しています)を使っているのなら、ワーカーノードがサポート対象のランタイムを使用しているか、Dockerのサポートが将来のK8sバージョンで切れる前に確認しておく必要があるでしょう。 もし、ノードをカスタマイズしているのなら、環境やRuntimeの仕様に合わせて更新する必要があるでしょう。サービスプロバイダーと確認し、アップグレードのための適切なテストと計画を立ててください。
もし、ご自身でClusterを管理しているのなら、やはり問題が発生する前に必要な対応を行う必要があります。v1.20の時点で、Dockerの使用についての警告メッセージが表示されるようになります。将来のKubernetesリリース(現在の計画では2021年下旬のv1.22)でDockerのRuntimeとしての使用がサポートされなくなれば、containerdやCRI-Oといった他のサポート対象のRuntimeに切り替える必要があります。切り替える際、そのRuntimeが現在使用しているDocker Daemonの設定をサポートすることを確認してください。(Loggingなど)
では、なぜ混乱が生じ、誰もが恐怖に駆られているのか。
ここで議論になっているのは2つの異なる場面についてであり、それが混乱の原因になっています。Kubernetesクラスターの内部では、Container runtimeと呼ばれるものがあり、それはImageをPullし起動する役目を持っています。Dockerはその選択肢として人気があります(他にはcontainerdやCRI-Oが挙げられます)が、しかしDockerはそれ自体がKubernetesの一部として設計されているわけではありません。これが問題の原因となっています。
お分かりかと思いますが、ここで”Docker”と呼んでいるものは、ある1つのものではなく、その技術的な体系の全体であり、その一部には"containerd"と呼ばれるものもあり、これはそれ自体がハイレベルなContainer runtimeとなっています。Dockerは素晴らしいもので、便利です。なぜなら、多くのUXの改善がされており、それは人間が開発を行うための操作を簡単にしているのです。しかし、それらはKubernetesに必要なものではありません。Kubernetesは人間ではないからです。 このhuman-friendlyな抽象化レイヤーが作られたために、結果としてはKubernetesクラスターはDockershimと呼ばれるほかのツールを使い、本当に必要な機能つまりcontainerdを利用してきました。これは素晴らしいとは言えません。なぜなら、我々がメンテする必要のあるものが増えますし、それは問題が発生する要因ともなります。今回の変更で実際に行われることというのは、Dockershimを最も早い場合でv1.23のリリースでkubeletから除外することです。その結果として、Dockerのサポートがなくなるということなのです。 ここで、containerdがDockerに含まれているなら、なぜDockershimが必要なのかと疑問に思われる方もいるでしょう。
DockerはCRI(Container Runtime Interface)に準拠していません。もしそうであればshimは必要ないのですが、現実はそうでありません。 しかし、これは世界の終わりでありません、心配しないでください。みなさんはContainer runtimeをDockerから他のサポート対象であるContainer runtimeに切り替えるだけでよいのです。
1つ注意すべきことは、クラスターで行われる処理のなかでDocker socket(/var/run/docker.sock
)に依存する部分がある場合、他のRuntimeへ切り替えるとこの部分が働かなくなるでしょう。このパターンはしばしばDocker in Dockerと呼ばれます。このような場合の対応方法はたくさんあります。kaniko、img、buildahなどです。
では開発者にとって、この変更は何を意味するのか。これからもDockerfileを使ってよいのか。これからもDockerでビルドを行ってよいのか。
この変更は、Dockerを直接操作している多くのみなさんとは別の場面に影響を与えるでしょう。 みなさんが開発を行う際に使用しているDockerと、Kubernetesクラスターの内部で使われているDocker runtimeは関係ありません。これがわかりにくいことは理解しています。開発者にとって、Dockerはこれからも便利なものであり、このアナウンスがあった前と変わらないでしょう。DockerでビルドされたImageは、決してDockerでだけ動作するというわけではありません。それはOCI(Open Container Initiative) Imageと呼ばれるものです。あらゆるOCI準拠のImageは、それを何のツールでビルドしたかによらず、Kubernetesから見れば同じものなのです。containerdもCRI-Oも、そのようなImageをPullし、起動することが出来ます。 これがコンテナの仕様について、共通の仕様を策定している理由なのです。
さて、この変更は決定しています。いくつかの問題は発生するかもしてませんが、決して壊滅的なものではなく、ほとんどの場合は良い変化となるでしょう。Kubernetesをどのように使用しているかによりますが、この変更が特に何の影響も及ぼさない人もいるでしょうし、影響がとても少ない場合もあります。長期的に見れば、物事を簡単にするのに役立つものです。 もし、この問題がまだわかりにくいとしても、心配しないでください。Kubernetesでは多くのものが変化しており、その全てに完璧に精通している人など存在しません。 経験の多寡や難易度にかかわらず、どんなことでも質問してください。我々の目標は、全ての人が将来の変化について、可能な限りの知識と理解を得られることです。 このブログが多くの質問の答えとなり、不安を和らげることができればと願っています。
別の情報をお探しであれば、dockershimの削除に関するFAQを参照してください。