迁移在创建虚拟机期间部署在虚拟机上的容器


Compute Engine 中的容器启动代理已弃用。借助此代理,您可以在创建虚拟机时在 Compute Engine 实例上部署容器。

本文档介绍了如何将启动代理在虚拟机或代管式实例组 (MIG) 上创建的现有容器迁移到其他Google Cloud 服务。

根据您的需求,选择以下选项之一,以迁移使用已弃用的方法部署在虚拟机上的容器:

  • 如果您想继续在各个虚拟机和 MIG 上运行容器,请使用启动脚本cloud-init
  • 如果您有无状态容器应用以及中小型作业,请使用 Cloud Run
  • 如果您的容器是具有明确结束状态且需要额外计算资源的批量作业,请使用 Batch
  • 如果您需要高级控制和可伸缩性,或者其他选项无法满足您的需求,请使用 GKE on Google Cloud

如需了解更多使用场景和替代解决方案,请参阅比较容器部署选项

用于在虚拟机上配置容器的已弃用选项

在创建虚拟机期间配置容器时,Compute Engine 会使用容器启动代理读取存储容器信息的 gce-container-declaration 元数据,并在虚拟机上部署容器。

以下直接在虚拟机或 MIG 上部署容器的选项(使用容器启动代理和 gce-container-metadata)已被弃用。

控制台

创建实例页面上的部署容器选项已弃用:

“部署容器”选项。

gcloud

以下用于在虚拟机或实例模板上配置容器的 gcloud 命令已被弃用:

Terraform

Terraform 模块 gce-container 和用于配置容器的 gce-container-declaration 元数据键已弃用。

确定使用已弃用的容器元数据的实例

如需确定项目中的任何实例是否使用了已弃用的容器元数据,请运行以下 Google Cloud CLI 命令,该命令会列出具有 gce-container-declaration 元数据键和值的实例:

gcloud compute instances list --filter="metadata.items.key:gce-container-declaration"

此命令会列出配置的项目中包含 gce-container-declaration 元数据键的所有虚拟机实例。元数据键可唯一标识处于弃用范围内的虚拟机。如果您使用的是多个项目,请在所有有效项目中运行此命令。

如果您有要验证的特定实例,请运行以下 Google Cloud CLI 命令:

  gcloud compute instances describe VM_NAME --format="(metadata.items)"

VM_NAME 替换为您要验证的虚拟机实例的名称。

如需详细了解如何查看元数据,请参阅查看和查询元数据

比较容器部署选项

下表总结了在虚拟机上运行容器的使用场景,并推荐了用于迁移工作负载的替代容器解决方案:

