本番環境のジレンマ:なぜ「クリーン」なデプロイも時間とともに劣化するのか
パイプラインが通り、GitHub Actionsに緑色のチェックマークが点灯し、コンテナイメージがそのまま本番環境へと出荷されます。月曜日の朝には完全にセキュアに見えていたクラスタも、木曜日には状況が一変することがあります。
脆弱性の公開はスプリントサイクルを待ってはくれません。実際のケースを考えてみましょう。月の半ばにOpenSSLやglibcのリモートコード実行の脆弱性がNVDデータベースに登録されたとします。決済サービスを支えるイメージは3週間前のビルド時にスキャン済みです。それ以降どの開発者もリポジトリを変更していないため、CIのアラートを一切発生させることなく、本番環境で脆弱なバイナリを実行するPodが稼働し続けることになります。
ランタイム時のドリフト(構成の乖離)がこの問題をさらに悪化させます。本番障害時にエンジニアがマニフェストに緊急修正を加えたり、コンテナをroot権限で実行したり、メモリ制限の設定を省略したりすることがあります。静的なパイプラインチェックでは、このような実行時の調整を検知することができません。
根本原因の分析:CI/CDにおける4つのセキュリティ盲点
ビルド時のスキャンのみに依存していると、運用上4つの大きな盲点が生じます。
- 脆弱性情報のタイムラグ: CVEデータベースには毎日数十件の更新情報が公開されます。午前9時の時点では安全と認定されたコンテナイメージであっても、クラスタ内でそのまま稼働し続けるうちに、午後5時には重大な欠陥を抱える可能性があります。
- クラスタ構成のドリフト: ステージング環境や本番環境において、エンジニアが
kubectl editコマンドで直接パッチを適用することがよくあります。こうした手動の変更はプルリクエストのチェックをバイパスし、安全でないセキュリティコンテキストを持ち込む原因となります。 - サードパーティ製Helmチャート: 本番クラスタは、cert-manager、NGINX Ingress、Prometheusエクスポーターなどのオープンソースアドオンに依存しています。これらのサードパーティ製イメージは、社内のビルドパイプラインを完全に迂回してデプロイされます。
- 静的なCIS監査の限界: ワーカーノード、APIサーバーの起動フラグ、kubeletの設定をCIS Kubernetes Benchmarkに準拠して監査するには、継続的なランタイムチェックが不可欠です。四半期に一度スプレッドシートで手動レビューを行うだけでは、リリース間の構成ドリフトを捉えきれません。
Kubernetesセキュリティスキャン手法の比較検討
プラットフォームチームは通常、以下の3つのランタイムスキャンアーキテクチャから選択します。
| アプローチ | メリット | デメリット | リソースオーバーヘッド |
|---|---|---|---|
| 1. スケジュール実行のCLI CronJob(Trivyやkube-benchのスクリプト) | ソフトウェアのライセンス費用がゼロ、シンプルなシェルスクリプトで運用可能 | メンテナンスが壊れやすい、ログが生テキスト出力のみ、KubernetesネイティブなCRD連携が皆無 | 運用負荷が高い |
| 2. エンタープライズ向けSaaSエージェント(Prisma Cloud、Sysdig Secureなど) | 包括的なWebダッシュボード、eBPFを活用したランタイムのカーネルテレメトリ | 高額なシート単価、複雑なマルチテナント設定、独自ベンダーへのロックイン | ノードあたり100〜300MBのRAM |
| 3. KubernetesネイティブOperator(Aqua Trivy Operator) | オープンソース、監査データをカスタムリソース(CRD)に直接保存、ネイティブなGitOps連携が可能 | スキャンジョブ用にクラスタ内のCPU/メモリバジェットを確保する必要がある | コントローラーのアイドル時RAMは50MB未満 |
ステップ別実装ガイド:Trivy Operatorのデプロイ
Trivy Operatorはセキュリティ監査をKubernetesネイティブなカスタムリソースへと変換します。新しいPod、Job、またはDaemonSetが起動すると、Operatorコントローラーが短時間動作するスキャンジョブを生成します。対象のワークロードを検査し、構造化された検出結果をVulnerabilityReportなどのカスタムリソースに書き込み、スキャナーPodを自動的にクリーンアップします。
ステップ1:Helmを使用したTrivy Operatorのインストール
公式のAqua Securityチャートリポジトリを追加し、専用の名前空間を作成します。
# Aqua SecurityのHelmリポジトリを追加
helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm repo update
# 専用の名前空間を作成
kubectl create namespace trivy-system
本番環境向けに同時実行数の制限と定期的なCIS監査スケジュールを設定してチャートをデプロイします。
helm install trivy-operator aqua/trivy-operator \
--namespace trivy-system \
--set trivy.ignoreUnfixed=true \
--set operator.scanJobsConcurrentLimit=3 \
--set compliance.cron="0 2 * * *"
OperatorのPodが正常に稼働していることを確認します。
kubectl get pods -n trivy-system
ステップ2:生成されたセキュリティCRDの確認
Trivy Operatorは標準的なKubernetesオブジェクトに沿ったカスタムリソース定義(CRD)を登録します。登録された定義を確認してみましょう。
kubectl get crds | grep aquasecurity
主要なカスタムリソースには以下のようなものがあります。
vulnerabilityreports.aquasecurity.github.io:稼働中のコンテナイメージに含まれるパッケージのCVEを追跡します。configauditreports.aquasecurity.github.io:root実行や読み取り専用ルートファイルシステムの設定漏れなど、Podの設定ミスを検知します。clustercompliancereports.aquasecurity.github.io:クラスタ全体の設定をCIS BenchmarkやNSA/CISAのガイドラインと照合・マッピングします。exposedsecretreports.aquasecurity.github.io:コンテナのファイルシステムレイヤーをスキャンし、漏洩したAPIキー、トークン、証明書を検出します。
ステップ3:テスト用ワークロードのデプロイ
自動検出とスキャンをトリガーするために、古いバージョンのNGINXインスタンスをデプロイします。
kubectl create namespace demo-apps
kubectl create deployment vulnerable-web --image=nginx:1.18 --namespace demo-apps
Operatorコントローラーは新しいReplicaSetを即座に検知します。trivy-system名前空間に一時的なスキャン用Podを起動して脆弱性データベースに問い合わせ、30〜60秒以内にレポートを生成します。
ステップ4:kubectlによるレポートのクエリ
脆弱性を確認するために外部のダッシュボードを用意する必要はありません。クラスタに対して直接クエリを実行できます。
kubectl get vulnerabilityreports -n demo-apps
CLI上に重要度レベル別の分かりやすい表形式サマリーが表示されます。
NAME REPOSITORY TAG CRITICAL HIGH MEDIUM LOW AGE
deployment-vulnerable-web-vulnerable-web-nginx library/nginx 1.18 12 48 65 82 2m
特定のCVE識別子、影響を受けるパッケージ、修正バージョンを抽出するには、jsonpathを使用します。
kubectl get vulnerabilityreport deployment-vulnerable-web-vulnerable-web-nginx -n demo-apps -o jsonpath='{range .report.vulnerabilities[*]}{.vulnerabilityID}{"\t"}{.severity}{"\t"}{.resource}{"\t"}{.fixedVersion}{"\n"}{end}'
次にPodの設定監査レポートを確認し、デプロイにおけるアンチパターンを特定します。
kubectl get configauditreports -n demo-apps -o wide
出力結果には、メモリ要求(request)の未設定、CPU制限(limit)の未設定、安全でないLinuxケーパビリティなど、マニフェストの設定不備がハイライトされます。
ステップ5:CIS Kubernetes Benchmarkの自動監査実行
Trivy Operatorは、ステップ1で設定したスケジュールに基づいて、マスターノードおよびワーカーノードのセキュリティパラメータを自動的に監査します。
クラスタ全体のアクティブなコンプライアンスレポート一覧を取得します。
kubectl get clustercompliancereports
不合格となった特定のコンプライアンス項目と必要な是正手順を確認します。
kubectl get clustercompliancereport cis-k8s -o yaml
レポートには、APIサーバーの設定、etcdの暗号化、kubeletの認可などをカバーする合否判定マトリクスと、不合格となった各チェック項目に対する具体的な是正手順が提示されます。
ステップ6:本番環境向けの強化と運用のベストプラクティス
- 同時スキャン数のスロットリング: 数百ものマイクロサービスが動作する大規模クラスタでは、複数のスキャンジョブがワーカーノードを圧迫する可能性があります。CPUスロットリングを防止するため、
operator.scanJobsConcurrentLimitは2〜5の間に設定しておくことを推奨します。 - 対応不可能なアラートのフィルタリング:
trivy.ignoreUnfixed=trueを有効にします。これによりベンダーからの修正パッチが未提供の脆弱性が除外され、エンジニアはすぐに対応可能な是正措置に集中できます。 - Prometheusへのメトリクス送信: Trivy Operatorは
:8080/metricsでtrivy_image_vulnerabilitiesやtrivy_configaudit_checksなどのメトリクスを提供します。これらをスクレイピングすることで、CriticalレベルのCVE数が社内SLAを超過した際にPagerDutyのアラートを自動発報できます。

