CI パイプラインで会社のポリシーに照らしてアプリの状態を検証する

組織で Policy Controller を使用して Google Kubernetes Engine(GKE)Enterprise エディション クラスタ全体のポリシーを管理している場合は、継続的インテグレーション(CI)パイプラインでアプリのデプロイ構成を検証できます。このチュートリアルでは、この結果を達成する方法について説明します。アプリに CI パイプラインを構築するデベロッパーや、複数のアプリチーム用に CI パイプライン テンプレートを作成するプラットフォーム エンジニアにとって、アプリの検証は有効な手段となります。

ポリシーは、組織のセキュリティとコンプライアンスの重要な部分です。Policy Controller を使用すると、組織はすべてのクラスタに対してこれらのポリシーを一元的かつ宣言的に管理できます。デベロッパーは、ポリシーの一元的かつ宣言型な性質を利用できます。これらの特性を利用して、開発ワークフローの早い段階でポリシーに基づいてアプリを検証できます。デプロイ中ではなく CI パイプラインでのポリシー違反について学習すると、主に 2 つの利点があります。1 つはセキュリティのシフトレフトが可能なことです。そして、フィードバック ループを厳格化することで、違反の修正に要する時間とコストが削減されます。

このチュートリアルでは、Cloud Build を CI ツールとして使用し、デモンストレーションのポリシーを含むサンプル GitHub リポジトリを使用します。

リソース

このチュートリアルでは、いくつかの Kubernetes ツールを使用します。このセクションでは、これらのツールの概要、各コンポーネント間の相互作用、他のツールに置き換えることができるかどうかについて説明します。

