在Google App Engine上进行持续集成/部署/交付是否太冒险了?

洛希克

我们最近在Google App Engine上设置了Node.js Web应用程序的持续集成/部署/交付。CI服务器(GitLabCI)根据分支(开发/母版)运行依赖项安装,构建,测试和部署到集成/产品。

在今天,我们面临的唯一错误是在依赖步骤中,因此我们对此并不在意。但是昨天(16/10/16),发生了大规模的DNS中断,并且在部署步骤的中间,管道发生故障,从而破坏了产品只需重新运行管道就可以完成工作,但是问题可以随时重现。

我的问题是:

  • 在持续部署过程中,我们如何处理此类网络问题?
  • 在Google App Engine上进行持续部署真的是一个好主意吗?
  • 如果是,那么App Engine部署方法是什么?我找不到任何相关的文档...

目前,我们只有两个版本“ dev”和“ prod”在提交后进行了更新,但是在随机时间,我可以观察到奇怪的行为。

任何回应/建议/反馈都非常欢迎!

关于我正在谈论的网络问题的stacktrace示例:

DEBUG: Error sending result: 'MetadataServerException(HTTPError(),)'. Reason: 'PicklingError("Can't pickle <type 'cStringIO.StringO'>: attribute lookup cStringIO.StringO failed",)'
Traceback (most recent call last):
  File "/google-cloud-sdk/lib/googlecloudsdk/calliope/cli.py", line 733, in Execute
    resources = args.calliope_command.Run(cli=self, args=args)
  File "/google-cloud-sdk/lib/googlecloudsdk/calliope/backend.py", line 1630, in Run
    resources = command_instance.Run(args)
  File "/google-cloud-sdk/lib/surface/app/deploy.py", line 53, in Run
    return deploy_util.RunDeploy(self, args)
  File "/google-cloud-sdk/lib/googlecloudsdk/command_lib/app/deploy_util.py", line 387, in RunDeploy
    all_services)
  File "/google-cloud-sdk/lib/googlecloudsdk/command_lib/app/deploy_util.py", line 247, in Deploy
    manifest = _UploadFiles(service, code_bucket_ref)
  File "/google-cloud-sdk/lib/googlecloudsdk/command_lib/app/deploy_util.py", line 115, in _UploadFiles
    service, code_bucket_ref)
  File "/google-cloud-sdk/lib/googlecloudsdk/api_lib/app/deploy_app_command_util.py", line 277, in CopyFilesToCodeBucketNoGsUtil
    _UploadFiles(files_to_upload, bucket_ref)
  File "/google-cloud-sdk/lib/googlecloudsdk/api_lib/app/deploy_app_command_util.py", line 219, in _UploadFiles
    results = pool.map(_UploadFile, tasks)
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
    raise self._value
MaybeEncodingError: Error sending result: 'MetadataServerException(HTTPError(),)'. Reason: 'PicklingError("Can't pickle <type 'cStringIO.StringO'>: attribute lookup cStringIO.StringO failed",)'
DEBUG: Exception captured in Error
Traceback (most recent call last):
  File "/google-cloud-sdk/lib/googlecloudsdk/core/metrics.py", line 411, in Wrapper
    return func(*args, **kwds)
TypeError: Error() takes exactly 3 arguments (1 given)
ERROR: gcloud crashed (MaybeEncodingError): Error sending result: 'MetadataServerException(HTTPError(),)'. Reason: 'PicklingError("Can't pickle <type 'cStringIO.StringO'>: attribute lookup cStringIO.StringO failed",)'
Traceback (most recent call last):
  File "/google-cloud-sdk/lib/gcloud.py", line 65, in <module>
    main()
  File "/google-cloud-sdk/lib/gcloud.py", line 61, in main
    sys.exit(googlecloudsdk.gcloud_main.main())
  File "/google-cloud-sdk/lib/googlecloudsdk/gcloud_main.py", line 145, in main
    crash_handling.HandleGcloudCrash(err)
  File "/google-cloud-sdk/lib/googlecloudsdk/command_lib/crash_handling.py", line 107, in HandleGcloudCrash
    _ReportError(err)
  File "/google-cloud-sdk/lib/googlecloudsdk/command_lib/crash_handling.py", line 86, in _ReportError
    util.ErrorReporting().ReportEvent(error_message=stacktrace,
  File "/google-cloud-sdk/lib/googlecloudsdk/api_lib/error_reporting/util.py", line 28, in __init__
    self._API_NAME, self._API_VERSION)
  File "/google-cloud-sdk/lib/googlecloudsdk/core/apis.py", line 254, in GetClientInstance
    http_client = http.Http()
  File "/google-cloud-sdk/lib/googlecloudsdk/core/credentials/http.py", line 60, in Http
    creds = store.Load()
  File "/google-cloud-sdk/lib/googlecloudsdk/core/credentials/store.py", line 282, in Load
    if account in c_gce.Metadata().Accounts():
  File "/google-cloud-sdk/lib/googlecloudsdk/core/credentials/gce.py", line 122, in Accounts
    gce_read.GOOGLE_GCE_METADATA_ACCOUNTS_URI + '/')
  File "/google-cloud-sdk/lib/googlecloudsdk/core/util/retry.py", line 160, in TryFunc
    return func(*args, **kwargs), None
  File "/google-cloud-sdk/lib/googlecloudsdk/core/credentials/gce.py", line 45, in _ReadNoProxyWithCleanFailures
    raise MetadataServerException(e)
googlecloudsdk.core.credentials.gce.MetadataServerException: HTTP Error 503: Service Unavailable
DEBUG: Uploading [/builds/apps/webapp/lib/jinja2/defaults.pyc] to [151c77b4e5bdd2c38b6a2bf914fffa3a6ffa71a6]
INFO: Uploading [/builds/apps/webapp/lib/jinja2/defaults.pyc] to [151c77b4e5bdd2c38b6a2bf914fffa3a6ffa71a6]
INFO: Refreshing access_token
丹·科尼莱斯库(Dan Cornilescu)

好坏?主观的-因此对SO来说是题外话。假设问题是如何使连续部署可靠:)

好吧,问题在于您正在使用应用程序版本作为CI环境,这意味着您无法避免由于特定版本不良而造成的损坏。您只能希望通过重新部署版本(中断结束时)来尽快恢复-这可以自动进行。

您不应让生产站点直接在CIproduction管道覆盖的版本上运行,否则会因部署不当而冒着站点中断的风险。相反,你可以使用一个新的/唯一版本的CI的每个执行production管线并且只有完成之后成功你最终使用流量如下所述切换网站流量到它的版本(也可以在CI管线内使用,如果使用不同的应用程序,而不是CI版本应用程序版本

部署程序开始

默认情况下,deploy命令每次使用时都会自动生成一个新的版本ID,并将所有流量路由到该新版本。

要覆盖此行为,可以使用version标志指定版本ID:

gcloud app deploy --version myID

您也可以使用--no-promote标志指定不立即将所有流量发送到新版本:

gcloud app deploy --no-promote

因此,请确保不要部署一个版本,并且不要在同一步骤中将该版本设置为默认的流量目标(如果从客户端驱动,则可能不是原子的)。特别是对于生产应用程序。代替:

这样,唯一关键的操作就是流量切换,(有希望)这是一个成功的原子操作,或者它已经完全退回到GAE端(如果不是,则是GAE错误)。如果此步骤失败,则该应用仍应继续使用旧版本。

当然,这假设网络问题仅在您和GAE之间,如果它们也影响GAE的内部运营,那么所有的赌注都没有了(但是我相信应该及时解决)。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章