如果直接从第三方注册表中拉取某些容器映像以部署到 Google Cloud 环境(例如 Google Kubernetes Engine 或 Cloud Run),则映像拉取或第三方服务中断的速率限制可能会中断您的构建和部署。本页面介绍如何识别这些映像并将其复制到 Artifact Registry 中以进行整合、一致的容器映像管理。
Artifact Registry 不会监控第三方注册表,以检测您复制到 Artifact Registry 的映像的更新情况。如果您想要将较新版本的映像整合到流水线中,则必须将该映像推送到 Artifact Registry。
迁移概览
容器映像的迁移包括以下步骤:
- 设置前提条件。
- 识别要迁移的映像。
- 搜索 Dockerfile 文件和部署清单,查找第三方注册表的引用
- 使用 Cloud Logging 和 BigQuery 确定从第三方注册表拉取映像的频率。
- 将识别的映像复制到 Artifact Registry。
- 验证注册表的权限是否配置正确,尤其是 Artifact Registry 和 Google Cloud 部署环境位于不同的项目中时。
- 更新部署的清单。
- 重新部署您的工作负载。
准备工作
- 验证您的权限。在要将映像迁移到 Artifact Registry 的项目中,您必须具有 Owner 或 Editor IAM 角色。
-
- 选择要在其中使用 Artifact egistry 的 Google Cloud 项目
- 在 Google Cloud 控制台中,前往 Cloud Shell
查找您的项目 ID 并在 Cloud Shell 中进行设置。将
YOUR_PROJECT_ID
替换为您的项目 ID。gcloud config set project YOUR_PROJECT_ID
导出以下环境变量:
export PROJECT=$(gcloud config get-value project)
使用以下命令启用 BigQuery、Artifact Registry 和 Cloud Monitoring API:
gcloud services enable \ artifactregistry.googleapis.com \ stackdriver.googleapis.com \ logging.googleapis.com \ monitoring.googleapis.com
如果当前未使用 Artifact Registry,请为您的映像配置代码库:
验证是否已安装 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 中的位置(如果文件位于虚拟机)。
在包含 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: 行,根据需要调整清单的存储方式
如需列出当前在集群上运行的映像,请运行以下命令:
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。日志接收器包含目标位置以及用于选择要导出的日志条目的查询。您可以通过查询各个项目来创建接收器,也可以使用脚本来跨项目收集数据。
如需为单个项目创建接收器,请执行以下操作:
选择 Google Cloud 项目。
在查询构建器标签页中,输入以下查询:
resource.type="k8s_pod" jsonPayload.reason="Pulling"
将历史过滤条件从过去 1 小时更改为过去 7 天。
点击运行查询。
验证结果正确显示后,点击操作 > 创建接收器。
在接收器列表中,选择 BigQuery 数据集,然后点击下一步。
在“修改接收器”面板中,执行以下步骤:
- 在接收器名称字段中,输入
image_pull_logs
。 - 在接收器目标位置字段中,创建新数据集或在另一个项目中选择目标数据集。
- 在接收器名称字段中,输入
点击创建接收器。
如需为多个项目创建接收器,请执行以下操作:
在 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
。
- PROJECT-LIST 是用空格分隔的 Google Cloud 项目 ID 列表。例如
创建接收器后,数据需要一些时间才能流向 BigQuery 表,具体取决于映像的拉取频率。
查询拉取频率
获得构建创建的映像拉取的代表性样本后,运行查询以获取拉取频率。
请运行以下查询:
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 工具可以帮助您执行复制过程。
在 Cloud Shell 中使用您识别的映像名称创建一个文本文件
images.txt
。例如:ubuntu:18.04 debian:buster hello-world:latest redis:buster jupyter/tensorflow-notebook
下载 gcrane。
GO111MODULE=on go get github.com/google/go-containerregistry/cmd/gcrane
创建一个名为
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
让该脚本可执行:
chmod x copy_images.sh
运行该脚本以复制文件:
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
。