Kubernetesにおけるアドミッションコントローラーによるコンテナドリフトの検出
Boxのエンジニアは、ランタイム時のコンテナ変更を検出し、Podの退避ポリシーを強制するために、カスタムのアドミッションコントローラーとkubectlプラグインを開発しました。
英語の原文から自動翻訳されました。
2021年12月のKubernetes Blogの投稿で、Boxのエンジニアたちは、インタラクティブなコマンドによって引き起こされるコンテナドリフトを検出し管理するために構築したシステムについて説明しました。チームは、kubectl execやattachを通じて変更されたPodを識別し、自動退避ポリシーを適用するためのカスタムアドミッションコントローラーと対応するkubectlプラグインを開発しました。
何が起きたか
Boxは、ペタバイト規模のデータストリーミングを処理するために、数百のマイクロサービスをKubernetes上で実行しています。彼らのデプロイワークフローはGitOpsに依存しており、コードレビューと自動チェックを経て、Gitリポジトリから宣言的な設定を適用するためにkube-applierを使用しています。このプロセスにより、本番環境への変更すべてが追跡され、レビューされ、コードで定義された望ましい状態と一致することが保証されます。
しかし、開発者はkubectl execなどのインタラクティブなコマンドを使用して、実行中のコンテナを直接変更することで、これらの制御を回避できます。こうしたアドホックな変更は「コンテナドリフト」を生み出し、コンテナのライブ状態が宣言された設定から逸脱します。このような変更は変更管理プロセスを無効にし、影響を受けたコンテナが監視なしに本番環境でトラフィックを提供し続けることを許してしまいます。
このセキュリティおよび運用上のギャップに対処するため、BoxはカスタムKubernetesコンポーネントであるkube-exec-controllerと、kubectl piという名前のkubectlプラグインを作成しました。このシステムは、開発者が実行中のコンテナとやり取りしているタイミングを検出し、影響を受けるPodにラベルを付け、最終的にそれらを退避させて宣言された状態を復元します。このプロジェクトは、他のチームがクラスター内の同様のリスクを管理できるよう支援するためにオープンソース化されました。
仕組み
このソリューションは、オブジェクトが永続化される前にAPIサーバーへのリクエストをインターセプトするKubernetesアドミッションコントローラーを活用しています。具体的には、チームはpods/execおよびpods/attachリソースに対するCONNECT操作を監視するように設定されたValidatingAdmissionWebhookを使用しました。開発者がインタラクティブなコマンドを実行すると、Webhookは検証のためにリクエストをkube-exec-controllerサービスに送信します。

即時の拒否はデバッグを妨げるため、コントローラーは初期リクエストをブロックしません。代わりに、接続を許可し、非同期で対象のPodにインタラクターのユーザー名やタイムスタンプなどのメタデータをラベルとして付与します。また、Podに警告イベントをログ出力します。コントローラー内の別のプロセスが、各ラベル付きPodに対して有効期限(TTL)タイマーを追跡します。TTLが切れると、コントローラーはPodを退避させます。削除よりも退避が優先されるのは、PodDisruptionBudgetsを尊重し、クリーンアッププロセス中にサービスの可用性が維持されるようにするためです。
可視性と使いやすさを向上させるために、Boxはkubectl piプラグインを開発しました。Kubernetesイベントはデフォルトでは1時間しか保持されないため、このプラグインはコントローラーによって付与されたラベルとアノテーションを読み取り、Podとのインタラクションに関する人間が読める情報を提供します。インタラクションの詳細を表示するためのgetサブコマンドと、extendサブコマンドが含まれています。extendコマンドにより、開発者はPodのアノテーションを更新して退避前に時間を延長することをリクエストでき、別のバリデーションWebhookを経た後に退避タイマーがリセットされます。
主要な詳細
- システムは
ValidatingAdmissionWebhookを使用して、pods/execおよびpods/attachのCONNECTリクエストをインターセプトします。 - 影響を受けるPodには、インタラクターのユーザー名と最初のインタラクションのタイムスタンプを含むメタデータがラベルとして付与されます。
- Podは事前に定義されたTTLの後に退避されますが、これは環境によって異なります(開発環境では長く、本番環境では短く設定されます)。
- 退避はPodDisruptionBudgetsを尊重し、強制再起動中のサービス停止を防ぎます。
kubectl piプラグインは、ステータスの確認とTTL延長のリクエストを行うためのgetおよびextendサブコマンドを提供します。kube-exec-controllerという名前のこのプロジェクトは、BoxによってGitHubでオープンソース化されました。
なぜ重要なのか
Kubernetes上でソフトウェアを構築するチームにとって、デプロイされた状態の整合性を維持することは、セキュリティと信頼性にとって極めて重要です。コンテナへのインタラクティブアクセスはデバッグにおいて一般的な必要性ですが、追跡されていない変更を導入し、設定ドリフトにつながる可能性があります。これらの変更を検出して元に戻す仕組みがなければ、クラスターは一貫性の欠如を蓄積し、トラブルシューティングを困難にするだけでなく、セキュリティリスクを増大させます。
このアプローチは、アドミッションコントローラーがポリシー執行だけでなく、運用衛生のためにも使用できることを示しています。ドリフトの検出と修復を自動化することで、チームは必要なデバッグアクセスを許可しつつ、本番システムが最終的に宣言され、レビューされた状態に戻ることを保証できます。これは開発者の柔軟性とプラットフォームガバナンスのバランスを取ります。
即時終了ではなく退避を使用することは、本番環境の制約に対する成熟した理解を示しています。PodDisruptionBudgetsを尊重することで、セキュリティ対策が意図せずダウンタイムを引き起こさないことが保証されます。このパターンは、厳格な変更管理とアクティブな開発・サポートワークフローの両方が必要とされるKubernetesを使用するあらゆる組織に適用可能です。
あなたができること
- 現在のKubernetesセキュリティポリシーを評価し、
kubectl execなどのインタラクティブコマンドが無制限かどうかを確認してください。 pods/execおよびpods/attachリクエストを監視しログ記録するためのバリデーションアドミッションWebhookの実装を検討してください。- 環境に基づいてドリフトしたPodの明確なTTLポリシーを定義し、本番クラスターにはより厳しい制限を設定してください。
- ドリフトしたコンテナのクリーンアップ時には、中断予算を尊重するために削除ではなくPod退避を使用してください。
- Podインタラクション履歴と退避タイマーへの可視性を開発者に提供するために、kubectlプラグインを開発または採用してください。
- GitHub上のオープンソースプロジェクト
kube-exec-controllerを確認し、実装の詳細を理解してニーズに合わせて適応させてください。


