gcloud app deploy 不会删除以前的版本

Posted

技术标签:

【中文标题】gcloud app deploy 不会删除以前的版本【英文标题】:gcloud app deploy does not remove previous versions 【发布时间】:2017-09-11 19:49:21 【问题描述】:

我正在 Google App Engine 上运行 Node.js 应用,使用以下命令部署我的代码:

gcloud app deploy --stop-previous-version

我希望的行为是终止运行先前版本的所有实例,但它们似乎总是存在。我有什么遗漏吗?

我意识到他们没有收到流量,但我仍在为他们付费,而且他们会产生一些背景遥测噪音。有没有更好的方法来运行这个命令?

gcloud app instances list 的示例输出: 如您所见,我运行了两个不同的版本。

【问题讨论】:

根据您的信息很难准确判断问题出在哪里。 【参考方案1】:

这是我的其他主要答案之外的补充和可选答案。

我现在除了我的其他答案外,还使用脚本在部署时手动自动递增版本。

我的脚本内容如下。

基本上,每次部署时脚本都会自动增加版本。我使用的是 node.js,所以脚本使用 npm version 来提升版本,但这条线可以很容易地调整为您使用的任何语言。

脚本需要一个干净的 git 工作目录进行部署。

脚本假定当版本被碰撞时,这将导致需要推送的文件更改(例如更改为package.json 版本)。

该脚本本质上是尝试查找您的 SSH 密钥,如果找到,它会启动一个 SSH 代理并使用您的 SSH 密钥来 git commit 和 git push 文件更改。否则它只是做一个 git 提交而不需要推送。

然后它使用 --version 标志进行部署 ...--version="$deployVer"

认为这可能会对某人有所帮助,尤其是因为最佳答案谈到了很多关于在部署中使用 --version flag 的内容。

#!/usr/bin/env bash

projectName="vehicle-damage-inspector-app-engine"

# Find SSH key

sshFile1=~/.ssh/id_ed25519
sshFile2=~/Desktop/.ssh/id_ed25519
sshFile3=~/.ssh/id_rsa
sshFile4=~/Desktop/.ssh/id_rsa

if [ -f "$sshFile1" ]; then
  sshFile="$sshFile1"
elif [ -f "$sshFile2" ]; then
  sshFile="$sshFile2"
elif [ -f "$sshFile3" ]; then
  sshFile="$sshFile3"
elif [ -f "$sshFile4" ]; then
  sshFile="$sshFile4"
fi

# If SSH key found then fire up SSH agent

if [ -n "$sshFile" ]; then

  pub=$(cat "$sshFile.pub")
  for i in $pub; do email="$i"; done
  name="Auto Deploy $projectName"

  git config --global user.email "$email"
  git config --global user.name "$name"

  echo "Git SSH key = $sshFile"
  echo "Git email = $email"
  echo "Git name = $name"

  eval "$(ssh-agent -s)"
  ssh-add "$sshFile" &>/dev/null
  sshKeyAdded=true
fi

# Bump version and git commit (and git push if SSH key added) and deploy

if [ -z "$(git status --porcelain)" ]; then

  echo "Working directory clean"

  echo "Bumping patch version"
  ver=$(npm version patch --no-git-tag-version)

  git add -A
  git commit -m "$projectName version $ver"

  if [ -n "$sshKeyAdded" ]; then
    echo ">>>>> Bumped patch version to $ver with git commit and git push"
    git push
  else
    echo ">>>>> Bumped patch version to $ver with git commit only, please git push manually"
  fi

  deployVer="$ver//"."/"-""

  gcloud app deploy --quiet --promote --stop-previous-version --version="$deployVer"

else
  echo "Working directory unclean, please commit changes"
fi

对于 node.js 用户,如果你调用脚本 deploy.sh 你应该添加:

"deploy": "sh deploy.sh"

在您的 package.json 脚本中并使用 npm run deploy 进行部署

【讨论】:

【参考方案2】:

我遇到了和 OP 一样的问题。在 Docker 中使用 flex 环境(其中一些也适用于标准环境)(runtime: custom in app.yaml)我终于解决了这个问题!我尝试了很多东西,但不确定是哪一个修复了它(或者它是否是一个组合),所以我将在这里列出我所做的事情,最有可能的解决方案首先列出。

解决方案 1) 确保云存储删除旧版本

云存储与什么有什么关系? (我听到你问了)

有一个小工具提示 (Google Cloud Platform Web UI (GCP) > App Engine > Versions > Size),当您将鼠标悬停在它上面时会显示:

(Google App Engine) 柔性环境代码从谷歌云存储存储和计费... yada yada yada

因此,基于此信息和this answer,我访问了GCP > Cloud Storage > Browser,发现了我的存储桶和大量我不知道存在的其他存储桶。事实证明,一些存储桶存储缓存的云功能代码,一些存储缓存的 docker 图像,还有一些存储其他缓存的代码/东西(您可以通过浏览存储桶来判断哪个是哪个)。

所以我给所有的bucket(除了云函数bucket)添加了一个删除策略如下:

转到GCP > Cloud Storage > Browser 并单击Lifecycle Rules 列中的链接(用于相关存储桶)> 单击添加规则> 那么:

对于 SELECT ACTION,选择“删除对象”并单击继续

对于 SELECT OBJECT 选择“更新版本数”并在输入中输入 1

点击创建

这将使您返回表格视图,您现在应该会在生命周期规则列中看到该规则。

对所有相关存储桶重复此过程(相关存储桶已在前面描述过)。

然后删除相关存储桶的内容。 警告:有些存储桶会警告您不要删除存储桶本身,只删除其中的内容!

现在重新部署,您的最新版本现在应该已部署,希望您再也不会遇到此问题!