使用场景 替换类型 费用 推荐的解决方案
  • 继续在虚拟机或 MIG 上运行容器。
  • 不太熟悉无服务器或托管式解决方案。
  • 运行容器以进行测试和开发。
  • 您的工作负载包含单个虚拟机。
  • 在特权模式下运行容器。
  • 直接替换 无需支付额外费用 使用启动脚本创建虚拟机
  • 继续在虚拟机或 MIG 上运行容器。
  • 在单个虚拟机上运行多个容器。
  • 在容器或虚拟机上配置高级场景。
    例如,创建用户、导入文件、装载磁盘或使用特权模式。
  • 您的工作负载包含多个虚拟机或 MIG。
  • 直接替换 无需支付额外费用 使用 cloud-init 在虚拟机生命周期内运行任务
    运行具有明确结束状态且需要额外计算资源的批量作业。 托管式服务 取决于工作负载特征和容器配置的复杂程度。 Batch
  • 运行无状态应用。
  • 运行中小型作业。
  • 托管式服务 适用于较小工作负载的零成本或低成本解决方案。 Cloud Run
  • 您已有现有的 GKE 集群。
  • 您需要高级控制和可伸缩性。
  • 托管式服务 取决于工作负载特征和容器配置的复杂性。 Google Kubernetes Engine

    从 Compute Engine 容器启动代理转换到替代解决方案时,请考虑以下必需的更改以及实现这些更改可能需要的工作量:

    • 运行 Container-Optimized OS 的虚拟机:完全掌控虚拟机和容器运行时设置、配置、安全性和维护,这通常涉及使用启动脚本或 cloud-init 进行脚本编写。
    • Cloud Run 或 Batch:确保您的应用是无状态的,并且符合请求驱动或基于作业的执行模型。这种方法可能需要调整应用,使其能够与外部状态管理服务搭配使用。
    • GKE:采用 Kubernetes 原则,使用 Kubernetes 清单文件定义工作负载,并管理集群资源。

    使用启动脚本在虚拟机上部署容器

    您可以使用启动脚本在虚拟机上运行基本容器。

    使用启动脚本配置容器时,请考虑以下几点:

    • 您可以使用启动脚本来处理基本场景。对于高级配置,请考虑使用 cloud-init
    • 由于您要创建的新虚拟机配置了使用启动脚本的容器,因此您必须规划部署在现有虚拟机上的任何工作负载的过渡。
    • 在将流量路由到新创建的含容器的虚拟机之前,请先进行测试并确保一切按预期运行。

    如需创建虚拟机并在虚拟机或 MIG 上部署容器,请执行以下操作:

    1. 将虚拟机元数据中的当前容器映射到启动脚本命令
    2. 根据现有元数据配置创建启动脚本
    3. 使用启动脚本创建虚拟机使用启动脚本创建 MIG

    将容器元数据映射到 docker run 命令

    您可以将虚拟机元数据或 gcloud 标志映射到 docker run 实参,并将其包含在用于创建虚拟机的启动脚本中。

    部分 gcloud 标志可直接转换为虚拟机元数据。这些标志也会直接转换为 docker run 标志。如果您在虚拟机上已有容器,则可以读取虚拟机元数据配置,并使用等效的 docker run 命令构建启动脚本。

      # Get your existing VM instance configuration in yaml format
      gcloud compute instances describe VM_NAME --format="(metadata.items)"
    

    输出类似于以下内容:

      metadata:
        items:
        - key: gce-container-declaration
          value: |
            spec:
              containers:
              - args:
                - '"hello world!"'
                command:
                - echo
                env:
                - name: ONE
                  value: '1'
                image: docker.io/library/busybox
                name: my-instance
                securityContext:
                  privileged: true
                stdin: true
                tty: true
              restartPolicy: Always
        - key: google-logging-enabled
          value: 'true'
    

    使用下表将现有规范映射到 docker run 命令:

    Google Cloud CLI 标志 虚拟机元数据键 Docker run 命令
    --container-image containers.image 以不带任何标志的实参形式指定。
    例如:
    docker run gcr.io/google-containers/busybox
    --container-command command 在容器映像名称后指定为不带任何标志的实参。
    例如:
    docker run gcr.io/google-containers/busybox echo "hello world"
    --container-arg args 在命令后指定为不带任何标志的实参。
    例如:
    docker run gcr.io/google-containers/busybox echo "hello world"
    --container-env containers.env array --env KEY=VALUE [--env KEY=VALUE ...]
    --container-restart-policy restartPolicy --restart
    可能的值包括 noon-failurealways。默认值为 no
    --container-stdin containers.stdin -i
    布尔值标志,如果存在则为 true,默认为 false。
    --container-tty containers.tty -t
    布尔值标志,如果存在则为 true,默认为 false。
    --container-privileged containers.securityContext.privileged --privileged
    布尔值标志,如果存在则为 true,默认为 false。
    --container-mount-disk - 没有等效的 docker run 命令。
    您可以单独装载磁盘

    启动脚本示例

    以下示例展示了如何在启动脚本中添加 docker 命令:

    • 示例 1:在基于 Container-Optimized OS 的虚拟机中运行独立容器。
    • 示例 2:在基于 Container-Optimized OS 的虚拟机中运行 Web 服务器容器。

    示例 1

    在基于 Container-Optimized OS 的虚拟机中运行独立容器:

    #!/bin/bash
    
    # A name for the container
    CONTAINER_NAME="my-app-container"
    
    # Stop and remove the container if it exists
    docker stop $CONTAINER_NAME || true
    docker rm $CONTAINER_NAME || true
    
    # Pull the latest version of the container image from Docker Hub
    docker pull busybox:latest
    
    # Run docker container from image in docker hub
    docker run busybox:latest \
      echo "hello world!"
    

    示例 2

    在基于 Container-Optimized OS 的虚拟机中运行 Web 服务器容器:

    #!/bin/bash
    
    # Enable incoming traffic
    iptables -A INPUT -j ACCEPT
    
    # A name for the container
    CONTAINER_NAME="my-app-container"
    
    # Stop and remove the container if it exists
    docker stop $CONTAINER_NAME || true
    docker rm $CONTAINER_NAME || true
    
    # Pull the latest version of the container image from Docker Hub
    docker pull nginx:latest
    
    # Run docker container from image in docker hub
    docker run \
      --name=$CONTAINER_NAME \
      --privileged \
      --restart=always \
      --tty \
      --detach \
      --network="host" \
      nginx:latest
    

    容器部署的其他配置选项

    本部分介绍了在虚拟机上部署容器的其他配置参数。

    如需详细了解这些选项,请参阅配置选项以运行容器

    访问 Artifact Registry 映像

    如果您需要访问 gcr.io 或 pkg.dev 中的容器映像,请使用 docker-credential-gcr 工具(该工具已预安装在 Container-Optimized OS 中),并为 Docker 配置对 Artifact Registry 的身份验证。在运行容器之前,请先运行以下命令:

      # Set home directory to save docker credentials
      HOME=/home/appuser
    
      # Configure docker with credentials for gcr.io and pkg.dev
      docker-credential-gcr configure-docker
    

    如需了解详情,请参阅为 Docker 配置向 Artifact Registry 的身份验证

    配置日志记录

    我们建议在虚拟机上启用日志记录代理,以使用 Cloud Logging。

    或者,如果您想更改日志记录驱动程序,可以在 docker run 命令中添加 --log-driver 参数:

      # Use Cloud Logging logging driver
      docker run --log-driver=gcplogs nginx:latest
    

    如需了解详情,请参阅将 Cloud Logging 与 Container-Optimized OS 搭配使用

    配置内部防火墙

    Container-Optimized OS 默认拒绝入站流量,因此您必须添加 iptables 规则来允许该流量。请注意,这些命令会配置宿主操作系统的内部防火墙。此外,您还必须配置 Virtual Private Cloud 防火墙,以允许该流量流向新虚拟机

    如需了解详情,请参阅使用 VPC 防火墙规则

      # Enable all incoming and routed traffic
      iptables -A INPUT -p -j ACCEPT
      iptables -A FORWARD -p -j ACCEPT
    

    如需了解详情,请参阅配置主机防火墙

    将卷附加到容器

    如果卷已附加到容器,则容器元数据会包含 volumes 条目和 volumeMounts 数组。volumes 中条目的 name 对应于 volumeMounts 中条目的名称,反之亦然。对于您收集的每个卷,请从 volumesvolumeMounts 条目中收集所需信息。

    如果容器未挂载任何卷,您可以跳过此部分,直接使用启动脚本创建虚拟机

    如需详细了解 Container-Optimized OS 上的磁盘和文件系统,请参阅磁盘和文件系统概览

    装载 tmpfs 文件系统

    如需将空的 tmpfs 文件系统装载到容器,请在 docker run 命令中指定 --tmpfs 实参。例如,如需将缓存文件系统装载到 nginx 容器,请运行以下命令:

      # mount a cache file system to the nginx container
      docker run -d --name=$CONTAINER_NAME --tmpfs /var/cache/nginx:rw,size=512m,noexec,nosuid,nodev --network="host" nginx:latest
    

    如需详细了解如何装载 tmpfs 文件系统,请参阅 tmpfs 装载

    装载主机目录

    如需将主机虚拟机中的目录装载到容器中,请使用 docker run 命令指定 --mount 实参:

      # mount a read-only directory to the nginx container
      docker run -d --name=$CONTAINER_NAME --mount type=bind,source=/var/www/html,target=/usr/share/nginx/html,ro nginx:latest
    

    如需了解详情,请参阅绑定装载

    将永久性磁盘装载到容器

    将磁盘装载到容器需要执行额外的步骤。如需装载磁盘,请先将其装载到虚拟机上,然后再将该磁盘装载到容器:

    1. 如需将磁盘装载到虚拟机,请运行以下命令:

      #!/bin/bash
      
      DISK_DEVICE_NAME="my-persistent-disk" # This name MUST match the 'device-name' in the gcloud --disk flag
      DISK_BY_ID_PATH="/dev/disk/by-id/google-${DISK_DEVICE_NAME}"
      HOST_MOUNT_POINT="/mnt/disks/my-persistent-disk" # This is the path where the disk will be mounted on the VM
      CONTAINER_MOUNT_PATH="/usr/share/my-persistent-disk" # This is the path where the disk will be mounted in the container
      
      # format a disk as an ext4 filesystem, if it doesn't already contain one
      file -sL $DISK_BY_ID_PATH | grep -q filesystem || \
              mkfs.ext4 -m 0 -E lazy_itable_init=0,lazy_journal_init=0,discard $DISK_BY_ID_PATH
      
      # create a directory for mounting point
      sudo mkdir -p "${HOST_MOUNT_POINT}"
      
      # mount a disk to the VM
      sudo mount -o defaults,discard "${DISK_BY_ID_PATH}" "${HOST_MOUNT_POINT}"
      
    2. 将磁盘装载到虚拟机后,使用 docker run 命令添加 --mount 标志,以将磁盘装载到容器:

      docker run -d --name=$CONTAINER_NAME --mount type=bind,source="${HOST_MOUNT_POINT}",target="${CONTAINER_MOUNT_PATH}",readonly nginx:latest
      

    使用启动脚本创建虚拟机

    使用容器配置创建启动脚本后,使用此启动脚本创建基于 Container-Optimized OS 的虚拟机。如需详细了解如何基于 Container-Optimized OS 创建虚拟机,请参阅通过公共映像创建实例

    如需详细了解如何使用启动脚本,请参阅在 Linux 虚拟机上使用启动脚本

    控制台

    1. 在 Google Cloud 控制台中,前往创建实例页面。

      转到“创建实例”

      如果出现提示,请选择您的项目并点击继续。 系统会显示创建实例页面,并显示机器配置窗格。

    2. 机器配置窗格中,为虚拟机选择机器家族和机器类型。

    3. 在导航菜单中,点击操作系统和存储空间。在显示的操作系统和存储空间窗格中,执行以下操作来配置启动磁盘:

      1. 点击更改。系统会显示启动磁盘窗格,并显示公共映像标签页。
      2. 操作系统列表中,选择 Container Optimized OS
      3. 版本列表中,选择操作系统版本。
      4. 启动磁盘类型列表中,选择启动磁盘的类型。
      5. (可选)如果您需要其他磁盘,请在额外磁盘部分中添加磁盘。
      6. 点击选择
    4. 在导航菜单中,点击高级

      1. 自动化部分中,粘贴您为容器部署创建的启动脚本。
    5. 要创建并启动该虚拟机,请点击创建

    gcloud

    使用 gcloud CLI 时,请将启动脚本存储在单独的文件中。

    1. 如需使用启动脚本创建虚拟机,请运行以下命令:

      gcloud compute instances create VM_NAME \
          --zone=ZONE \
          --image-family=IMAGE_FAMILY \
          --image-project=IMAGE_PROJECT \
          --machine-type=MACHINE_TYPE \
          --metadata-from-file=startup-script=STARTUP_SCRIPT_FILE
      

      替换以下内容:

      • VM_NAME:新虚拟机的名称
      • ZONE:要创建实例的可用区。
      • IMAGE_PROJECT:包含相应映像的 Container-Optimized OS 映像项目,例如 cos-cloud
      • IMAGE_FAMILY:Container-Optimized OS 映像系列,例如 cos-stable
      • MACHINE_TYPE:新虚拟机的机器类型,可以是预定义机器类型或自定义机器类型。
      • STARTUP_SCRIPT_FILE:本地计算机上启动脚本文件的相对路径,例如 ./startup_script.sh

      示例

      # Create COS-based VM by using a startup script
      gcloud compute instances create "cos-instance-with-startup-script" \
      --zone="us-central1-c" \
      --machine-type="e2-medium" \
      --image-family="cos-stable" \
      --image-project="cos-cloud" \
      --metadata-from-file=startup-script="./startup_script.sh"
      
    2. 运行以下命令,验证 Compute Engine 是否已创建虚拟机:

      gcloud compute instances describe VM_NAME
      

      VM_NAME 替换为您创建的虚拟机的名称。

    Terraform

    如需创建虚拟机,您可以使用 google_compute_instance 资源

    provider "google" {
    project = "PROJECT_ID"
    }
    
    resource "google_compute_instance" "cos_vm_instance" {
    name         = "VM_NAME"
    machine_type = "MACHINE_TYPE"
    zone         = "ZONE"
    
    # Use a Container-Optimized OS image for the boot disk
    boot_disk {
      initialize_params {
        image = "IMAGE_PROJECT/IMAGE_FAMILY"
      }
    }
    
    # Attaches the instance to the default network
    network_interface {
      network = "default"
    }
    
    # Specify the relative path to the startup script on your local machine
    metadata = {
      startup-script = file("STARTUP_SCRIPT_FILE")
    }
    }
    

    替换以下内容:

    • VM_NAME:新虚拟机的名称
    • ZONE:要创建实例的可用区。
    • IMAGE_PROJECT:包含映像的 Container-Optimized OS 映像项目,例如 cos-cloud
    • IMAGE_FAMILY:Container-Optimized OS 映像系列,例如 cos-stable
    • MACHINE_TYPE:新虚拟机的机器类型,可以是预定义机器类型或自定义机器类型。
    • STARTUP_SCRIPT_FILE:本地计算机上启动脚本文件的相对路径,例如 ./startup_script.sh

    示例

    provider "google" {
      project = "my-project"
    }
    
    resource "google_compute_instance" "my_container_vm" {
      name = "my-container-vm-startup"
      machine_type = "e2-medium"
      zone = "us-central1-a"
    
      boot_disk {
        initialize_params {
          image = "cos-cloud/cos-stable"
        }
      }
    
      network_interface {
        network = "default"
      }
    
      metadata = {
        startup-script = file("./startup_script.sh")
      }
    }
    

    使用启动脚本创建 MIG

    使用启动脚本创建实例模板后,请使用以下方法之一创建 MIG。

    如需详细了解如何创建 MIG,请参阅创建代管式实例组

    控制台

    1. 创建实例模板,该模板基于您在上一部分中创建的启动脚本。

      1. 操作系统部分中,选择 Container Optimized OS 和版本。
      2. 自动化部分中,粘贴您为容器部署创建的启动脚本。
    2. 使用在上一步中创建的实例模板创建 MIG

    gcloud

    1. 使用 instance-templates create 命令创建实例模板

      您必须为虚拟机使用 Container-Optimized OS 映像。您可以在 --metadata-from-file 标志中指定启动脚本文件的相对路径。

    2. 使用在上一步中创建的实例模板创建 MIG

    示例

      # Create the instance template that uses a startup script
      gcloud compute instance-templates create startup-template \
          --machine-type=e2-medium \
          --image-family=cos-stable \
          --image-project=cos-cloud \
          --metadata-from-file=startup-script=./startup_script.sh
    
      # Create the managed instance group
        gcloud compute instance-groups managed create startup-mig \
          --template=startup-template \
          --size=2 \
          --zone=us-central1-a
    

    Terraform

    使用 google_compute_instance_templategoogle_compute_instance_group_manager 资源创建实例模板和 MIG,如以下示例所示:

    示例

    resource "google_compute_instance_template" "startup_template" {
      name_prefix = "startup-template-"
      machine_type = "e2-medium"
      disk {
        source_image = "cos-cloud/cos-stable"
        auto_delete  = true
        boot         = true
      }
    
      network_interface {
        network = "default"
      }
      metadata = {
        startup-script = file("./startup_script.sh")
    }
    }
    
    resource "google_compute_instance_group_manager" "startup_mig" {
      name               = "startup-mig"
      base_instance_name = "startup-vm"
      zone               = "us-central1-a"
      version {
        instance_template = google_compute_instance_template.startup_template.id
      }
      target_size = 2
    }
    

    测试和清理

    成功创建虚拟机或 MIG 后,验证您的应用是否在容器上运行并按预期工作。如需解决任何问题,请参阅问题排查

    如果应用在通过启动脚本创建的新虚拟机上成功运行,您可以删除使用已弃用的容器部署方法的虚拟机代管式实例组 (MIG)

    问题排查

    如需排查使用启动脚本在虚拟机上配置容器时可能出现的问题,请查看启动脚本日志和容器日志。

    • 如需查看虚拟机实例上的启动脚本日志,请运行以下命令:

      sudo journalctl | grep "startup script"
      
    • 如需查看 Docker 容器的日志,请运行 docker logs 命令:

      docker logs CONTAINER_NAME
      

      CONTAINER_NAME 替换为您的容器名称。

    如需排查其他问题,请参阅以下文档:

    cloud-init 与 Container-Optimized OS 搭配使用

    您可以使用 cloud-init(一种行业标准且跨平台的解决方案)在运行 Container-Optimized OS 的虚拟机上部署容器。借助此工具,您可以在虚拟机创建或启动期间运行自定义配置。如需了解详情,请参阅cloud-init 与 Cloud 配置格式搭配使用

    使用托管式服务进行容器部署

    本部分介绍了 Google Cloud 提供的可用于部署容器的代管式服务。

    Cloud Run

    Cloud Run 非常适合无状态容器应用以及中小型作业。

    Cloud Run 的主要功能包括:

    • 您可以选择仅在请求处理期间分配 CPU,也可以选择始终分配 CPU。
    • 您可以运行无状态容器应用,也可以按以下方式执行作业:作为一次性作业执行、按计划执行或在工作流中执行。
    • 您可以为每个请求或任务配置超时。
    • 它具有高度的可伸缩性和安全性。
    • 它集成了负载均衡和自动扩缩功能。

    如需详细了解如何在 Cloud Run 上部署容器,请参阅将容器映像部署到 Cloud Run

    批量

    Batch 是一项全代管式服务,可让您在 Google Cloud 资源上安排、排队和执行批处理工作负载。它专为运行批处理式、可并行化的工作负载而设计,包括封装在容器中的工作负载。

    如需详细了解如何在 Batch 上部署容器,请参阅以下文档:

    Google Kubernetes Engine

    如果您运行的是复杂的应用、微服务,需要持续运营,并且需要精细的控制和可伸缩性,那么 Google Kubernetes Engine (GKE) 是最适合您的产品。如需详细了解如何在 GKE 上部署容器,请参阅以下文档:

    获取支持

    如果您对迁移过程有任何疑问或需要帮助,请查看常见问题解答或与Google Cloud 支持团队联系。