如何通过更新容器映像将容器部署到gce?

时间:2020-05-30 13:48:46

标签: docker google-cloud-platform google-compute-engine

我使用以下命令设置CD,以将容器部署到gce:

gcloud compute instances stop my-awesome-app
gcloud compute instances update my-awesome-app --no-shielded-integrity-monitoring
gcloud beta compute instances update-container my-awesome-app --container-image=docker.io/my-docker-hub-user/my-awesome-app:${IMAGE_TAG}
gcloud compute instances start my-awesome-app

然后实例将停止,替换容器映像并启动。

如果我使用最新的图像创建新实例,则一切正常。

如果我使用CD流水线进行部署,则实例始终会永远挂起(在收到启动事件之后,就不会再有新的日志记录了),永远不会拉出新映像,并且永远不会启动并运行。

任何人都可以告诉我这是什么问题?

3 个答案:

答案 0 :(得分:3)

我不会启动和停止实例来更新容器。我只是:

gcloud compute instances update-container $instanceName2 --zone $instanceZone --container-image $registry:$BUILD_ID

但是在提取新映像之前,我总是进行docker prune以避免磁盘上充满映像:

gcloud compute ssh $instanceName2 --zone $instanceZone --command 'docker system prune -f -a'

对我来说,更好的方法是使用指向我的存储库的模板,然后从该模板中构建一个Managed-Instance-group。这样,您可以将零停机时间部署为零,而一台计算机仍可以在99%的时间内运行。 Details

答案 1 :(得分:1)

我希望文档[1]对您有所帮助,从那里您可以执行一些步骤来更新Google Cloud中VM上的容器。

要更新运行容器的VM时,Compute Engine执行以下两个步骤:

  1. 更新实例上的容器声明。 Compute Engine将更新的容器声明存储在gce-container-declaration元数据键下的实例元数据中。
  2. 如果实例正在运行,则停止并重新启动该实例以激活更新的配置。如果实例已停止,则更新容器声明并保持实例停止。 VM实例下载新映像并在VM启动时启动容器。

请按照文档[1]的1-5步进行操作,Compute Engine将保存更改并自动重新启动实例以进行更新。 VM重新启动后,它将下载新映像并使用更新后的配置启动容器。

[1] https://cloud.google.com/compute/docs/containers/deploying-containers#updating_a_container_on_a_vm_instance

答案 2 :(得分:0)

感谢上述回答!

我终于想出了自己的方式。 1.每个部署将使用容器创建一个新的托管实例。 2.然后,我保留的IP地址指向新实例。 (因此我不需要更新DNS) 3.最后,在可能的情况下关闭旧的部署。

不利之处显然是部署期间会出现停机时间,但是我认为部署管道对于我当前的项目已经足够了。

# install dependencies
apt-get --yes install jq

# Create new instance
NEW_INSTANCE="$INSTANCE_NAME_PREFIX-build-$CIRCLE_BUILD_NUM"
gcloud beta compute instances create-with-container "$NEW_INSTANCE" \
    --machine-type=f1-micro \
    --container-image=docker.io/xxx/yyy:$IMAGE_TAG \
    --container-env="ANSIBLE_VAULT_PASSWORD=${ANSIBLE_VAULT_PASSWORD}" \
    --tags http-server,https-server \
    --zone ${GOOGLE_COMPUTE_ZONE}

IP_ADDRESS=$(gcloud compute addresses list --filter="name=('$RESERVED_IP_NAME')" --format=json | jq '.[0].address' --raw-output)
OLD_INSTANCE=$(gcloud compute instances list --filter="EXTERNAL_IP=('$IP_ADDRESS')" --zones asia-east1-a --format=json | jq '.[0].name' --raw-output)

# Remove ephemeral IP address from new instance
echo "Removing ephemeral IP address from instance: $NEW_INSTANCE"
gcloud compute instances delete-access-config "$NEW_INSTANCE" \
    --access-config-name "external-nat" \
    --zone ${GOOGLE_COMPUTE_ZONE}

# Remove reserved IP address from old instance
# Ignore error if there is no access config present
if [ "$OLD_INSTANCE" != "null" ]; then
    echo "Removing reserved IP address from instance: $OLD_INSTANCE"
    gcloud compute instances delete-access-config "$OLD_INSTANCE" \
        --access-config-name "external-nat" \
        --zone ${GOOGLE_COMPUTE_ZONE} || true
fi

# Assign reserved IP address to new instance
gcloud compute instances add-access-config "$NEW_INSTANCE" \
    --access-config-name "external-nat" --address "$IP_ADDRESS" \
    --zone ${GOOGLE_COMPUTE_ZONE}

# Shutdown old instance
if [ "$OLD_INSTANCE" != "null" ]; then
    gcloud compute instances stop "$OLD_INSTANCE" --zone ${GOOGLE_COMPUTE_ZONE}
fi