大規模環境におけるKubernetesコンプライアンス:OPA Gatekeeperを使いこなす

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

制限のないKubernetesクラスターがもたらす混乱

最初のKubernetesクラスターをサイドプロジェクト用にセットアップするのは簡単です。チームを信頼し、全員がデプロイに関する「暗黙のルール」に従っているからです。しかし、それが50のネームスペースと200のマイクロサービスにスケールすると、事態はすぐに混乱します。リソース制限のないたった1つの制御不能なポッドが、ノード上の他のすべてのサービスに対して60%ものパフォーマンス低下を引き起こしたケースを私は見てきました。ある事例では、開発者が誤ってコンテナをroot権限で実行してしまい、潜在的なエクスプロイトに対して門戸を広げてしまったこともあります。

この規模で手動のコードレビューに頼ることは, 燃え尽き症候群を招く原因となります。セキュリティコンプライアンスやコスト管理用のラベルを確認するために、すべてのYAMLファイルを現実的に検査することは不可能です。このような「無法地帯」のような環境は、設定のドリフトやセキュリティホールを招きます。さらに悪いことに、たった一度の週末で2,500ドルの予期せぬクラウド利用料が発生することさえあります。不適切な設定がクラスターに到達する前に、自動的に「No」と言う方法がないため、インフラストラクチャは脆弱なままなのです。

ギャップ:なぜRBACだけでは不十分なのか

エンジニアは、ロールベースアクセス制御 (RBAC) がセキュリティの特効薬であると考えがちです。RBACは不可欠ですが、それは**アイデンティティ(身元)**のみを扱います。つまり、「誰が何をできるか」という問いに答えるものです。例えば、RBACは開発者が「staging」ネームスペースでDeploymentを作成することを許可します。しかし、そのDeploymentの**内容(コンテンツ)**まではチェックしません。

標準的なRBACでは、プライベートデータベースをパブリックインターネットに公開するLoadBalancerの作成を止めることはできません。また、未承認の脆弱なコンテナレジストリの使用を防ぐこともできません。Kubernetesには、リソースのボディ内の特定の属性を検証するネイティブできめ細かな方法が不足しています。Policy as Code (PaC) はこの空白を埋めます。組織の基準を満たさないリクエストを拒否する、デジタルの建築検査官のようなシステムが必要なのです。

解決策:Open Policy Agent (OPA) と Gatekeeper

そこで登場するのが、**Rego**と呼ばれる宣言型言語を使用する汎用ポリシーエンジン、Open Policy Agent (OPA) です。OPAはCI/CDパイプラインからSSH認証まであらゆるものを処理しますが、**Gatekeeper**はKubernetesネイティブ版です。これはKubernetesのAdmission Controllerに直接プラグインされ、リアルタイムでルールを適用します。

APIサーバーの前に門番(ゲートキーパー)が立っているところを想像してください。`kubectl apply -f pod.yaml` を実行すると、Gatekeeperがリクエストを遮断します。そして、あなたのYAMLを定義済みのポリシーと比較します。もしポッドがルールに違反していれば、Gatekeeperは明確なエラーメッセージとともに即座にリクエストを却下します。これはコンテナが1つも起動する前に行われるため、クラスターを常に検証済みの「良好な」状態に保つことができます。

Gatekeeperの主要コンポーネント

  • ConstraintTemplates: Regoを使用してポリシーのロジックを定義します。これは「設計図」または関数定義のようなものだと考えてください。
  • Constraints: テンプレートのインスタンスです。特定のネームスペースなど、ポリシーを適用する場所と、チェックする値を定義します。これは「実装」のようなものです。

チュートリアル:最初のポリシーを動かしてみる

私はこのセットアップを高トラフィックの本番環境に導入してきましたが、安定性の向上はすぐに現れます。以下の手順に従ってGatekeeperをインストールし、すべてのネームスペースに特定のラベルを付けることを義務付けるポリシーを適用してみましょう。

1. Gatekeeperのインストール

Helmを使用するのが最も早い方法です。以下のコマンドを実行してコントローラーを起動します:

helm repo add gatekeeper https://open-policy-agent.github.io/gatekeeper/charts
helm install gatekeeper gatekeeper/gatekeeper --namespace gatekeeper-system --create-namespace

次に進む前に、`gatekeeper-system` ネームスペース内のポッドが正常であることを確認してください。

2. ConstraintTemplate of the 作成

ラベルをチェックするテンプレートが必要です。このRegoロジックは、入力されたオブジェクトのラベルを、パラメータで指定された必須ラベルのリストと比較します。

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels

        violation[{"msg": msg}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("必須ラベルが不足しています: %v", [missing])
        }

テンプレートを適用します:`kubectl apply -f template.yaml`。

3. Constraint(制約)の定義

それでは、すべての**Namespace**に `cost-center` ラベルを付けることを義務付けてみましょう。これにより、後で開発者を追いかけ回すことなく、部門ごとのクラウド支出を追跡できるようになります。

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-cost-center
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Namespace"]
  parameters:
    labels: ["cost-center"]

この制約を適用します。これでGatekeeperがクラスターを保護するようになりました。

4. 強制適用のテスト

ラベルを付けずにネームスペースを作成してみみます:

kubectl create namespace test-violation

APIサーバーはエラーでブロックします:

サーバーからのエラー (Forbidden): アドミッションウェブフック "validation.gatekeeper.sh" がリクエストを拒否しました:
[ns-must-have-cost-center] 必須ラベルが不足しています: {"cost-center"}

次に、ラベルを追加して再試行してください。リクエストが通るはずです。この自動化されたループにより、手動の介入なしでコンプライアンスが確保されます。

本番環境での戦略的導入

本番環境ですぐにリクエストのブロックを開始しないでください。CI/CDパイプラインや自動スケーリングイベントを壊してしまう可能性があります。代わりに、段階的な展開を行ってください。

Gatekeeperには `enforcementAction: dryrun` フィールドがあります。これにより、実際に停止させることなく、ログでどのリソースがブロックされていたはずかを確認できます。まずクラスターを監査してください。準拠していないリソースをクリーンアップします。そして、確信が持てたら `enforce` モードに切り替えます。

一般的な本番環境でのユースケースは以下の通りです:

  • レジストリのホワイトリスト化: `company.azurecr.io` からのイメージのみを許可します。
  • リソース制限の義務化: CPU/メモリの要求(requests)が欠落しているポッドをブロックします。
  • Ingressの衝突防止: 2つのチームが誤って同じホスト名を占有するのを防ぎます。

自動化された安全性への移行

Policy as Codeは、セキュリティをスプリントの最後に行うチェック項目から、リアルタイムのガードレールへと変貌させます。OPA Gatekeeperを使用することで、開発者は安全な境界線内で迅速に動くことができるようになります。コンプライアンスの負担を人間からシステムへと移す。クラウドネイティブの世界において、正気を保つ唯一の方法はそれなのです。

Share: