Skip to main content

GitLab Auto DevOpsの『とりあえず動くCI』が、本番K3sクラスタへの一番近い脅威になる理由

GitLab Auto DevOpsの「何もしなくても動く」という罠

section01

GitLab Auto DevOps を有効化した瞬間から、SAST(静的解析)やDASTといったセキュリティスキャンは自動的に動き出す。マージリクエストの画面には脆弱性のバッジが並び、チームは「うちはもうDevSecOpsができている」と安心する。だが、ここに典型的な落とし穴がある。

たとえば、あるチームがAuto DevOpsを有効化し、SASTスキャンでCritical判定の脆弱性が検出されたとする。ジョブ自体は正常終了し、パイプラインはグリーンのまま進み続ける。担当者はマージリクエストの警告バッジに気づかないまま、あるいはリリース期限を優先してそのままマージする。結果として、脆弱性を含んだコンテナイメージがビルドされ、レジストリにpushされ、何の障害もなく本番のK3sクラスタにデプロイされる。

GitLab公式のSASTドキュメントでも、SASTは「開発の早い段階、修正コストが最も低いタイミングで脆弱性を検出する」ことを目的としたツールだと説明されている。つまりSASTの役割はあくまで検知であり、検知した結果をパイプラインの合否条件に組み込んで強制するかどうかは、利用者側の設計に委ねられている。

さらに厄介なのは、Auto DevOpsが2026年時点で以前ほど「全部お任せ」の製品ではなくなっている点だ。GitLabはAuto DevOpsが提供していたin-cluster PrometheusやWAFといったマネージドアプリケーションの一部を廃止し、運用者が自身でingressやPrometheus、Cilium等を持ち込む方向にシフトしている。「有効化するだけで安全なパイプラインが完成する」という前提そのものが、もはや成立しない。

「CI通過」と「デプロイしていい」はイコールではない

section02

なぜこの落とし穴が起きるのか。根本原因は、CI/CDパイプラインのセキュリティ境界とKubernetesクラスタのセキュリティ境界がまったく別物であるという事実が見落とされているからだ。

コンテナイメージの脆弱性リスクは、決して一部の有名イメージだけの問題ではない。Chainguardの調査「The State of Trusted Open Source Report」によれば、検出されたCVEインスタンスの96.2%は、利用頻度の高い上位20イメージ以外から発生している。つまり、自社が組み合わせて使っている依存パッケージのどこかに、常に未知のリスクが潜んでいると考えるべきだ。

Wizのセキュリティ解説記事でも指摘されている通り、CI/CDのスキャン結果は量が多すぎて、優先順位付けなしにはそのまま実質的なリスク低減につながらない。フィーチャーブランチでは高速な非ブロッキングチェックにとどめ、本番デプロイに向かうパイプラインではCritical・High判定の検出結果を厳格にゲートするという段階的な設計が推奨されている。だが、Auto DevOpsのデフォルト構成だけでは、この「本番向けの厳格なゲート」は自動的には作られない。CI側の検知と、Kubernetesクラスタ側の実行制御は、意識的に接続しない限り繋がらないのだ。

この「CI/CDとクラスタの間の断絶」をどう埋めるかは、マネージドKubernetesを選ぶ際の隠れた判断基準でもある。クラスタ側が独自拡張だらけのブラックボックスだと、標準的なゲート機構を後から組み込むこと自体が難しくなる。KuboのようにPure Kubernetesを維持したマネージドK3s環境であれば、この後説明するCNCFエコシステムのポリシーエンジンをそのまま利用できる。

パイプラインとクラスタの間に「関所」を作る — Admission Controllerによるゲート設計

section03

この断絶を埋める仕組みが、Kubernetes標準のAdmission Controllerだ。Kubernetes公式ドキュメントによると、Admission Controllerは「APIサーバーがリソースをデータベースに永続化する前に、認証・認可後のリクエストをインターセプトして検証・変更するコンポーネント」と定義されている。つまり、CIパイプラインがどれだけ緩くても、クラスタのAPIサーバーに届いた時点で最後のチェックをかけられるという点が重要だ。

