Loh*_*eek 5 google-app-engine continuous-integration continuous-deployment continuous-delivery gitlab-ci
我们最近在 Google App Engine 上设置了一个 nodejs webapp 的持续集成/部署/交付。CI 服务器 (GitLabCI) 根据分支 (develop/master) 运行依赖项安装、构建、测试和部署到集成/生产。
在今天,我们面临的唯一错误是在依赖步骤期间,所以我们并没有太在意它。但是昨天(21/10/16)发生了大规模的 DNS 中断,并且管道在部署步骤中间失败,导致生产中断。只需重新运行管道即可完成工作,但问题随时可能重现。
我的问题是:
目前我们只有两个版本“dev”和“prod”在提交后更新,但在随机时间我可以观察到奇怪的行为。
非常欢迎任何回应/建议/反馈!
关于我正在谈论的网络问题的堆栈跟踪示例:
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
Run Code Online (Sandbox Code Playgroud)
好坏?主观 - 因此偏离主题。假设问题是如何使持续部署可靠:)
好吧,问题在于您使用应用程序版本作为 CI 环境,这意味着您无法避免由于特定版本不好而导致的损坏。您只能希望通过重新部署版本(在中断结束时)尽快恢复——这可以自动化。
您不应让生产站点直接在 CIproduction管道覆盖的版本上运行,否则您可能会因部署不当而导致站点中断。相反,你可以使用一个新的/唯一版本的CI的每个执行production管线并且只有完成之后成功你最终使用流量如下所述切换网站流量到它的版本(也可以在CI管线内使用,如果使用不同的应用程序,而不是的应用程序版本为CI环境)
从部署您的程序:
默认情况下,deploy 命令会在您每次使用时自动生成一个新版本 ID,并将所有流量路由到新版本。
要覆盖此行为,您可以使用版本标志指定版本 ID:
Run Code Online (Sandbox Code Playgroud)gcloud app deploy --version myID您还可以使用 --no-promote 标志指定不立即将所有流量发送到新版本:
Run Code Online (Sandbox Code Playgroud)gcloud app deploy --no-promote
因此,请确保您永远不会部署某个版本,并将该版本设为同一步骤中的默认流量目标(如果从客户端驱动,则可能不是原子的)。特别是对于生产应用程序。反而:
gcloud app deploy --no-promote --version ...)gcloud app versions ...) 并检查它是否有效gcloud app services set-traffic ...)这样,唯一的关键操作是流量切换,它(希望)是一个原子操作,要么成功,要么在 GAE 端完全回滚(如果不是,则是 GAE 错误)。如果此步骤失败,应用程序仍应继续使用旧版本。
当然,这假设网络问题仅存在于您和 GAE 之间,如果它们也影响 GAE 的内部操作,那么所有赌注都将关闭(但我认为应该及时修复那些问题)。
| 归档时间: |
|
| 查看次数: |
1608 次 |
| 最近记录: |