1

Google App Engine에서 nodejs 웹 애플리케이션의 지속적인 통합/배포/전달을 최근에 설정했습니다. CI 서버 (GitLabCI)는 분기 (개발/마스터)에 따라 종속성 설치, 빌드, 테스트 및 배포를 통합/prod에 실행합니다.Google App Engine에서 지속적인 통합/배포/전달이 너무 위험합니다.

오늘 날 우리가 직면 한 유일한 버그는 의존성 단계에서 발생했기 때문에 우리는 그것에 대해별로 신경 쓰지 않았습니다. 그러나 어제 (21/10/16), 대규모 DNS 중단이 있었고 파이프가 배포 단계 중간에 실패했습니다. 은 찌꺼기을 무너 뜨 렸습니다. 파이프 라인을 다시 실행하기 만하면되었지만 문제는 언제든지 재현 할 수 있습니다.

내 질문은 :

  • 우리가 어떻게 연속 배포 과정에서 네트워크 문제의이 종류를 처리 할 수 ​​
      ?
    • Google App Engine에 지속적으로 배포하는 것이 좋은 생각입니까?
    • 그렇다면 App Engine 배포 방법은 무엇입니까? 나는 잠시 동안 모든 관련 그것에 대해 문서 ...

    을 찾을 수없는 우리는 두 가지 버전 "DEV"와 커밋 이후에 업데이트됩니다 "자극"을 가지고 있지만, 임의의 시간에 나는 이상한 행동을 관찰 할 수 있었다 .

    모든 의견/제안/의견은 매우 환영합니다!

    내가 얘기하고있는 네트워킹 문제와 관련된 스택 트레이스의 예 :

    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

    좋은/나쁜? 주관적인 - 따라서 주제에 벗어났습니다. 질문을 가정하면 신뢰성 :

    잘 연속 배포를 만드는 방법입니다, 문제는 당신이 때문에 특정 버전의 나쁜 것에 파손을 방지 할 수 없음을 의미하는 응용 프로그램 버전 당신의 CI 환경 등을 사용하고 있다는 것입니다 . 버전을 재배포하여 (중단이 끝나면) 가능한 한 빨리 복구 할 수 있습니다. 자동 업그레이드가 가능합니다.

    프로덕션 사이트를 CI production 파이프 라인으로 덮어 쓰는 버전에서 직접 실행하지 않아야합니다. 그렇지 않으면 잘못된 배포로 인해 사이트가 중단 될 위험이 있습니다. 다른 사용하는 경우 대신 당신은 CI production 파이프 라인의 각 실행에 대한 새/독특한 버전을 사용할 수 있으며,이 성공적으로 완료 후에 당신은 마침내 또한 CI 파이프 라인 내에서 사용할 수있는 아래에 설명 된 흐름을 (사용하여 버전으로 사이트 트래픽을 전환 응용 프로그램 대신 응용 프로그램 버전 CI 환경 등) Deploying your program에서

    :

    deploy 명령이 자동으로 새 버전 ID 당신이 그것을 사용할 때마다 생성 기본적으로

    과 의지 라우팅에 대한 트래픽 신규 버전.

    이 동작을 재정의하려면 버전 플래그 버전 ID를 지정할 수 있습니다

    gcloud app deploy --version myID 
    

    당신은 또한에 새 버전 immediatey 모든 트래픽을 보내도록 지정할 수 있습니다 --no 홍보 플래그 :

    gcloud app deploy --no-promote 
    

    그렇다면 원자하지 가능성 (당신은 결코 버전을 배포하지 않고 동일한 단계에서 해당 버전을 기본 트래픽 대상 하나를 만들 확인 클라이언트 측에서 구동 됨). 특히 프로덕션 응용 프로그램의 경우. 대신 :

    에 잘 스위치 실제 트래픽을 작동하는 경우는
  • 를 작동하는지 확인
  • 이런 식으로 유일한 중요한 작업은 트래픽 교환입니다. (잘하면) 원자 연산이 성공했거나 GAE 측에서 완전히 롤백 된 것입니다 (그렇지 않은 경우 GAE 버그 임). 이 단계가 실패해도 앱은 이전 버전에서 계속 작동해야합니다.

    물론 네트워킹 문제는 GAE의 내부 작업에 영향을 주며 모든 내기가 인 경우에만 발생합니다 (하지만 신뢰하는 사람은시기 적절하게 수정해야 함).

  • +0

    매우 자세한 답변을 보내 주셔서 감사합니다. CI 환경으로 여러 가지 응용 프로그램을 사용하는 것이 옳았습니다. 이는 더 좋은 아이디어이며 우리가 직면 한 다른 문제를 해결할 수 있습니다. 마지막 질문입니다. 앱이 자동 크기 조정되어 버전을 시작/중지 할 수 없습니다 ([doc에 따라] (https://cloud.google.com/sdk/gcloud/reference/app/versions/start)).). 빌드가 버전을 만들면 기본 규모를 설정해야 트래픽이 청구됩니까? 또는 new가 생성되면 이전 버전을 삭제해야합니까? – Loheek

    +1

    자동 확장으로 새 버전을 명시 적으로 시작할 필요가 없습니다. 버전이 작동하는지 테스트하기 위해 해당 버전의 URL을 사용하면 GAE가 인스턴스 자체를 시작합니다. https://cloud.google.com/appengine/docs/flexible/python/how-requests-are-routed#routing_via_url –