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. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

次のステップ