在持续集成流水线中根据公司政策验证应用

如果您的组织使用 Policy Controller 管理其 Google Kubernetes Engine (GKE) 企业版集群中的政策,则您可以在应用的持续集成 (CI) 流水线中验证应用的部署配置。本教程演示了如何实现此结果。如果您是为应用构建持续集成流水线的开发者,或者是为多个应用团队构建持续集成流水线模板的平台工程师,则验证您的应用非常有用。

政策是组织安全和合规性的重要组成部分。借助 Policy Controller,您的组织可以通过声明方式集中为所有集群管理这些政策。作为开发者,您可以利用这些政策的集中式和声明式特征。在开发工作流中,您可以使用这些特征尽早验证您的应用是否符合这些政策。了解持续集成流水线中(而不是部署期间)的政策违规情况有两个主要优势:一是可让您提前确保安全性,二是可以加强反馈环,从而减少纠正这些违规情况所需的时间和费用。

本教程使用 Cloud Build 作为持续集成工具,并且使用包含政策的示例 GitHub 代码库来进行演示。

资源

本教程使用多种 Kubernetes 工具。本部分将介绍这些工具、它们之间的交互方式,以及您是否可以将它们替换为其他工具。

您在本教程中使用的工具包括:

  • Policy Controller:基于开源项目 Open Policy Agent - Gatekeeper。政策控制器对在 Kubernetes 集群中创建的对象强制执行政策(例如,阻止使用特定选项或强制使用特定标签)。这些政策称为限制条件。限制条件定义为 Kubernetes 自定义资源。Policy Controller 作为 Google Kubernetes Engine (GKE) 企业版的一部分提供,但您可以在实现中使用 Open Policy Agent - Gatekeeper,而不是 Policy Controller。

  • GitHub:在本教程中,我们使用 GitHub 托管 Git 代码库:一个用于示例应用,另一个包含 Policy Controller 的限制条件。为简单起见,这两个代码库是单个 Git 代码库中的两个不同文件夹。实际上,这两个代码库是不同的代码库。您可以使用任何 Git 解决方案。

  • Cloud Build:Cloud Build 是 Google Cloud 的持续集成解决方案。在本教程中,我们使用它运行验证测试。虽然实现细节可能因持续集成系统而异,但本教程中概述的概念可用于任何基于容器的持续集成系统。

  • Kustomize:Kustomize 是 Kubernetes 配置的自定义工具。其工作原理是采用“基本”配置并应用自定义设置。它可以让您对 Kubernetes 配置执行 DRY(不要重复您自己)方法。借助 kustomize,您可以在基本配置中保留所有环境通用的元素,并为每个环境创建自定义设置。在本教程中,我们将 Kustomize 配置保存在应用代码库中,并在持续集成流水线中“构建”(例如,应用自定义设置)配置。您可以将本教程中概述的概念用于任何可生成准备应用到集群的 Kubernetes 配置的工具(例如 helm template 命令)。

  • Kpt:Kpt 是一种为 Kubernetes 配置构建工作流的工具。Kpt 让您可以提取、显示、自定义、更新、验证和应用 Kubernetes 配置。由于它使用 Git 和 YAML 文件,因此与 Kubernetes 生态系统的大多数现有工具都兼容。在本教程中,我们在持续集成流水线中使用 kpt 从 anthos-config-management-samples 代码库提取限制条件,并根据这些限制条件验证 Kubernetes 配置。

流水线

我们在本教程中使用的持续集成流水线如下图所示:

适用于政策控制器的持续集成流水线

流水线在 Cloud Build 中运行,这些命令在包含示例应用代码库副本的目录中运行。流水线首先通过 Kustomize 生成最终的 Kubernetes 配置。接下来,使用 kpt 从 anthos-config-management-samples 代码库获取我们要根据其进行验证的约束条件。最后,它使用 kpt 根据这些限制条件来验证 Kubernetes 配置。为了实现这最后一步,我们使用一个名为 gatekeeper 的特定配置函数,用于执行此验证。在本教程中,您将手动触发持续集成流水线,但实际上,您可以将其配置为在对 Git 代码库执行 git push 操作之后运行。

目标

  • 使用 Cloud Build 为示例应用运行持续集成流水线。
  • 观察流水线因违反政策而失败。
  • 修改示例应用代码库,使其符合政策。
  • 再次成功运行持续集成流水线。

费用

本教程使用 Google Cloud 的以下收费组件:

  • Cloud Build
  • Google Kubernetes Engine (GKE) 企业版

如需根据您的预计使用量来估算费用,请使用价格计算器

完成本教程后,您可以通过删除您创建的资源来避免继续计费。如需了解详情,请参阅清理部分。

准备工作

  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 为我们提供的示例应用代码库运行持续集成流水线。此流水线根据 anthos-config-management-samples 代码库中提供的限制条件,验证该示例应用代码库中可用的 Kubernetes 配置。

要验证应用配置,请执行以下操作:

  1. 在 Cloud Shell 中,克隆示例应用代码库:

    git clone https://github.com/GoogleCloudPlatform/anthos-config-management-samples.git
    
  2. 使用 Cloud Build 运行持续集成流水线。构建的日志会直接显示在 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']

    在政策控制器中,限制条件是限制条件模板的实例化结果。限制条件模板包含用于实施限制条件的实际 Rego 代码。gcr.io/kpt-fn/gatekeeper 函数需要限制条件模板和限制条件定义才能运行。示例政策代码库包含这两项,但实际上它们可以存储在不同的地方。根据需要使用 kpt pkg get 命令下载限制条件模板和限制条件。

    本教程将 gcr.io/kpt-fn/gatekeeper 与 Cloud Build 搭配使用来验证资源,但您也可以使用另外两个替代方案:

    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 中,将 commonLabels 部分添加到基本 Kustomization 文件中:

    cat <<EOF >> config/base/kustomization.yaml
    commonLabels:
      owner: myself
    EOF
    
  2. 构建完整的 Kubernetes 配置,并观察 owner 标签现在是否存在:

    kubectl kustomize config/prod
    
  3. 使用 Cloud Build 重新运行持续集成流水线:

    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,然后点击关闭以删除项目。

后续步骤

  • 如需查看更多参考架构、图表和最佳做法,请浏览云架构中心