有关在 Google Cloud 中构建和部署应用的更改

本文档将引导您详细了解在使用 Cloud Build 构建容器映像并将其部署到 Cloud Run 或 Google Kubernetes Engine 等运行时环境时,Container Registry 和 Artifact Registry 之间的区别。 Google Cloud

在本指南中,我们将重点比较标准 Artifact Registry 仓库,即独立于 Container Registry 且支持所有 Artifact Registry 功能的常规 Artifact Registry 仓库。如果您的管理员设置了具有 gcr.io 网域支持的代码库,系统会自动将对 gcr.io 主机名的请求重定向到相应的 Artifact Registry 代码库,并且有权访问 Container Registry 的默认服务账号对 Artifact Registry 也有等效的默认权限。

如需了解使用 Docker 客户端时 Container Registry 和 Artifact Registry 之间的区别,请参阅使用 Docker 推送和拉取的变更

您可以参考这些信息,调整现有的命令、配置或文档,使其适用于将 Container Registry 与 Cloud Build 搭配使用。

准备工作

本文档假定您满足以下条件:

  1. 在您的项目中启用 Artifact Registry
  2. 启用了 Cloud Build API 以及您与 Artifact Registry 搭配使用的任何其他 Google Cloud 服务的 API。

工作流程变更

在同一项目中将 Cloud Build 与 Container Registry 搭配使用时,工作流程如下所示:

  1. 使用 Dockerfile构建配置文件,通过 Cloud Build 构建映像、为其添加标记并将其推送到代码库。

    以下示例会构建映像 my-image,为其添加标记 tag1,并将其推送到项目 my-project 中的主机 gcr.io

    gcloud builds submit --tag gcr.io/my-project/my-image:tag1
    
  2. Google Cloud 运行时环境(例如 Cloud Run 和 Google Kubernetes Engine)从注册表中拉取映像。

    例如,以下命令会将上一步中的映像部署到 Cloud Run 作为 my-service

    gcloud run deploy my-service --image gcr.io/my-project/my-image:tag1
    

Container Registry 工作流将管理员职责与构建和部署结合在一起。

  • 启用某些 Google Cloud API 后,系统会自动启用 Container Registry API。这意味着,这些服务的用户对同一项目中的 Container Registry 具有隐式访问权限。例如,默认情况下,可以运行 Cloud Build 中的 build 的用户可以将映像推送到注册库并添加注册库主机。
  • Cloud Build 服务账号具有创建 Cloud Storage 存储分区的权限。这意味着,该账号在首次将映像推送到主机时,可以自动将 Container Registry 主机添加到项目中。这也意味着,该账号可以在整个项目中创建、读取和写入存储分区,包括 Container Registry 未使用的存储分区。

在工件注册库中,管理员角色和 build 角色明确分开,这会更改构建和部署工作流中的步骤。如需将 Container Registry 工作流调整为适用于 Artifact Registry,请进行以下更改。每个步骤都链接到有关修改工作流的其他信息。

  1. 新功能启用 Artifact Registry API。

    您必须启用 Artifact Registry API。Cloud Build 和 Cloud Run、GKE 等运行时环境不会自动为您启用该 API。

  2. 新建:如果目标 Docker 仓库尚不存在,则创建目标 Docker 仓库。您必须先创建一个仓库,然后才能向其推送映像。推送映像不会触发系统创建仓库,而且 Cloud Build 服务账号也没有创建仓库的权限。

  3. 已更改:使用 Dockerfile 或构建配置文件,通过 Cloud Build 构建、标记和推送映像到代码库。

    以下示例命令与 Container Registry 示例相同,但使用的是映像的 Artifact Registry 代码库路径。

    gcloud builds submit --tag us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1
    
  4. 已更改:将映像部署到 Google Cloud 运行时环境(例如 Cloud Run 或 GKE)。

    以下示例命令与 Container Registry 示例相同,但使用的是映像的 Artifact Registry 代码库路径。

    gcloud run deploy my-service --image us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1
    

此外,Artifact Registry 使用的角色与 Container Registry 不同,用于控制对映像的访问权限。在以下情况下,您需要配置权限

  • Cloud Build 或 Google Cloud 运行时环境位于与 Artifact Registry 不同的项目中。
  • 您为 Cloud Build 或 GKE 等服务使用自定义服务账号,而不是默认服务账号。 Google Cloud
  • 您向其他用户或服务账号授予了权限。

启用 API

要点:

以下对比介绍了如何为每项服务启用该 API:

Container Registry

启用以下 API 时,系统还会自动启用 Container Registry API: Google Cloud

  • App Engine 柔性环境
  • Cloud Build
  • Cloud Run functions
  • Cloud Run
  • Artifact Analysis 中的容器扫描或按需扫描
  • Google Kubernetes Engine

