从第三方注册表迁移容器映像

如果直接从第三方注册表中拉取某些容器映像以部署到 Google Cloud 环境(例如 Google Kubernetes Engine 或 Cloud Run),则映像拉取或第三方服务中断的速率限制可能会中断您的构建和部署。本页面介绍如何识别这些映像并将其复制到 Artifact Registry 中以进行整合、一致的容器映像管理。

Artifact Registry 不会监控第三方注册表,以检测您复制到 Artifact Registry 的映像的更新情况。如果您想要将较新版本的映像整合到流水线中,则必须将该映像推送到 Artifact Registry。

迁移概览

容器映像的迁移包括以下步骤:

  1. 设置前提条件
  2. 识别要迁移的映像。
    • 搜索 Dockerfile 文件和部署清单,查找第三方注册表的引用
    • 使用 Cloud Logging 和 BigQuery 确定从第三方注册表拉取映像的频率。
  3. 将识别的映像复制到 Artifact Registry。
  4. 验证注册表的权限是否配置正确,尤其是 Artifact Registry 和 Google Cloud 部署环境位于不同的项目中时。
  5. 更新部署的清单
  6. 重新部署您的工作负载。

准备工作

  1. 验证您的权限。在要将映像迁移到 Artifact Registry 的项目中,您必须具有 Owner 或 Editor IAM 角色。
  2. 转到项目选择器页面

    1. 选择要在其中使用 Artifact egistry 的 Google Cloud 项目
    2. 在 Google Cloud 控制台中,前往 Cloud Shell
    3. 查找您的项目 ID 并在 Cloud Shell 中进行设置。将 YOUR_PROJECT_ID 替换为您的项目 ID。

      gcloud config set project YOUR_PROJECT_ID
      
  3. 导出以下环境变量:

      export PROJECT=$(gcloud config get-value project)
    
  4. 使用以下命令启用 BigQuery、Artifact Registry 和 Cloud Monitoring API:

    gcloud services enable \
    artifactregistry.googleapis.com \
    stackdriver.googleapis.com \
    logging.googleapis.com \
    monitoring.googleapis.com
    
  5. 如果当前未使用 Artifact Registry,请为您的映像配置代码库:

  6. 验证是否已安装 Go 版本 1.13 或更高版本。

    • 使用以下命令查看现有的 Go 安装版本:

      go version
      
    • 如果您需要安装或更新 Go,请参阅 Go 安装文档

费用

本指南使用 Google Cloud 的以下收费组件:

识别要迁移的映像

搜索用于构建和部署容器映像的文件,以查找第三方注册表的引用,然后检查映像的拉取频率。

识别 Dockerfile 中的引用

在 Dockerfile 的存储位置执行此步骤。该位置可能是在本地签出代码的位置或 Cloud Shell 中的位置(如果文件位于虚拟机)。

在包含 Dockerfile 的目录中,运行以下命令:

grep -inr -H --include Dockerfile\* "FROM" . | grep -i -v -E 'docker.pkg.dev|gcr.io' 

输出类似于以下示例:

./code/build/baseimage/Dockerfile:1:FROM debian:stretch
./code/build/ubuntubase/Dockerfile:1:FROM ubuntu:latest
./code/build/pythonbase/Dockerfile:1:FROM python:3.5-buster

此命令会搜索目录中的所有 Dockerfile,并标识 "FROM" 行。根据需要调整命令,以匹配 Dockerfile 的存储方式。

识别清单中的引用

在存储 GKE 或 Cloud Run 清单的存储位置执行此步骤。该位置可能是在本地签出代码的位置或 Cloud Shell 中的位置(如果文件位于虚拟机)。

  1. 在包含 GKE 或 Cloud Run 清单的目录中,运行以下命令:

    grep -inr -H --include \*.yaml "image:" . | grep -i -v -E 'docker.pkg.dev|gcr.io'
    

    示例输出:

    ./code/deploy/k8s/ubuntu16-04.yaml:63: image: busybox:1.31.1-uclibc
    ./code/deploy/k8s/master.yaml:26:      image: kubernetes/redis:v1
    

    此命令会查看您的目录中的所有 YAML 文件,并标识 image: 行,根据需要调整清单的存储方式

  2. 如需列出当前在集群上运行的映像,请运行以下命令:

      kubectl get all --all-namespaces -o yaml | grep image: | grep -i -v -E 'docker.pkg.dev|gcr.io'
    

    此命令会返回当前选定的 Kubernetes 集群中运行的所有对象,并获取其映像名称。

    示例输出:

    - image: nginx
      image: nginx:latest
        - image: nginx
        - image: nginx
    

在所有 Google Cloud 项目中对所有 GKE 集群运行此命令,以实现全部覆盖。

识别从第三方注册表拉取映像的频率

在从第三方注册表拉取映像的项目中,使用映像拉取频率相关信息来确定您的用量是否接近或超过第三方注册表强制执行的速率限制。

收集日志数据

创建日志接收器,以将数据导出到 BigQuery。日志接收器包含目标位置以及用于选择要导出的日志条目的查询。您可以通过查询各个项目来创建接收器,也可以使用脚本来跨项目收集数据。

