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

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

本页面适用于想要提供并维护自动化以进行审核或强制执行,从而确保云平台中运行的所有资源满足组织合规性要求的 IT 管理员和运维人员,以及管理底层技术基础设施生命周期的 IT 管理员和运维人员。如需详细了解我们在 Google Cloud 内容中提及的常见角色和示例任务,请参阅常见的 GKE Enterprise 用户角色和任务

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

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

资源

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

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

  • Policy Controller:基于开源项目 Open Policy Agent - Gatekeeper。政策控制器对在 Kubernetes 集群中创建的对象强制执行政策(例如,阻止使用特定选项或强制使用特定标签)。这些政策称为限制条件。限制条件定义为 Kubernetes 自定义资源。Policy Controller 作为 Google Kubernetes Engine (GKE) Enterprise 版本的一部分提供,但您可以将 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 配置。

流水线

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

适用于 Policy Controller 的 CI 流水线

流水线在 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) Enterprise 版本

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

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

准备工作

  1. 选择或创建 Google Cloud 项目。在 Google Cloud 控制台中,前往管理资源页面:

    转到“管理资源”

  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. 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.

后续步骤

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