Google App Engine Flexible env 的定价,一节 500 美元的课程

Pricing of Google App Engine Flexible env, a $500 lesson

我遵循了 Nodejs on App Engine Flexible env 教程: https://cloud.google.com/appengine/docs/flexible/nodejs/create-app

在成功部署和测试教程后,我更改了代码进行了一些实验并成功部署了它...然后将其保留 运行 因为这是一个测试环境(不是 public ).

一个月后,我收到了 Google 的账单,金额超过 370 美元!

在交易详情中,我看到以下内容:

Oct 1 – 31, 2017 App Engine Flex Instance RAM: 5948.774 Gibibyte-hours ([MYPROJECT]) .24

Oct 1 – 31, 2017 App Engine Flex Instance Core Hours: 5948.774 Hours ([MYPROJECT]) 2.91

这个请求几乎为0的测试环境是怎么耗费了大约6000小时资源的?在最坏的情况下,我会假设每月 720 小时 运行 全职工作,每小时 0.05 美元将花费我约 40 美元。 https://cloud.google.com/appengine/pricing

有人可以帮忙解释一下吗?我还没弄明白为什么需要这么多资源?

感谢您的帮助!

更多数据,这是上个月的流量(基本为0):

和实例数据

更新: 请注意,我确实对 package.json 进行了一项修改:我将 nodemon 添加为依赖项并将其添加为我的“nmp 启动”脚本的一部分。尽管我怀疑这能否解释 6000 小时的资源:

  "scripts": {
    "deploy": "gcloud app deploy",
    "start": "nodemon app.js",
    "dev": "nodemon app js",
    "lint": "samples lint",
    "pretest": "npm run lint",
    "system-test": "samples test app",
    "test": "npm run system-test",
    "e2e-test": "samples test deploy"
  },

App.yaml(默认-与教程无变化)

runtime: nodejs
env: flex

在与 Google 多次来回讨论,以及阅读博客和查看报告数小时后,我终于找到了对发生的事情的解释。我会 post 在这里加上我的建议,这样其他人就不会成为这个问题的受害者。

请注意,这对某些人来说似乎是显而易见的,但作为一个新的 GAE 用户,所有这些对我来说都是全新的。

简而言之,当部署到 GAE 并使用以下命令“$ gcloud app deploy”时,它会创建一个新版本并将其设置为默认版本,而且还有更多重要的是,它不会删除已部署的先前版本。

有关版本和实例的更多信息可在此处找到:https://cloud.google.com/appengine/docs/standard/python/an-overview-of-app-engine

因此,在我不知情的情况下,我已经创建了我的简单节点应用程序的多个版本。这些版本仍然是 运行,以防出现错误后需要切换。但这些版本也需要实例,默认情况下,除非在 app.yaml 中说明,否则为 2 个实例。

Google 说:

App Engine by default scales the number of instances running up and down to match the load, thus providing consistent performance for your app at all times while minimizing idle instances and thus reducing cost.

然而,根据我的经验,情况并非如此。正如我之前所说,我用 nodemon 推送了我的节点应用程序,这似乎导致了错误。

最后,按照教程并没有关闭项目,我有 4 个版本,每个版本有 2 个实例 运行 全职工作 1.5 个月,服务 0 个请求并生成大量错误消息,它花了我 500 美元。

如果您仍想使用 GAE FLEX ENV,建议:

  1. 首先,设置计费预算和提醒,这样您就不会对自动记入您的 CC 的昂贵发票感到惊讶:https://cloud.google.com/billing/docs/how-to/budgets

  2. 在测试环境中,您很可能不需要多个版本,因此在部署时使用以下命令:
    $ gcloud app deploy --version v1

  3. 更新您的 app.yaml 以强制仅使用最少资源的 1 个实例:

runtime: nodejs
env: flex

# This sample incurs costs to run on the App Engine flexible environment.
# The settings below are to reduce costs during testing and are not appropriate
# for production use. For more information, see:
# https://cloud.google.com/appengine/docs/flexible/nodejs/configuring-your-app-with-app-yaml
manual_scaling:
  instances: 1
resources:
  cpu: 1
  memory_gb: 0.5
  disk_size_gb: 10
  1. 设置每日支出限额

有关详细信息,请参阅此博客 post:https://medium.com/google-cloud/three-simple-steps-to-save-costs-when-prototyping-with-app-engine-flexible-environment-104fc6736495

我希望教程中包含其中一些步骤以保护那些正在尝试学习和实验的人,但事实并非如此。

Google 如果不知道所有这些细节,App Engine Flex env 可能会很棘手。一位朋友向我推荐了 Heroku,它既有定价又有 Free/Hobby 优惠。我能够在那里快速推送一个新的节点应用程序,而且效果很好! https://www.heroku.com/pricing

学习这节课“只”花了我 500 美元,但我确实希望这能帮助其他关注 Google App Engine Flex Env​​ 的人。

另请注意,如果您仍然希望您的应用具有自动缩放功能,但您不想始终使用默认的最小 2 个实例 运行,您可以像这样配置您的 app.yaml :

runtime: nodejs
env: flex
automatic_scaling:
  min_num_instances: 1