默认情况下,如果用户可以在 Cloud Build 中运行 build、使用 Artifact Analysis 扫描容器或将容器部署到Google Cloud 运行时,则在注册表位于同一项目中时,他们会隐式拥有对 Container Registry 中映像的访问权限。

Artifact Registry

您必须启用 Artifact Registry API。Cloud Build、Cloud Run 和 GKE 等服务不会自动启用 Artifact Registry API。

您可以使用 gcloud 在同一项目中启用多个 API。例如,如需启用 Cloud Build API 和 Artifact Registry API,请运行以下命令:

gcloud services enable
    artifactregistry.googleapis.com \
    cloudbuild.googleapis.com

添加注册库和代码库

要点:

  • 您必须先创建 Artifact Registry Docker 代码库,然后才能将映像推送到其中。
  • Container Registry 会将所有映像存储在同一存储分区中的单个多区域位置。在 Artifact Registry 中,您可以在同一区域或多区域中创建多个代码库,并为其设置单独的访问权限政策。

以下对比介绍了每项服务中的代码库设置:

Container Registry

在 Container Registry 中,您最多可以向项目添加四个注册表主机。您可以通过推送第一个映像来添加注册表主机。

  1. 如需向项目添加 gcr.io 等注册表,需要在项目级拥有 Storage Admin 角色的账号推送初始映像。

    例如,如果项目 my-project 中不存在 gcr.io 主机,则推送映像 gcr.io/my-project/my-image:1.0 会触发以下步骤:

    1. gcr.io 主机添加到项目中
    2. 在项目中为 gcr.io 创建一个存储分区。
    3. 将图片存储为 gcr.io/my-project/my-image:1.0
  2. 完成此初始推送后,您可以为其他用户授予对存储分区的权限

默认情况下,Cloud Build 拥有创建存储分区所需的权限,因此初始映像推送和后续推送无法区分。

在项目中,注册表主机会将所有映像存储在同一存储分区中。在以下示例中,项目 my-project 在注册表 gcr.io 中有两个名为 web-app 的映像。一个位于项目 ID my-project 直接下方。另一个映像位于代码库 team1 中。

gcr.io/my-project/web-app
gcr.io/my-project/team1/web-app

Artifact Registry

Cloud Build 无权在 Artifact Registry pkg.dev 网域中创建标准代码库。

具有 Artifact Registry 代码库管理员角色的账号必须先创建代码库,然后您才能将映像推送到该代码库。然后,您可以为其他用户授予对代码库的权限

在 Artifact Registry 中,每个代码库都是一个单独的资源。因此,所有映像路径都必须包含代码库。

有效的图片路径:

us-central1-docker.pkg.dev/my-project/team1/web-app:1.0
us-central1-docker.pkg.dev/my-project/team2/web-app:1.0

映像路径无效(不包含代码库):

us-central1-docker.pkg.dev/my-project/web-app:1.0

以下示例展示了将映像推送到缺失的仓库时会失败的情况。

  • 如果 us-central1-docker.pkg.dev/my-project/team1 不存在,则将映像推送到 us-central1-docker.pkg.dev/my-project/team1
  • us-central1-docker.pkg.dev/my-project/team1 存在但 us-central1-docker.pkg.dev/my-project/team2 不存在时,将映像推送到 us-central1-docker.pkg.dev/my-project/team2

授予权限

要点:

  • Google Cloud 服务对 Container Registry 和 Artifact Registry 具有等效的读写权限。不过,默认的 Cloud Build 服务账号无法在 pkg.dev 网域中创建标准仓库。
  • 向其他有权访问 Artifact Registry 的账号授予适当的 Artifact Registry 角色。
  • Container Registry 支持在存储分区级层进行访问权限控制。Artifact Registry 支持仓库级访问权限控制。

下表对比了每项服务的权限:

Container Registry

Container Registry 使用 Cloud Storage 角色来控制访问权限。Cloud Build 在 Storage Admin 角色中拥有向项目添加 Container Registry 主机所需的权限

存储分区级 Storage Object Viewer
从项目中的现有注册表主机拉取(读取)映像。
存储分区级别的 Storage Legacy Bucket Writer
为项目中的现有注册表主机推送(写入)和拉取(读取)映像。
项目级 Storage Admin
将初始映像推送到主机,以向项目添加注册表主机。

在初始映像推送到注册表后,您可以向需要访问存储分区的其他账号授予 Cloud Storage 角色。请注意,具有 Storage Admin 角色的所有权限的任何账号都可以读取、写入和删除整个项目中的存储分区和存储对象。

