将自定义映像导出到 Cloud Storage

如需将 Compute Engine 启动磁盘数据移出 Compute Engine 项目,您可以将启动磁盘映像以 tar.gz 文件导出到 Cloud Storage。如需在 Compute Engine 上创建新的永久性磁盘时创建要使用的永久性磁盘映像,请参阅创建自定义映像

您可以通过将自定义映像导出到 Cloud Storage 来备份或共享该映像。如果您需要与无法访问您的映像的项目共享个别映像,此方法非常适合。您也可以选择通过在映像上或其所属的项目上授予 Compute Engine 映像用户角色来共享映像。

下图显示了创建和重用自定义映像的一些典型工作流程。

创建和重用自定义映像。
图 1.自定义映像的创建和重用示例

准备工作

启用 Cloud Build API

虚拟设备导出工具使用 Cloud Build

在大多数情况下,gcloud compute images export 会尝试将这些权限授予 Cloud Build 服务帐号。不过,您可以手动授予这些权限,以确保所需权限已生效。

控制台

  1. 在 Google Cloud Console 中,启用 Cloud Build API。

    启用 Cloud Build API

    通过控制台启用 Cloud Build API 时,Compute Engine 会向 Cloud Build 服务帐号授予以下角色,以便 Cloud Build 服务可以从 Compute Engine 中导出实例:

    • roles/iam.serviceAccountTokenCreator
    • roles/compute.admin
    • roles/iam.serviceAccountUser

    导出工具还会使用默认的 Compute Engine 服务帐号。默认情况下,Compute Engine 服务帐号具有 Cloud IAM Project Editor 角色。如果移除此角色,导出过程可能会失败。如需将该角色添加回服务帐号,请参阅授予访问权限。 如需详细了解 Compute Engine 默认服务帐号,请参阅 Compute Engine 默认服务帐号

gcloud

如需使用 gcloud 命令行工具设置 Cloud Build 服务,请完成以下步骤:

  1. 通过 gcloud 命令行工具启用 Cloud Build。

    gcloud services enable cloudbuild.googleapis.com

    导出工具还会使用默认的 Compute Engine 服务帐号。默认情况下,Compute Engine 服务帐号具有 Cloud IAM Project Editor 角色。如果移除此角色,导出过程可能会失败。如需将该角色添加回服务帐号,请参阅授予访问权限。 如需详细了解 Compute Engine 默认服务帐号,请参阅 Compute Engine 默认服务帐号

  2. compute.admin 角色添加到 Cloud Build API 服务帐号。

    gcloud projects add-iam-policy-binding project-id \
       --member serviceAccount:project-num@cloudbuild.gserviceaccount.com \
       --role roles/compute.admin
    
  3. iam.serviceAccountUser 角色添加到 Cloud Build API 服务帐号。

    gcloud projects add-iam-policy-binding project-id \
       --member serviceAccount:project-num@cloudbuild.gserviceaccount.com \
       --role roles/iam.serviceAccountUser
    
  4. iam.serviceAccountTokenCreator 角色添加到 Cloud Build API 服务帐号。

    gcloud projects add-iam-policy-binding project-id \
       --member serviceAccount:project-num@cloudbuild.gserviceaccount.com \
       --role roles/iam.serviceAccountTokenCreator
    

    替换以下内容:

使用单个命令导出映像

控制台

  1. 在 Google Cloud Console 中,转到映像页面。

    转到映像页面

  2. 点击要导出的映像的名称,以转到映像详情页面。您无法导出 Google 提供的公共映像。您只能导出之前创建或导入的映像。

  3. 在映像详情页面中,点击导出以打开导出映像页面。

  4. 导出映像页面上,选择映像的导出格式

  5. 点击浏览以选择导出映像的目标 Cloud Storage 位置。

  6. 选择现有 Cloud Storage 位置以导出映像。或者,按照说明创建新的 Cloud Storage 存储分区,然后输入新 Cloud Storage 存储分区的名称。

  7. 选择 Cloud Storage 后,请为导出的映像选择一个文件名。您可以使用默认文件名,也可以选择自己的文件名。

  8. 选择 Cloud Storage 并为映像输入文件名后,点击选择

  9. 导出映像页面中,点击导出。选择导出后,Cloud Console 将显示映像导出历史记录,您可以在其中查看映像导出过程。如需详细了解映像导出过程,请点击 Cloud Build ID 以转到映像导出详情页面,您可以在其中查看和下载映像导出日志。

  10. 转到 Storage 以访问导出的映像。

    转到 Storage 页面

gcloud