我们部署到 GAE FE 的代码由于级联、指数级故障(退回电子邮件生成退回电子邮件等)而变得非常疯狂,我们无法关闭被窃听的 GAE 实例。 4 个多小时后,发送了 100 万封电子邮件(Mailgun 不允许我们禁用该帐户。它说“请等待 24 小时让密码更改生效”,并且撤销 API 密钥没有任何作用) ,redis VM 已停止,数据库已关闭,所有站点代码都缩减为单个“停机维护”静态 503 页面),电子邮件仍在发送。

我确定 GAE FE 只是简单地不会结束处于 CPU 负载下的 docker 虚拟机或云计算虚拟机 (redis)。也许永远不会!一旦我们真正删除了 Compute VM(而不是“仅仅”停止它),电子邮件立即停止。

但是,尽管 GAE 应用程序报告 100% 的版本和实例“已停止”,但我们的数据库继续充满“无法发送电子邮件”通知长达 2 个小时。我最终不得不更改 Google Cloud SQL 密码。

我们一直在检查账单,7 个流氓实例一直在用完 CPU 所以我们取消了该帐户上使用的卡,事实上,当账单过去时,该网站确实关闭了由于,但流氓实例也是如此。我们无法通过 GAE 电子邮件支持解决问题。


更新(2020 年 9 月 30 日):这仍然是我 22 年职业生涯中最糟糕的时刻!!整个公司的 15 名天才开发人员都不知道如何关闭 GAE。我们知道,当我的一位开发人员无法访问她的 GMail 帐户时,客户会收到数百万封电子邮件。无法拔下它,无法将其关闭。这真是一个“终结者”时刻!

如果 MailGun 允许我们实际禁用 API 访问或更改密码,除了费用之外,情况不会那么糟糕。但在 GAE 上,它在费用方面仍然很糟糕。

我不再信任我无法在其上发布 reboot 的服务器。

最后,MailGun 只收了我们 50 美元左右。然而,GAE... 如果我只是假设“好的,邮件停止了,我们可以停止”,我们可能会以 20,000 美元的超额账单告终!实际上,它“仅”花费 1,500 美元。而且我们永远无法与任何人联系以对此提出异议。所以CEO直接吃了。

如果您想降低 GAE 成本,请不要使用manual_scaling this article中的建议或已接受的答案!

GoogleApp Engine 的美妙之处在于它可以根据需要在几毫秒内扩展和缩减到数百台机器。而且您只需为 运行ning 的实例付费。

为了能够优化您的成本,您需要了解不同的扩展选项和实例类型:

1. App Engine 弹性与标准:

可以找到有关差异的详细信息 here,但与此问题相关的一个重要差异是:

[Standard is] Intended to run for free or at very low cost, where you pay only for what you need and when you need it. For example, your application can scale to 0 instances when there is no traffic.

2。缩放选项:

  • 自动缩放:Google 将根据您提供的需求和配置缩放您的应用程序。
  • 手动缩放:根本不缩放,GAE 将始终运行精确计算您要求的实例数量(极具误导性的命名)
  • 基本缩放:它会放大到你设置的限制,也会在一定时间后缩小

3。实例类型: 有 2 个 instance types,它们在启动新实例所需的时间上基本不同。 F class 个实例(用于自动缩放)可以在需要时在 ~0.1 秒内创建,B class 个实例(用于手动 scaling/basic)在 ~0.7 秒内创建:

现在您已经了解了基础知识,让我们回到已接受的答案:

manual_scaling:
  instances: 1
resources:
  cpu: 1
  memory_gb: 0.5
  disk_size_gb: 10

这指示 GAE 始终是 运行 自定义实例 class(more costly)。显然这不是最便宜的选择,因为可以使用 B1/F1 实例类型代替(它具有较低的规格)并且它也不断地 运行 宁一个实例。

什么是最便宜是在没有流量时关闭实例。如果您不介意大约 0.1 秒的启动时间,您可以改用这个:

instance_class: F1
automatic_scaling:
  max_instances: 1 (--> you can adjust this as you wish)
  min_instances: 0 (--> will scale to 0 when there is no traffic so won't incur costs)

这将在 google 提供的免费配额范围内,如果您没有任何实际流量,它不会花费您任何费用。

PS: 也强烈建议设置daily spending limit in case you forgot something running or you have some costly settings somewhere(daily spending limits are deprecated but will be available until July 24, 2021, source).

对于我不介意有一点延迟的开发环境,我使用以下设置:

instance_class: B1
basic_scaling:
  max_instances: 1
  idle_timeout: 1m

如果您使用实例的次数超过了免费后端实例限额,请试试这个:

instance_class: F1
automatic_scaling:
  max_instances: 1

它是 AppEngine 仪表板,观察实例,记下开始时间,并观察以确保在 idle_timeout 时间段过去后实例计数降为零,您会看到消息 "This version has no instances deployed".

由于没有人提到,这里是与版本相关的gcloud命令

# List all versions
$ gcloud app versions list

SERVICE  VERSION.ID       TRAFFIC_SPLIT  LAST_DEPLOYED              SERVING_STATUS
default  20200620t174631  0.00           2020-06-20T17:46:56+03:00  SERVING
default  20200620t174746  0.00           2020-06-20T17:48:12+03:00  SERVING
default  prod             1.00           2020-06-20T17:54:51+03:00  SERVING

# Delete these 2 versions (you can't delete all versions, you have to have at least one remaining)
$ gcloud app versions delete 20200620t174631 20200620t174746

# Help
$ gcloud app versions --help