如需为单个项目创建接收器,请执行以下操作:

  1. 转到日志浏览器

  2. 选择 Google Cloud 项目。

  3. 查询构建器标签页中,输入以下查询:

      resource.type="k8s_pod"
      jsonPayload.reason="Pulling"
    
  4. 将历史过滤条件从过去 1 小时更改为过去 7 天

    映像

  5. 点击运行查询

  6. 验证结果正确显示后,点击操作 > 创建接收器

  7. 在接收器列表中,选择 BigQuery 数据集,然后点击下一步

  8. 在“修改接收器”面板中,执行以下步骤:

    • 接收器名称字段中,输入 image_pull_logs
    • 接收器目标位置字段中,创建新数据集或在另一个项目中选择目标数据集。
  9. 点击创建接收器

如需为多个项目创建接收器,请执行以下操作:

  1. 打开 Cloud Shell

  2. 在 Cloud Shell 中运行以下命令:

    PROJECTS="PROJECT-LIST"
    DESTINATION_PROJECT="DATASET-PROJECT"
    DATASET="DATASET-NAME"
    
    for source_project in $PROJECTS
    do
      gcloud logging --project="${source_project}" sinks create image_pull_logs bigquery.googleapis.com/projects/${DESTINATION_PROJECT}/datasets/${DATASET} --log-filter='resource.type="k8s_pod" jsonPayload.reason="Pulling"'
    done
    

    其中

    • PROJECT-LIST 是用空格分隔的 Google Cloud 项目 ID 列表。例如 project1 project2 project3
    • DATASET-PROJECT 是您要存储数据集的项目。
    • DATASET-NAME 是数据集的名称,例如 image_pull_logs

创建接收器后,数据需要一些时间才能流向 BigQuery 表,具体取决于映像的拉取频率。

查询拉取频率

获得构建创建的映像拉取的代表性样本后,运行查询以获取拉取频率。

  1. 转到 BigQuery 控制台

  2. 请运行以下查询:

    SELECT
      REGEXP_EXTRACT(jsonPayload.message, r'"(.*?)"') AS imageName,
      COUNT(*) AS numberOfPulls
    FROM
          `DATASET-PROJECT.DATASET-NAME.events_*`
    GROUP BY
          imageName
    ORDER BY
          numberOfPulls DESC
    

    其中

    • DATASET-PROJECT 是包含您的数据集的项目。
    • DATASET-NAME 是数据集的名称。

以下示例展示了查询的输出。在 imageName 列中,您可以查看未存储在 Artifact Registry 或 Container Registry 中的映像的拉取频率。

映像

将映像复制到 Artifact Registry

通过第三方注册表确定映像后,就可以将它们复制到 Artifact Registry 中了。gcrane 工具可以帮助您执行复制过程。

  1. 在 Cloud Shell 中使用您识别的映像名称创建一个文本文件 images.txt。例如:

    ubuntu:18.04
    debian:buster
    hello-world:latest
    redis:buster
    jupyter/tensorflow-notebook
    
  2. 下载 gcrane

      GO111MODULE=on go get github.com/google/go-containerregistry/cmd/gcrane
    
  3. 创建一个名为 copy_images.sh 的脚本以复制文件列表。

    #!/bin/bash
    
    images=$(cat images.txt)
    
    if [ -z "${AR_PROJECT}" ]
    then
        echo ERROR: AR_PROJECT must be set before running this
        exit 1
    fi
    
    for img in ${images}
    do
        gcrane cp ${img} LOCATION-docker.pkg.dev/${AR_PROJECT}/${img}
    done
    

    LOCATION 替换为您的代码库的区域多区域位置。

    让该脚本可执行:

      chmod +x copy_images.sh
    
  4. 运行该脚本以复制文件:

    AR_PROJECT=${PROJECT}
    ./copy_images.sh
    

验证权限

默认情况下,Google Cloud CI/CD 服务有权访问同一 Google Cloud 项目中的 Artifact Registry。

  • Cloud Build 可以推送和拉取映像
  • 运行时环境(如 GKE、Cloud Run、App Engine 柔性环境和 Compute Engine)可以拉取映像。

如果您需要跨项目推送或拉取映像,或者您使用的是流水线中需要访问 Artifact Registry 的第三方工具,请确保权限已正确配置,然后再更新和重新部署工作负载。

如需了解详情,请参阅访问权限控制文档。

更新清单以引用 Artifact Registry

更新 Dockerfile 和清单,以引用 Artifact Registry 而不是第三方注册表。

以下示例展示了引用第三方注册表的清单:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

此更新后的清单版本指向 us-docker.pkg.dev 上的映像。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: us-docker.pkg.dev/<AR_PROJECT>/nginx:1.14.2
        ports:
        - containerPort: 80

如果有大量清单,请使用 sed 或其他工具跨多个文本文件处理更新。

重新部署工作负载

使用更新后的清单重新部署工作负载。

通过在 BigQuery 控制台中运行以下查询,来跟踪新映像拉取:

SELECT`

FORMAT_TIMESTAMP("%D %R", timestamp) as timeOfImagePull,
REGEXP_EXTRACT(jsonPayload.message, r'"(.*?)"') AS imageName,
COUNT(*) AS numberOfPulls
FROM
  `image_pull_logs.events_*`
GROUP BY
  timeOfImagePull,
  imageName
ORDER BY
  timeOfImagePull DESC,
  numberOfPulls DESC

所有新映像拉取都应从 Artifact Registry 拉取并包含字符串 docker.pkg.dev