如需将映像导出到 Cloud Storage,首选方法是使用 gcloud compute images export 命令。此命令使用 Daisy 将导出映像所需的多个步骤串联起来。此命令假定您已经创建了一个映像(例如,使用 gcloud compute images create 命令创建了映像)。

gcloud 命令行工具中,运行以下命令:

gcloud compute images export \
    --destination-uri destination-uri \
    --image image-name

替换以下内容:

  • destination-uri:导出的虚拟磁盘文件的目标 Cloud Storage URI。
  • image-name:要导出的磁盘映像的名称。

例如,以下命令会将名为 my-image 的映像从 my-project 导出到名为 my-bucket 的 Cloud Storage 存储分区。默认情况下,映像将以 disk.raw 文件的形式导出并压缩为 tar.gz 文件格式。

gcloud compute images export \
    --destination-uri gs://my-bucket/my-image.tar.gz \
    --image my-image \
    --project my-project

如需了解所有可用的标志,请参阅 gcloud compute images export 参考文档。

API

在 API 中,创建一个指向 Cloud Build API 的 POST 请求。

POST https://cloudbuild.googleapis.com/v1/projects/project-id/builds
{
  "timeout":"timeout",
  "steps":[
    {
      "args":[
        "-timeout=timeout",
        "-source_image=source-image",
        "-client_id=api",
        "-format=image-format",
        "-destination_uri=destination-uri"
      ],
      "name":"gcr.io/compute-image-tools/gce_vm_image_export:release",
      "env":[
        "BUILD_ID=$BUILD_ID"
      ]
    }
  ],
  "tags":[
    "gce-daisy",
    "gce-daisy-image-export"
  ]
}

替换以下内容:

  • project-id:要导出的映像所属项目的 ID。
  • timeout:构建作业在失败并发送 TIMEOUT 消息前应持续的最长时间。在 API 中,该时间必须以秒为单位指定。超时值 7200s 适用于大多数情况。
  • source-image:要导出的映像的名称。
  • image-format:所导出映像的格式。有效格式包括 vmdkvhdxvpcvdiqcow2
  • destination-uri:您要将虚拟磁盘文件导出到的 Cloud Storage URI 目标位置。例如 gs://my-bucket/my-exported-image.vmdk

如需查看可提供的其他 args 值,请参阅虚拟机映像导出 GitHub 页面的“可选标志”部分。

示例响应

以下示例响应类似于返回的输出:

{
"name": "operations/build/myproject-12345/operation-1578608233418",
"metadata": {
 "@type": "type.googleapis.com/google.devtools.cloudbuild.v1.BuildOperationMetadata",
 "build": {
  "id": "3a2055bc-ccbd-4101-9434-d376b88b8940",
  "status": "QUEUED",
  "createTime": "2019-10-02T18:59:13.393492020Z",
  "steps": [
   {
    "name": "gcr.io/compute-image-tools/gce_vm_image_export:release",
    "env": [
     "BUILD_ID=3a2055bc-ccbd-4101-9434-d376b88b8940"
    ],
    "args": [
     "-timeout=7056s",
     "-source_image=my-image",
     "-client_id=api",
     "-format=vmdk",
     "-destination_uri=gs://my-bucket/my-exported-image.vmdk"
    ]
   }
  ],
  "timeout": "7200s",
  "projectId": "myproject-12345",
  "logsBucket": "gs://123456.cloudbuild-logs.googleusercontent.com",
  "options": {
   "logging": "LEGACY"
  },
  "logUrl": "https://console.cloud.google.com/gcr/builds/3a2055bc-ccbd-4101-9434-d376b88b8940?project=123456"
 }
 }

您可以通过以下几种方式监控您的版本:

  • 使用返回的 build-id 运行 projects.builds.get 请求。
  • 查看在提供的 logUrl 下托管的日志。

手动创建和导出映像

如果 gcloud compute images creategcloud compute images export 命令不符合您的要求,您可以在 Compute Engine 实例中手动创建和导出映像。此过程包含多个独立步骤,您可以先创建一个映像,然后导出一个映像。

在以下示例中,请注意创建的磁盘名为 image-disk

要创建和导出映像,请执行以下操作:

  1. (可选)在创建快照之前,先停止挂接了磁盘的实例。停止实例可确保快照中磁盘内容的完整性。 将 disk-name 替换为要用于创建快照的磁盘的名称。

  2. 创建磁盘的快照,将该快照命名为 image-snapshot

    gcloud compute disks snapshot disk-name \
        --snapshot-names image-snapshot
  3. 通过运行以下命令,使用 image-snapshot 快照创建一个名为 image-disk 的新磁盘:

    gcloud compute disks create image-disk \
        --source-snapshot image-snapshot
  4. 创建一个临时磁盘 temporary-disk 来保存 tar 文件,并将该磁盘的 size 指定为至少比映像磁盘大 50%。

    之后,您可以分离并删除磁盘。

    gcloud compute disks create temporary-disk \
        --size size

    其中,size 是临时磁盘的大小(以千兆字或太字节为单位)。例如,指定 100GB 可创建一个 100 千兆字节的磁盘。

  5. 创建实例并在实例上启用 storage-rw 范围。另外,将 image-disktemporary-disk 挂接到实例,以作为具有特定 device-name 属性的辅助磁盘。将 instance-name 替换为要创建的实例的名称。

    gcloud compute instances create instance-name \
        --scopes storage-rw \
        --disk name=image-disk,device-name=image-disk \
        --disk name=temporary-disk,device-name=temporary-disk

    请注意,您正在传入服务帐号范围,以便在后续步骤中将文件上传到 Cloud Storage。

    如有必要,请查看有关启动新实例的详情。

  6. 连接到您的实例。 将 instance-name 替换为要连接的实例的名称。

    gcloud compute ssh instance-name
  7. 格式化并装载临时磁盘。格式化磁盘将删除临时磁盘的内容。

    sudo mkdir /mnt/tmp
    sudo mkfs.ext4 -F /dev/disk/by-id/google-temporary-disk
    sudo mount -o discard,defaults /dev/disk/by-id/google-temporary-disk /mnt/tmp
  8. (可选)在创建 tar 文件之前,您可以装载映像磁盘并进行其他更改。例如,如果您不希望任何现有的文件包含在映像中,可从 /home 目录中删除这些文件。装载需要修改的磁盘分区,修改磁盘上需要更改的文件,然后在完成这些操作后卸载磁盘。

    1. 创建一个可以装载磁盘或分区的目录。

      sudo mkdir /mnt/image-disk
    2. 使用 ls 命令确定您需要装载的具体磁盘或磁盘分区。

      ls /dev/disk/by-id/

      该命令会输出磁盘 ID 和分区的列表。例如,以下磁盘具有一个分区表,其中包含一个分区。google-image-disk ID 指向您要从中创建映像的完整磁盘,而 google-image-disk-part1 ID 指向该磁盘上的第一个分区。如果需要更改磁盘,请装载分区,然后从完整磁盘创建映像。

      google-image-disk
      google-image-disk-part1
      
    3. 装载磁盘或分区。如果您的磁盘具有分区表,请装载磁盘的各个分区。例如,装载 google-image-disk-part1

      sudo mount /dev/disk/by-id/google-image-disk-part1 /mnt/image-disk

      或者,如果您的磁盘采用了 raw 格式,并且没有分区表,请装载完整的 google-image-disk 磁盘。

      sudo mount /dev/disk/by-id/google-image-disk /mnt/image-disk
    4. 修改 /mnt/image-disk 目录中的文件以配置磁盘上的文件。例如,您可以移除 /mnt/image-disk/home/[USER]/.ssh/authorized_keys 文件以保护您的 SSH 密钥不被共享。

    5. 修改完文件之后,卸载磁盘。

      sudo umount /mnt/image-disk/
  9. 为您的映像创建一个 tar 文件。

    完成对映像磁盘上的文件的自定义操作后,请在临时磁盘上创建原始磁盘文件。请注意,该原始磁盘映像的名称必须为“disk.raw”,如下所示:

     sudo dd if=/dev/disk/by-id/google-image-disk of=/mnt/tmp/disk.raw bs=4096

    然后对此文件执行 tar 和 gzip 操作,如下所示:

    cd /mnt/tmp

    sudo tar czvf myimage.tar.gz disk.raw

    此命令会在以下位置创建实例的映像:

    /mnt/tmp/myimage.tar.gz

  10. 将映像上传到 Cloud Storage。

    要将 tar 文件上传到 Cloud Storage,请使用预安装在您的实例上的 gsutil 命令行工具。

    1. 使用 gsutil 创建存储分区。

      在创建存储分区之前,请务必查看存储分区和对象命名准则。然后,使用以下命令创建您的存储分区:将 bucket-name 替换为要创建的存储分区的名称。

      me@example-instance:~$ 
      gsutil mb gs://bucket-name
    2. 将您的文件复制到新的存储分区中。将 bucket-name 替换为要将文件复制到其中的存储分区的名称。

      me@example-instance:~$ 
      gsutil cp /mnt/tmp/myimage.tar.gz gs://bucket-name

您已将您的文件导出到 Cloud Storage。现在,您可以与其他人共享映像,或使用 tar 文件将新映像添加到 Google Cloud Console 项目。

后续步骤