解决方案 2) 使用部署标志

我添加了这些flags

gcloud app deploy --quiet --promote --stop-previous-version

这可能没有帮助,因为这些标志似乎是默认的,但值得添加以防万一。

请注意,仅对于标准环境(我听说过小道消息),您还可以使用 --no-cache 标志,这可能有助于使用 flex,但此标志会导致部署失败(当我尝试时)。

解决方案 3)

这可能根本没有帮助,但我补充说:

COPY app.yaml .

到 Dockerfile

提示 1)

这可能比修复更有用/有用的调试方法。

访问GCP > App Engine > Versions

这会显示您应用的所有版本(每个部署 1 个),还显示每个实例正在运行的版本(实例在 app.yaml 中配置)。

确保所有实例都运行最新版本。这应该默认发生。可能值得删除旧版本。

您可以从gcloud app deploy 日志(在日志开头)确定您的版本,但似乎这些版本无论如何都是按部署顺序列出的(最新的在顶部)。

提示 2)

访问GCP > App Engine > Instances

SSH 进入一个实例。这只是点击几个按钮的问题(见下面的截图)。运行 SSH 后:

docker exec -it gaeapp /bin/bash

这将使您进入运行代码的 docker 容器。现在您可以四处浏览以确保它具有您的最新代码。

嗯,我想我的答案现在已经够长了。如果这有帮助,请不要感谢我,J-ES-US 是你应该感谢的人 ;) 我属于他 ^^

【讨论】:

最后我决定将“删除对象”规则添加到所有存储桶中 值得注意的是,我现在也在使用脚本进行部署时自动递增版本 - 如果有兴趣,请参阅我的其他补充答案【参考方案3】:

据我所知,至少对于 具有自动缩放功能的标准环境,旧版本保持“服务”是正常的,尽管它们应该有零实例(即使您的缩放配置指定一个非零最小值)。至少这是我所看到的。我认为(我希望)那些旧的“服务”实例不会产生任何费用,因为计费是按实例计费的。

我知道上面的大部分答案都是针对灵活环境的,但我想我会把这个包含在此处以供有疑问的人使用。

(如果谷歌的人能确认一下就好了。)

【讨论】:

【参考方案4】:

Google 可能已更新 @IAmKale 的回答中引用的 documentation

请注意,如果该版本在自动缩放服务的实例上运行,则使用--stop-previous-version 将不起作用,并且以前的版本将继续运行,因为自动缩放服务实例始终在运行。

似乎该标志仅适用于手动扩展的服务。

【讨论】:

那是很久以前的事了,但我不相信我打开了自动缩放(至少不是故意的),我只想要一台机器。 我知道这是很久以前的事了,但如果你还记得你的实例类,它会告诉你是否启用了自动缩放。如果它以 F 开头,例如 F2,我认为很多样板代码或示例都使用它,那么它就是自动缩放。【参考方案5】:

我们在不到 30 天的时间内意外耗尽了我们的免费 G​​oogle App Engine 信用额度,因为后续部署未清除一个错误的灵活实例。当我们将其确定为原因时,它已扩展到四个基本处于闲置状态的同时实例。

tl;dr: 在部署时使用--version 标志来指定版本名称。具有相同版本的现有实例将是 替换然后下次部署。

这使我陷入了--stop-previous-version 的兔子洞。以下是我目前发现的:

--stop-previous-version 似乎不再受支持。它在gcloud app deploy reference page 的Flags 下提到,但如果您查看列出所有标志的页面顶部,则找不到它。

我尝试使用该标志集进行部署以查看会发生什么,但它似乎没有任何效果。新版本还在创建,我还是要进去手动删除旧实例。

gcloud-maven-plugin repo 上有一个开放的 Github 问题,专门将此称为该插件的问题,但该问题似乎被忽略了。

此时我们最好的选择是将--version=staging 或其他任何内容添加到gcloud deploy app。该标志的参考文档似乎表明它将替换共享该“版本”的现有实例:

--version=版本,-v 版本

此部署将创建或替换的应用版本。如果您不指定版本,则会为您生成一个。

(强调我的)

此外,Google 自己的 reference documentation on app.yaml(Python 文档的链接,但它仍然相关)特别将 --version 标志称为部署时指定版本的“首选”方式:

推荐的方法是从您的 app.yaml 文件中删除版本元素,而是使用命令行标志来指定您的版本 ID

【讨论】:

替换当前版本似乎不是一个好主意。为避免停机,您需要创建一个新版本,将流量重定向到它,然后关闭旧版本。据我所知,当您在没有 --version 的情况下运行 gcloud app deploy 时,默认情况下会发生这种情况。 我想使用相同的版本,但我想这是标准而不是 Flex 的东西:ERROR: (gcloud.app.deploy) INVALID_ARGUMENT: In place deployments of App Engine Flexible Environment over an existing version are not supported. Please use a different version name, or delete the existing version first.。知道如何在 Flex 上实现这一点吗? 版本文档 - cloud.google.com/appengine/docs/standard/python/config/…

以上是关于gcloud app deploy 不会删除以前的版本的主要内容,如果未能解决你的问题,请参考以下文章

gcloud - 错误:(gcloud.app.deploy)权限错误获取应用程序

带有Gcloud错误的Rails:(gcloud.preview.app.deploy)错误响应:[13]意外错误。部署版本:

gcloud app deploy :此部署文件过多

错误:(gcloud.app.deploy)您必须在使用自定义运行时提供自己的 Dockerfile

(gcloud.app.deploy) 错误响应:[7] 未配置访问。项目中未使用 Cloud Build

错误:(gcloud.app.deploy)错误响应:[9] Cloud build XXXXXXXXXXXX 状态:FAILURE