本教程向将容器部署到 Kubernetes 的开发者和运维人员介绍了如何使用容器映像摘要来识别容器映像。容器映像摘要是唯一且不可改变地标识容器映像。
与使用映像标记相比,使用映像摘要部署容器映像有诸多好处。如需详细了解映像摘要,请参阅使用容器映像摘要的随附文档,然后再继续本教程。
Kubernetes pod 规范中的容器的 image
参数接受包含摘要的映像。此参数适用于所有使用 Pod 规范的位置,例如 Deployment、StatefulSet、DaemonSet、ReplicaSet、CronJob 和 Job 资源的 template
部分。
如需使用摘要部署映像,请使用映像名称,后跟 @sha256:
和摘要值。以下是使用包含摘要的映像的 Deployment 资源示例:
apiVersion: apps/v1 kind: Deployment metadata: name: echo-deployment spec: selector: matchLabels: app: echo template: metadata: labels: app: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 ports: - containerPort: 8080
使用映像摘要的一个缺点是,在将映像发布到注册表之前,您不知道摘要值。构建新映像时,摘要值会发生变化,您需要在每次部署时更新 Kubernetes 清单。
本教程介绍了如何使用 Skaffold、kpt、digester、kustomize、gke-deploy
和 ko
等工具在清单中使用映像摘要。
建议
本文档介绍了几种在 Kubernetes 部署中使用映像摘要的方法。本文档中介绍的工具互为补充。例如,您可以结合使用 kpt 函数的输出和 kustomize 来为不同环境创建变体。Skaffold 可以使用 ko
构建映像,并使用 kubectl
或 kpt 将映像部署到 Kubernetes 集群。
这些工具互为补充的原因是它们根据 Kubernetes 资源模型 (KRM) 执行结构化修改。此模型使工具成为可插入工具,您可以改进这些工具的用途,创建可帮助您部署应用和服务的流程和流水线。
首先,我们建议您使用最适合您的现有工具和流程的方法:
Skaffold 可以向映像引用添加摘要。您只需进行细微的配置更改即可启用此功能。采用 Skaffold 具有额外优势,例如总结不同的工具构建和部署容器映像的方式。
通过使用 digester 工具作为 Kubernetes 集群中的可变准入网络钩子,您可以向所有部署添加摘要,同时将对构建和部署容器映像的当前流程的影响降至最低。Digester 网络钩子也简化了 Binary Authorization 的采用,因为它只需要将标签添加到命名空间。
如果您需要灵活的工具来处理 Kubernetes 清单,kpt 不失为一种很不错的选择。Digester 工具可以在 kpt 流水线中用作客户端 KRM 函数。
如果您已使用 kustomize 跨环境管理 Kubernetes 清单,我们建议您利用其映像转换器以摘要的形式部署映像。
如果您没有使用本文档中所述的任何工具,我们建议您从 Skaffold 和 digester 网络钩子开始。Skaffold 是开发者和发布团队使用的常用工具,与本教程中所述的其他工具集成。随着需求的变化,您可以利用这些集成选项。Digester Kubernetes webhook 通过为整个集群启用基于摘要的部署来补充 Skaffold。
目标
- 使用 Skaffold 构建和推送映像,并在 Kubernetes 清单中插入映像名称和摘要。
- 使用 digester 客户端函数和可变准入网络钩子,将摘要添加到 Kubernetes Pod 和 Pod 模板中的映像。
- 使用 kpt setter 将 Kubernetes 清单中的映像标记替换为映像摘要。
- 使用 kustomize 生成带有映像摘要的 Kubernetes 清单。
- 使用
gke-deploy
将映像标记解析为 Kubernetes 清单中的摘要。 - 使用
ko
构建和推送映像,并在 Kubernetes 清单中插入映像名称和摘要。
费用
在本文档中,您将使用 Google Cloud 的以下收费组件:
您可使用价格计算器根据您的预计使用情况来估算费用。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Artifact Registry API.
-
In the Google Cloud console, activate Cloud Shell.
在 Cloud Shell 中,为 Google Cloud CLI 设置默认项目:
gcloud config set project PROJECT_ID
将
PROJECT_ID
替换为您的[项目 ID]。在 Artifact Registry 中创建容器映像制品库:
gcloud artifacts repositories create REPOSITORY \ --location=LOCATION \ --repository-format=docker
替换以下内容:
REPOSITORY
:您要用于制品库的名称,例如digest-tutorial
。LOCATION
:Artifact Registry 位置,例如us-central1
。
为本教程中使用的 CLI 工具配置针对 Artifact Registry 位置的身份验证:
gcloud auth configure-docker LOCATION-docker.pkg.dev
使用 Skaffold
Skaffold 是一种命令行工具,用于持续开发应用并将应用持续部署到 Kubernetes 集群。
使用 Skaffold 构建映像,将映像推送到 Artifact Registry,然后将 Kubernetes 清单模板中的 image
占位值替换为推送映像的名称、标记和摘要:
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/skaffold cd ~/container-image-digests-tutorial/skaffold
克隆 Skaffold Git 代码库:
git clone https://github.com/GoogleContainerTools/skaffold.git
转到
getting-started
示例的目录:cd skaffold/examples/getting-started
查看与您的 Skaffold 版本匹配的 Git 标记:
git checkout $(skaffold version)
查看
skaffold.yaml
配置文件:cat skaffold.yaml
该文件类似于以下内容:
apiVersion: skaffold/v4beta6 kind: Config build: artifacts: - image: skaffold-example manifests: rawYaml: - k8s-pod.yaml
build.artifacts
部分包含占位符映像名称。Skaffold 会在输入清单文件中查找此占位符。manifests
部分指示 Skaffold 读取当前目录中名为k8s-pod.yaml
的输入清单。如需大致了解所有可用选项,请参阅
skaffold.yaml
参考文档。查看 Kubernetes 清单模板:
cat k8s-pod.yaml
该文件如下所示:
apiVersion: v1 kind: Pod metadata: name: getting-started spec: containers: - name: getting-started image: skaffold-example
image
字段中的skaffold-example
占位值与skaffold.yaml
文件中的image
字段的值匹配。Skaffold 会在渲染的输出中将此占位值替换为完整的映像名称和摘要。构建映像并将其推送到 Artifact Registry:
skaffold build \ --default-repo=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY \ --file-output=artifacts.json \ --interactive=false \ --push=true \ --update-check=false
此命令使用以下标志:
--file-output
标志指定 Skaffold 用于保存有关构建映像的信息(包括摘要值)的文件。--push
标志指示 Skaffold 将构建的映像推送到由--default-repo
标志指定的容器映像注册表。--interactive
和--update-check
标志均设置为false
。在非交互式环境(如构建流水线)中,将这些标志设置为false
;对于本地开发,请将这些标志保留为默认值(两个标志均为true
)。
如果您使用 Cloud Deploy 部署到 GKE,请在创建版本时使用
--file-output
标志中的文件作为--build-artifacts
标志的值。使用上一步中的容器映像的名称、标记和摘要渲染展开的 Kubernetes 清单:
skaffold render \ --build-artifacts=artifacts.json \ --digest-source=none \ --interactive=false \ --offline=true \ --output=rendered.yaml \ --update-check=false
此命令使用以下标志:
--build-artifacts
标志引用上一步中skaffold build
命令的输出文件。--digest-source=none
标志表示 Skaffold 使用--build-artifacts
标志提供的文件中的摘要值,而不是解析容器映像注册表中的摘要。--offline=true
标志表示您可以在无需访问 Kubernetes 集群的情况下运行该命令。--output
标志指定渲染的清单的输出文件。
查看呈现的清单:
cat rendered.yaml
输出类似以下内容:
apiVersion: v1 kind: Pod metadata: name: getting-started spec: containers: - image: LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY/skaffold-example:TAG@sha256:DIGEST name: getting-started
在此输出中,您会看到以下值:
TAG
:Skaffold 分配给映像的标记。DIGEST
:映像摘要值
使用 digester
Digester 向 Kubernetes Pod 和 Pod 模板规范中的容器和 init 容器映像添加摘要。Digester 会替换使用标记的容器映像引用:
spec:
containers:
- image: gcr.io/google-containers/echoserver:1.10
对于使用映像摘要的引用,请注意以下事项:
spec:
containers:
- image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
Digester 可在 Kubernetes 集群中作为变更准入 webhook 运行,也可使用 kpt 或 kustomize 命令行工具作为客户端 KRM 函数运行。
使用 digester KRM 函数
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/digester-fn cd ~/container-image-digests-tutorial/digester-fn
下载 digester 二进制文件:
mkdir -p ${HOME}/bin export PATH=${HOME}/bin:${PATH} DIGESTER_VERSION=$(curl -sL https://api.github.com/repos/google/k8s-digester/releases/latest | jq -r .tag_name) curl -L "https://github.com/google/k8s-digester/releases/download/${DIGESTER_VERSION}/digester_$(uname -s)_$(uname -m)" --output ${HOME}/bin/digester chmod +x ${HOME}/bin/digester
使用标记
1.10
创建引用映像gcr.io/google-containers/echoserver
的 Kubernetes Pod 清单:cat << EOF > pod.yaml apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10 ports: - containerPort: 8080 EOF
使用 kpt 和当前目录 (
.
) 中的清单运行摘要 KRM 函数:kpt fn eval . --exec digester
运行此命令时,kpt 会对当前目录中的清单执行就地更新。如果您希望 kpt 在控制台中显示更新后的清单,并保持清单文件不变,请添加
--output unwrap
标志。查看更新后的清单:
cat pod.yaml
该文件如下所示:
apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 ports: - containerPort: 8080
使用 digester 准入网络钩子
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/digester-webhook cd ~/container-image-digests-tutorial/digester-webhook
使用 kind 创建本地 Kubernetes 集群:
kind create cluster
kind 是一种命令行工具,用于使用 Docker 运行本地 Kubernetes 集群。
部署 digester 网络钩子:
DIGESTER_VERSION=$(curl -sL https://api.github.com/repos/google/k8s-digester/releases/latest | jq -r .tag_name) kustomize build "https://github.com/google/k8s-digester.git/manifests?ref=${DIGESTER_VERSION}" | kubectl apply -f -
在种类集群中创建一个名为
digester-demo
的 Kubernetes 命名空间:kubectl create namespace digester-demo
将
digest-resolution: enabled
标签添加到digester-demo
命名空间:kubectl label namespace digester-demo digest-resolution=enabled
Digester 网络钩子会将摘要添加到带有此标签的命名空间中的 pod。
使用标记
1.10
创建引用映像gcr.io/google-containers/echoserver
的 Kubernetes Deployment 清单:cat << EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: echo-deployment spec: selector: matchLabels: app: echo template: metadata: labels: app: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10 ports: - containerPort: 8080 EOF
在
digester-demo
命名空间中应用清单:kubectl apply --filename deployment.yaml --namespace digester-demo \ --output jsonpath='{.spec.template.spec.containers[].image}{"\n"}'
--output
标志指示kubectl
将映像名称输出到控制台,后跟换行符。输出如下所示:gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
此输出表明 digester 网络钩子将映像摘要添加到了 Deployment 资源中的 Pod 模板规范。
删除种类集群以释放 Cloud Shell 会话中的资源:
kind delete cluster
使用 kpt setter
kpt 是一个命令行工具,用于管理、操作、自定义和应用 Kubernetes 资源清单。
您可以在构建新映像时使用 kpt Functions 目录中的 create-setters
和 apply-setters
KRM 函数更新 Kubernetes 清单中的映像摘要。
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/kpt cd ~/container-image-digests-tutorial/kpt
在当前目录中创建 kpt 软件包:
kpt pkg init --description "Container image digest tutorial"
使用标记
1.10
创建引用映像gcr.io/google-containers/echoserver
的 Kubernetes Pod 清单:cat << EOF > pod.yaml apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10 ports: - containerPort: 8080 EOF
使用 kpt 为清单字段创建一个名为
echoimage
的 setter,现有值为gcr.io/google-containers/echoserver:1.10
:kpt fn eval . \ --image gcr.io/kpt-fn/create-setters@sha256:0220cc87f29ff9abfa3a3b5643aa50f18d355d5e9dc9e1f518119633ddc4895c \ -- "echoimage=gcr.io/google-containers/echoserver:1.10"
查看清单:
cat pod.yaml
该文件如下所示:
apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10 # kpt-set: ${echoimage} ports: - containerPort: 8080
获取容器映像的摘要值:
DIGEST=$(gcloud container images describe \ gcr.io/google-containers/echoserver:1.10 \ --format='value(image_summary.digest)')
设置新字段值:
kpt fn eval . \ --image gcr.io/kpt-fn/apply-setters@sha256:4d4295727183396f0c3c6a75d2560254c2f9041a39e95dc1e5beffeb49cc1a12 \ -- "echoimage=gcr.io/google-containers/echoserver:1.10@$DIGEST"
运行此命令时,kpt 将就地替换清单中的
image
字段值。查看更新后的清单:
cat pod.yaml
该文件如下所示:
apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 # kpt-set: ${echoimage} ports: - containerPort: 8080
使用 kustomize 映像转换器
kustomize 是一个命令行工具,可让您使用叠加层、补丁程序和转换器自定义 Kubernetes 清单。
您可以使用 kustomize 映像转换器来更新现有清单中的映像名称、标记和摘要。
以下 kustomization.yaml
代码段介绍如何将映像转换器配置为将转换器 digest
值用于映像,这些映像中的 Pod 规范 image
值与转换器 name
值匹配:
images: - name: gcr.io/google-containers/echoserver digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
如需使用含有映像摘要的映像转换器,请执行以下操作:
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/kustomize cd ~/container-image-digests-tutorial/kustomize
创建
kustomization.yaml
文件:kustomize init
通过使用标记
1.10
引用映像gcr.io/google-containers/echoserver
的 Pod 规范创建一个 Kubernetes 清单:cat << EOF > pod.yaml apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10 ports: - containerPort: 8080 EOF
将清单作为资源添加到
kustomization.yaml
文件中:kustomize edit add resource pod.yaml
使用映像转换器更新映像的摘要:
kustomize edit set image \ gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229
在
kustomization.yaml
文件中查看映像转换器:cat kustomization.yaml
该文件如下所示:
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - pod.yaml images: - digest: sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 name: gcr.io/google-containers/echoserver
查看生成的清单:
kustomize build .
输出如下所示:
apiVersion: v1 kind: Pod metadata: name: echo spec: containers: - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 name: echoserver ports: - containerPort: 8080
如需在一个步骤中运行 kustomize 转换器并将生成的清单应用于 Kubernetes 集群,您可以使用带有
--kustomize
标志的kubectl apply
命令:kubectl apply --kustomize .
如果您之后要应用输出,可以将
kustomize build
命令的输出重定向到一个文件。
使用 gke-deploy
gke-deploy
是一个与 Google Kubernetes Engine (GKE) 搭配使用的命令行工具。gke-deploy
封装了 kubectl
命令行工具,并且可以修改您按照 Google 推荐的做法创建的资源。
如果您使用 gke-deploy
子命令 prepare
或 run
,gke-deploy
会默认将您的映像标记解析为摘要并使用映像摘要将展开后的清单保存到文件 output/expanded/aggregated-resources.yaml
。
您可以使用 gke-deploy run
将映像标记替换为摘要,并将展开的清单应用于 GKE 集群。虽然此命令使用方便,但存在一个缺点:映像标记会在部署时被替换。与标记关联的映像可能会在您决定部署与部署之间发生更改,导致部署异常映像。对于生产部署,我们建议将生成和应用清单步骤分开执行。
如需使用映像摘要替换 Kubernetes 部署清单中的映像标记,请执行以下操作:
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/gke-deploy cd ~/container-image-digests-tutorial/gke-deploy
安装
gke-deploy
:go install github.com/GoogleCloudPlatform/cloud-builders/gke-deploy@latest
使用标记
1.10
创建引用映像gcr.io/google-containers/echoserver
的 Kubernetes Deployment 清单:cat << EOF > deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: echo-deployment spec: selector: matchLabels: app: echo template: metadata: labels: app: echo spec: containers: - name: echoserver image: gcr.io/google-containers/echoserver:1.10 ports: - containerPort: 8080 EOF
根据
deployment.yaml
清单生成展开的清单:gke-deploy prepare \ --filename deployment.yaml \ --image gcr.io/google-containers/echoserver:1.10 \ --version 1.10
查看展开的清单:
cat output/expanded/aggregated-resources.yaml
输出如下所示:
apiVersion: apps/v1 kind: Deployment metadata: labels: app.kubernetes.io/managed-by: gcp-cloud-build-deploy app.kubernetes.io/version: "1.10" name: echo-deployment namespace: default spec: selector: matchLabels: app: echo template: metadata: labels: app: echo app.kubernetes.io/managed-by: gcp-cloud-build-deploy app.kubernetes.io/version: "1.10" spec: containers: - image: gcr.io/google-containers/echoserver@sha256:cb5c1bddd1b5665e1867a7fa1b5fa843a47ee433bbb75d4293888b71def53229 name: echoserver ports: - containerPort: 8080
在展开的清单中,映像标记会被替换为摘要。
与
gke-deploy
命令结合使用的--version
参数会设置部署中app.kubernetes.io/version
标签的值以及扩展清单的 Pod 模板元数据。如需了解如何将
gke-deploy
与 Cloud Build 结合使用,请参阅gke-deploy
的 Cloud Build 文档。
使用 ko
ko
是一种命令行工具和库,用于构建 Go 容器映像并将其部署到 Kubernetes 集群。ko
可以在不使用 Docker 守护程序的情况下构建映像,以便您可以在无法安装 Docker 的环境中使用映像。
ko
子命令 build
会构建映像并将其发布到容器映像注册表或将其加载到本地 Docker 守护程序。
ko
子命令 resolve
会执行以下操作:
- 通过在 Kubernetes 清单的
image
字段中查找您使用--filename
参数提供的占位符来找到要构建的映像。 - 构建和发布映像。
- 将
image
值占位符替换为所构建映像的名称和摘要。 - 输出展开的清单。
ko
子命令 apply
、create
和 run
会执行与 resolve
相同的步骤,然后使用展开的清单执行 kubectl apply
、create
或 run
。
如需通过 Go 源代码构建映像,并将映像摘要添加到 Kubernetes 部署清单,请执行以下操作:
在 Cloud Shell 中,创建并转到用于存储您在本部分创建的文件的目录:
mkdir -p ~/container-image-digests-tutorial/ko cd ~/container-image-digests-tutorial/ko
下载
ko
并将其添加到您的PATH
:mkdir -p ${HOME}/bin export PATH=${HOME}/bin:${PATH} KO_VERSION=$(curl -sL https://api.github.com/repos/ko-build/ko/releases/latest | jq -r .tag_name | cut -c2-) curl -L "https://github.com/ko-build/ko/releases/download/v${KO_VERSION}/ko_${KO_VERSION}_$(uname -s)_$(uname -m).tar.gz" | tar -zxC ${HOME}/bin ko
在名为
app
的新目录中创建模块名称为example.com/hello-world
的 Go 应用:mkdir -p app/cmd/ko-example cd app go mod init example.com/hello-world cat << EOF > cmd/ko-example/main.go package main import "fmt" func main() { fmt.Println("hello world") } EOF
定义
ko
用于发布映像的映像代码库:export KO_DOCKER_REPO=LOCATION-docker.pkg.dev/PROJECT_ID/REPOSITORY
此示例使用 Artifact Registry,但您可以将
ko
与其他容器映像注册表结合使用。如需为您的应用构建和发布映像,请执行以下步骤之一:
通过提供 Go 主软件包的路径,为应用构建并发布映像:
ko build --base-import-paths ./cmd/ko-example
可选参数
--base-import-paths
表示ko
使用主软件包目录的短名称作为映像名称。ko
采用以下格式将映像名称和摘要输出到stdout
:LOCATION-docker.pkg.dev/PROJECT_ID/ko-example@sha256:DIGEST
在此输出中,
DIGEST
是映像摘要值。使用
ko
将清单占位符替换为其构建并发布的映像的名称和摘要:创建 Kubernetes pod 清单。清单使用占位符
ko://IMPORT_PATH_OF_YOUR_MAIN_PACKAGE
作为image
字段的值:cat << EOF > ko-pod.yaml apiVersion: v1 kind: Pod metadata: name: ko-example spec: containers: - name: hello-world image: ko://example.com/hello-world/cmd/ko-example EOF
为应用构建和发布映像,并将清单占位符替换为映像名称和摘要:
ko resolve --base-import-paths --filename ko-pod.yaml
ko
会将包含映像名称和清单的摘要输出到stdout
:apiVersion: v1 kind: Pod metadata: name: ko-example spec: containers: - name: hello-world image: LOCATION-docker.pkg.dev/PROJECT_ID/ko-example@sha256:DIGEST
在此输出中,
DIGEST
是映像摘要值。
清理
避免产生费用的最简单方法是删除您为本教程创建的 Google Cloud 项目。或者,您也可以删除各个资源。
删除项目
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
删除资源
如果您希望保留在本教程中使用的 Google Cloud 项目,请删除单个资源:
在 Cloud Shell 中,删除您在本教程中创建的文件:
cd rm -rf ~/container-image-digests-tutorial
删除 Artifact Registry 中的容器映像制品库:
gcloud artifacts repositories delete REPOSITORY \ --location=LOCATION --async --quiet