このチュートリアルで使用するツールは次のとおりです。

  • Policy Controller: オープンソース プロジェクトの Open Policy Agent - Gatekeeper に基づいています。Policy Controller は、Kubernetes クラスタで作成されたオブジェクトに関するポリシーを適用します(たとえば、特定のオプションの使用の禁止や特定のラベルの使用の強制)。これらのポリシーは「制約」と呼ばれます。制約は、Kubernetes カスタム リソースとして定義されます。Policy Controller は Google Kubernetes Engine(GKE)Enterprise エディションの一部として利用できますが、実装には Policy Controller の代わりに Open Policy Agent の Gatekeeper を使用できます。

  • GitHub: このチュートリアルでは、GitHub を使用して Git リポジトリをホストします。1 つはサンプルアプリ用、もう 1 つは Policy Controller の制約を含むものです。便宜上、2 つのリポジトリは 1 つの Git リポジトリの 2 つの異なるフォルダにしています。実際には、これらは異なるリポジトリです。任意の Git ソリューションを使用できます。

  • Cloud Build: Google Cloud の CI ソリューションです。このチュートリアルでは、これを使用して検証テストを実行します。実装の詳細は CI システムによって異なりますが、このチュートリアルで説明するコンセプトは、任意のコンテナベースの CI システムで使用できます。

  • Kustomize: Kubernetes 構成のカスタマイズ ツールです。ベース構成を取り入れ、カスタマイズすることで機能します。これにより、Kubernetes の構成に対して DRY(Don't Repeat Yourself)アプローチを適用できます。Kustomize では、すべての環境に共通する要素をベース構成に保持し、環境ごとにカスタマイズを行います。このチュートリアルでは、Kustomize の構成をアプリ リポジトリに保存し、CI パイプライン内で構成をビルドします(たとえば、カスタマイズを適用します)。このチュートリアルで説明するコンセプトは、クラスタに適用する準備が整った Kubernetes 構成を生成する任意のツールで使用できます(Helm テンプレート コマンドなど)。

  • Kpt: Kubernetes 構成のワークフローを構築するためのツールです。Kpt を使用すると、Kubernetes 構成の取得、表示、カスタマイズ、更新、検証、適用ができます。これは Git ファイルと YAML ファイルに対応しているため、Kubernetes エコシステムのほとんどのツールと互換性があります。このチュートリアルでは、CI パイプラインで kpt を使用し anthos-config-management-samples リポジトリから制約を取得し、それらの制約に対して Kubernetes 構成を検証します。

パイプライン

このチュートリアルで使用する CI パイプラインを次の図に示します。

Policy Controller の CI パイプライン

このパイプラインは Cloud Build で動作し、コマンドはサンプルアプリのリポジトリのコピーを含むディレクトリで実行されます。パイプラインは、kustomize で最終的な Kustomize 構成を生成することから始まります。次に、kpt を使用して anthos-config-management-samples リポジトリから検証する制約を取得します。最後に、kpt を使用して Kubernetes 構成をこれらの制約に対して検証します。この最後のステップを達成するために、この検証を実行する gatekeeper という特定の構成関数を使用します。このチュートリアルでは、CI パイプラインを手動でトリガーしていますが、実際には Git リポジトリへの git push の後に実行するように構成します。

目標

  • Cloud Build を使用してサンプルアプリの CI パイプラインを実行する。
  • ポリシー違反があるとパイプラインが失敗することを確認する。
  • ポリシーを遵守するように、サンプルアプリのリポジトリを変更する。
  • CI パイプラインを再度実行する。

費用

このチュートリアルでは、課金対象である次の Google Cloud コンポーネントを使用します。

  • Cloud Build
  • Google Kubernetes Engine(GKE)Enterprise エディション

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。

このチュートリアルの終了後は、作成したリソースを削除するとそれ以上の請求が発生しなくなります。詳細については、クリーンアップ セクションをご覧ください。

準備

  1. Google Cloud プロジェクトを選択または作成します。Google Cloud Console で、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクトに対する課金を有効にします

  3. このチュートリアルのコマンドを実行するには、Cloud Shell を開きます。

    Cloud Shell に移動

  4. Cloud Shell で gcloud config get-value project コマンドを実行します。

    たとえば、コマンドで選択したプロジェクトの ID が返されない場合は、プロジェクトが使用されるように Cloud Shell を構成します。

    gcloud config set project PROJECT_ID
    

    PROJECT_ID は、実際のプロジェクト ID に置き換えます。

  5. Cloud Shell で、必要な Cloud Build API を有効にします。

    gcloud services enable cloudbuild.googleapis.com
    

サンプルアプリの構成を検証する

このセクションでは、提供されているサンプル リポジトリに対して、Cloud Build を使用して CI パイプラインを実行します。このパイプラインは、サンプルアプリ リポジトリにある Kubernetes 構成を anthos-config-management-samples リポジトリにある制約に対して検証します。

アプリの構成を検証するには:

  1. Cloud Shell で、サンプルアプリ リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git
    
  2. Cloud Build で CI パイプラインを実行します。ビルドのログが Cloud Shell に直接表示されます。

    cd anthos-config-management-samples/ci-app/app-repo
    gcloud builds submit .
    

    実行するパイプラインは、次のファイルで定義されます。

    steps:
    - id: 'Prepare config'
      # This step builds the final manifests for the app
      # using kustomize and the configuration files
      # available in the repository.
      name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
      entrypoint: '/bin/sh'
      args: ['-c', 'mkdir hydrated-manifests && kubectl kustomize config/prod > hydrated-manifests/prod.yaml']
    - id: 'Download policies'
      # This step fetches the policies from the Anthos Config Management repository
      # and consolidates every resource in a single file.
      name: 'gcr.io/kpt-dev/kpt'
      entrypoint: '/bin/sh'
      args: ['-c', 'kpt pkg get https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git/ci-app/acm-repo/cluster@main constraints
                      && kpt fn source constraints/ hydrated-manifests/ > hydrated-manifests/kpt-manifests.yaml']
    - id: 'Validate against policies'
      # This step validates that all resources comply with all policies.
      name: 'gcr.io/kpt-fn/gatekeeper:v0.2'
      args: ['--input', 'hydrated-manifests/kpt-manifests.yaml']

    Policy Controller では、制約は制約テンプレートのインスタンス化です。制約テンプレートには、制約の実装に使用される実際の Rego コードが含まれています。gcr.io/kpt-fn/gatekeeper 関数を使用するには、制約テンプレートと制約の定義の両方が必要です。サンプル ポリシー リポジトリには両方が含まれますが、実際には異なる場所に保存されていることがあります。必要に応じて kpt pkg get コマンドを使用して、制約テンプレートと制約の両方をダウンロードします。

    このチュートリアルでは、Cloud Build で gcr.io/kpt-fn/gatekeeper を使用してリソースを検証しますが、他にも 2 つの方法があります。

    kpt fn eval hydrated-manifests/kpt-manifests.yaml --image gcr.io/kpt-fn/gatekeeper:v0.2
    
    gator test -f hydrated-manifests/kpt-manifests.yaml
    
  3. 数分後、次のエラーが発生し、パイプラインが失敗することを確認します。

    [...]
    Step #2 - "Validate against policies": [error] apps/v1/Deployment/nginx-deployment : Deployment objects should have an 'owner' label indicating who created them.
    Step #2 - "Validate against policies": violatedConstraint: deployment-must-have-owner
    Finished Step #2 - "Validate against policies"
    2022/05/11 18:55:18 Step Step #2 - "Validate against policies" finished
    2022/05/11 18:55:19 status changed to "ERROR"
    ERROR
    ERROR: build step 2 "gcr.io/kpt-fn/gatekeeper:v0.2" failed: exit status 1
    2022/05/11 18:55:20 Build finished with ERROR status
    

    構成に違反する制約は、次のファイルに定義されています。これは K8sRequiredLabels という Kubernetes カスタム リソースです。

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: deployment-must-have-owner
    spec:
      match:
        kinds:
          - apiGroups: ["apps"]
            kinds: ["Deployment"]
      parameters:
        labels:
          - key: "owner"
        message: "Deployment objects should have an 'owner' label indicating who created them."

    この制約に対応する制約テンプレートについては、GitHub の requiredlabels.yaml をご覧ください。

  4. Kubernetes 構成全体を自分でビルドし、owner ラベルが実際に存在しないことを確認します。構成を作成するには:

    kubectl kustomize config/prod
    

会社のポリシーを遵守するようにアプリを修正する

このセクションでは、Kustomize を使用してポリシー違反を修正します。

  1. Cloud Shell で、ベースの Kustomization ファイルに commonLabels セクションを追加します。

    cat <<EOF >> config/base/kustomization.yaml
    commonLabels:
      owner: myself
    EOF
    
  2. 完全な Kubernetes 構成を作成し、owner ラベルが存在していることを確認します。

    kubectl kustomize config/prod
    
  3. Cloud Build で CI パイプラインを再度実行します。

    gcloud builds submit .
    

    次の出力が表示され、パイプラインが成功します。

    [...]
    Step #2 - "Validate against policies": [RUNNING] "gcr.io/kpt-fn/gatekeeper:v0"
    Step #2 - "Validate against policies": [PASS] "gcr.io/kpt-fn/gatekeeper:v0"
    [...]
    

クリーンアップ

  1. Google Cloud コンソールで、[リソースの管理] ページに移動します。

    [リソースの管理] に移動

  2. プロジェクト リストで、削除するプロジェクトを選択し、[削除] をクリックします。
  3. ダイアログでプロジェクト ID を入力し、[シャットダウン] をクリックしてプロジェクトを削除します。

次のステップ