1

Недавно мы установили непрерывную интеграцию/развертывание/поставку узла nodejs webapp в Google App Engine. Сервер CI (GitLabCI) выполняет установку, сборку, тестирование и развертывание зависимостей для интеграции/prod в зависимости от отрасли (разработка/мастер).Непрерывная интеграция/развертывание/доставка в Google App Engine слишком рискованна?

В наши дни единственные ошибки, с которыми мы столкнулись, были во время этапа зависимостей, и поэтому нам было все равно. Но вчера (21/10/16) произошел широкомасштабный перерыв DNS, и трубопровод провалился в середине этапа развертывания, разрушил продукт. Просто повторите запуск трубопровода, выполнив задание, но проблема может быть воспроизведена в любое время.

Мои вопросы:

  • Как мы можем справиться с такого рода проблем в сети, в непрерывном процессе развертывания?
  • Является ли непрерывное развертывание в Google App Engine действительно хорошей идеей?
  • Если да, то какой метод развертывания App Engine? Я не нахожу соответствующий документ об этом ...

На данный момент у нас есть только две версии «Dev» и «подталкивать», которые обновляются после фиксаций, но в случайные моменты времени, я мог наблюдать странное поведение ,

Любой ответ/предложения/обратная связь очень приветствуются!

Пример 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 

ответ

2

Хорошо/плохо? Субъективный - таким образом, вне темы для SO. Предполагая, что вопрос заключается в том, как сделать непрерывное развертывание надежным :)

Ну, проблема в том, что вы используете версии приложения в качестве среды вашего интерфейса, что означает, что вы не можете избежать поломки из-за плохой конкретной версии , Вы можете только надеяться восстановить как можно быстрее, повторно развернув версию (когда закончится провал) - это может быть автоматизировано.

Вам не нужно, чтобы ваш производственный сайт работал непосредственно с версией, перезаписанной конвейером CI production, иначе вы рискуете отключить сайт при плохом развертывании. Вместо этого вы можете использовать новую/уникальную версию для каждого выполнения конвейера CI production, и только после того, как это завершается успешно, вы, наконец, переключите трафик сайта на свою версию, используя поток, описанный ниже (который также может использоваться внутри конвейеров CI при использовании разных приложения вместо версии приложения, как CI сред)

от Deploying your program:

по умолчанию команда развертывания автоматически генерирует новый идентификатор версии каждый раз, когда вы используете его, и будет маршрут любой трафик на новый .

Чтобы изменить это поведение, вы можете указать идентификатор версии с этим флагом версии:

gcloud app deploy --version myID 

Вы также можете указать не посылать весь трафик к новой версии immediatey с --no-продвижение флаг:

gcloud app deploy --no-promote 

Поэтому убедитесь, что вы никогда не развертывать версию и сделать эту версию назначения одним из трафика по умолчанию в той же стадии (возможно, не атомная, если с клиентской стороны). Специально для производственного приложения. Вместо этого:

Таким образом, единственной критической операцией является переключение трафика, которое (надеюсь) является атомной операцией, которая либо успешна, либо полностью откатывается на стороне GAE (если это не ошибка GAE). Если этот шаг не удается, приложение должно продолжать работать со старой версией.

Конечно, это предполагает, что сетевые проблемы находятся только между вами и GAE, если они также влияют на внутренние операции GAE, все ставки отключены (но те, кому я доверяю, должны быть исправлены довольно своевременно).

+0

Благодарим вас за подробный ответ. Возможно, вы правы в использовании разных приложений в качестве сред CI, это лучшая идея, и она может решить различные проблемы, с которыми мы сталкиваемся. У меня последний вопрос: приложение автомасштабировано, поэтому я не могу запускать/останавливать версии ([согласно документу doc] (https://cloud.google.com/sdk/gcloud/reference/app/versions/start)). Когда сборка создаст версию, будет взиматься трафик, если я настрою базовую шкалу? Или я должен удалить предыдущую версию при создании нового? – Loheek

+1

Не нужно явно запускать новую версию с автомасштабированием. Просто используйте URL-адреса соответствующей версии для тестирования того, что версия работает, и GAE запустит сами экземпляры: https://cloud.google.com/appengine/docs/flexible/python/how-requests-are-routed#routing_via_url –

 Смежные вопросы

  • Нет связанных вопросов^_^