具体的にAdmission Controllerで何ができるのか。Wizの解説によれば、承認済みのレジストリ以外からのイメージpullを制限したり、root権限で動作するPodを拒否したり、ホストポートを公開するPodを拒否するといったポリシーを、クラスタ全体に一貫して強制できる。CIのスキャンが「検知」担当、Admission Controllerが「強制」担当という役割分担を持たせることで、初めて「検知したのに実害を防げなかった」というギャップが埋まる。

Kubo Cloudはベンダー独自の管理レイヤーでAPIサーバーを覆い隠さないPure Kubernetes構成のため、この後紹介するKyvernoやOPA Gatekeeperのような標準的なポリシーエンジンを、追加のライセンス制約なくそのままインストールして運用できる。GitOps対応も標準搭載しているため、ポリシー定義自体もArgoCD/Fluxの管理下に置きやすい。

検知から強制へ — 3つの実装パターン

section04

Admission Controllerの選択肢はいくつかあるが、いずれを選ぶにしても押さえるべき実装パターンは3つある。まず着手すべきは、優先度が最も高いブロッキングゲートだ。

1. イメージ検証をブロッキングゲート化する(最優先)

CNCFのGraduatedプロジェクトであるKyvernoは、署名済み・アテステーション付きのイメージだけをクラスタが受け入れるよう検証する機能を持つ。同様にOPA GatekeeperのConstraintTemplateを使えば、Rego/CELで書いたポリシーロジックをクラスタ全体のConstraintとして再利用可能な形で強制できる。まずはこのレイヤーで「未署名・未スキャンのイメージは拒否」というルールを1本通すことが、投資対効果の最も高い一手になる。

2. CIサービスアカウントのRBACを最小化する

CIパイプライン自体がクラスタに直接デプロイする構成では、そのサービスアカウントの権限が広すぎるケースが多い。Kubernetes公式のRBACグッドプラクティスでは、ClusterRoleBindingではなく名前空間スコープのRoleBindingを優先し、ワイルドカード権限を避けることが推奨されている。CIのサービスアカウントが乗っ取られた場合の被害範囲を、あらかじめ名前空間単位に限定しておく設計が欠かせない。

3. Secretsを平文のConfigMapに置かない

CI/CD変数として渡すAPIキーやDB接続情報は、ConfigMapではなくKubernetes SecretsまたはVaultなどの外部シークレットマネージャで管理する。これは地味だが、Admission Controllerのポリシーで「Secrets以外への機密情報の書き込みを拒否する」ルールと組み合わせることで、検知と強制の両輪が揃う。

まとめ

GitLab Auto DevOpsの「有効化するだけで動く」という手軽さ自体は否定すべきものではない。問題は、その手軽さを「クラスタまで安全である」という誤った安心感にすり替えてしまうことだ。CI側の検知(SAST/DAST)と、クラスタ側の強制(Admission Controller)を明確に役割分担させ、両者の間に「関所」を設計することで、初めてDevSecOpsパイプラインは実効性を持つ。

まずはKyvernoかOPA Gatekeeperのどちらかで、未署名イメージを拒否するポリシーを1本本番クラスタに適用するところから始めてほしい。そのうえでRBACの最小化、Secrets管理の見直しへと段階的に広げていけば、CI/CDとクラスタの間の断絶は着実に埋まっていく。

こうした標準的なポリシーエンジンをロックインなく運用できる基盤を探しているなら、KuboはK3sベースのPure Kubernetesとして、EKS/AKS比で4割以上安いコストで同じ設計をそのまま実践できる。GitOpsやHelmも標準対応しているため、ポリシー適用の自動化もスムーズに始められる。まずは料金プランでコスト構造を確認するか、お問い合わせから相談してみてほしい。

Related articles

← Back to all posts