存储分区的权限会应用于注册表中的所有代码库。例如,对 gcr.io/my-project 的存储分区拥有 Storage Object Viewer 权限的任何用户都可以读取以下所有代码库中的图片:

gcr.io/my-project/team1
gcr.io/my-project/team2
gcr.io/my-project/test
gcr.io/my-project/production

Artifact Registry

Artifact Registry 有自己的角色来控制访问权限。这些角色可在管理员角色和代码库用户角色之间进行明确分离。

Cloud Build 具有 Artifact Registry Writer 角色中的权限,因为它只需在 pkg.dev 网域上使用标准代码库推送和拉取映像。

只有管理代码库的账号才应具有 Artifact Registry Repository Administrator 或 Artifact Registry Administrator 角色。

Artifact Registry Reader
列出工件和代码库。下载工件。
Artifact Registry Writer
列出工件和代码库。下载工件、上传新的工件版本,以及添加或更新代码。
Artifact Registry Repository Administrator
Artifact Registry Writer 权限以及删除工件和标记的权限。
Artifact Registry Administrator
Artifact Registry 代码库管理员权限以及创建、更新、删除代码库和向代码库授予权限的权限。

您可以在代码库级别应用这些权限。例如:

  • 向 Team 1 授予对 us-central1-docker.pkg.dev/my-project/team1 的访问权限
  • 向 Team 2 授予对 us-central1-docker.pkg.dev/my-project/team2 的访问权限。

如需详细了解如何授予 Artifact Registry 权限,请参阅访问权限控制文档。

构建和推送映像

要点:

  • 您必须先创建 Artifact Registry Docker 代码库,然后才能将映像推送到其中。
  • Artifact Registry 主机名不同于 Container Registry 主机名。

Cloud Build 可以一步构建、标记和推送映像。

借助 Container Registry,Cloud Build 可以成功将映像推送到项目中尚不存在的注册表主机。 Google Cloud 对于此初始映像推送,Cloud Build 有权自动将注册表主机添加到项目中。

如需调整 Container Registry 工作流,请执行以下操作:

  1. 请先设置代码库,然后再将映像推送到这些代码库。
  2. 更新构建配置文件或 gcloud builds submit 命令中的映像路径。

使用构建配置文件进行构建

将您构建的映像的 Container Registry 路径替换为现有 Artifact Registry 仓库的路径。

以下 cloudbuild.yaml 文件示例会构建映像 us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1

steps:
- name: 'gcr.io/cloud-builders/docker'
  args: [ 'build', '-t', 'us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1', '.' ]
images:
- 'us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1'

然后,您可以使用以下命令构建映像:

gcloud builds submit --config cloudbuild.yaml

使用 Dockerfile 进行构建

将您构建的映像的 Container Registry 路径替换为现有 Artifact Registry 仓库的路径。

以下示例命令会使用当前目录中的 Dockerfile 构建映像 us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1

gcloud builds submit --tag us-central1-docker.pkg.dev/my-project/my-repo/my-image:tag1

部署映像

要点:

  • Artifact Registry 主机名不同于 Container Registry 主机名。

如需调整 Container Registry 工作流,请更新部署配置和部署命令中的映像路径。以下部分展示了 Cloud Build、Cloud Run 和 GKE 的示例,但相同的方法也适用于部署映像的任何其他服务。 Google Cloud

Cloud Build

将您要部署的映像的 Container Registry 路径替换为现有 Artifact Registry 仓库的路径。

以下示例 cloudbuild.yaml 文件会部署示例映像 us-docker.pkg.dev/cloudrun/container/hello

steps:
- name: 'gcr.io/cloud-builders/gcloud'
  args:
  - 'run'
  - 'deploy'
  - 'cloudrunservice'
  - '--image'
  - 'us-docker.pkg.dev/cloudrun/container/hello'
  - '--region'
  - 'us-central1'
  - '--platform'
  - 'managed'
  - '--allow-unauthenticated'

Cloud Run

将您要部署的映像的 Container Registry 路径替换为现有 Artifact Registry 仓库的路径。

例如,以下命令会部署示例图片 us-docker.pkg.dev/cloudrun/container/hello

gcloud run deploy my-service --image us-docker.pkg.dev/cloudrun/container/hello

GKE

将您构建的映像的 Container Registry 路径替换为现有 Artifact Registry 仓库的路径。

以下 Artifact Registry 示例使用示例图片 us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

通过命令行创建集群:

kubectl create deployment hello-server --image=us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0

在部署清单中指定映像:

In a deployment manifest:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 3
  selector:
    matchLabels:
      run: my-app
  template:
    metadata:
      labels:
        run: my-app
    spec:
      containers:
      - name: hello-app
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0