web-dev-qa-db-ja.com

CodePipeline:ECRソース+ ECSデプロイ構成

基本的に、ECSコンテナーへのbitbucketソースコードを使用してCI/CDを構成する必要があります。 CodePiplineを使用して、新しいECRイメージをECSに展開したいと思います。

現在、AWS CodePiplineには、ソースとしてbitbucketを指定するオプションはありません。ただし、私はwebhookでCodeBuildを構成して、Dockerファイルをビルドし、Push to releaseブランチごとにECRにプッシュしました。

ECRをCodePiplineの「ソース」ステージとして構成し、既存のECSクラスター/サービスに展開して、展開が自動化されるようにしたいと考えています。

  • ソースステージで「image_details」出力アーティファクトを持つアクションプロバイダーとして「Amazon ECR」を指定しました。
  • 「image_details」を入力アーティファクトとして、デプロイステージのアクションプロバイダーとして「Amazon ECS」(「Amazon ECS(青/緑)」ではない)を指定しました

codepipeline_settings

残念ながら、デプロイ手順で次のエラーが発生すると、基本的な構成とアーティファクトの連鎖が発生します。

Invalid action configuration
The image definition file imageDetail.json contains invalid JSON format

「Amazon ECR」ステージは出力アーティファクトとしてimageDetail.jsonを提供しますが、「Amazon ECS」デプロイプロバイダーでは想定されていないようです。この問題を回避するための合理的な方法はありますか?

CI/CDをbitbucket + API Gateway/Lambda + CodePipelineで構成できることは承知しています。また、ソースリポジトリとしてbitbucketの代わりにCodeCommitを使用することを検討します。直接CodePipeline。

UPD:this ブログポストで説明されているかなりいい構成になりました:全体的なアイデアは、CodeBuildにソースコードをbitbucketからS3にアップロードし、CodePipelineをS3とソースとして使用して、新しいDockerイメージをECRにデプロイし、新しいタスク定義のリビジョンをECSクラスターに公開します。 S3はまだオーバーヘッドであり、私はタスクのためのよりエレガントなソリューションを探しています。

11
Sergey Nikitin

ECRをパイプラインのソースとして使用して、イメージをECSにデプロイしたいという同様の問題を最近解決しなければなりませんでした。私が見つけた解決策は、3つのステージを作成することでした。

  • ソース:ECR
  • Build:ECRアーティファクトをDeployステージが理解できるアーティファクトに変換するカスタムコード
  • Deploy:ECSへ

これが、ビルドステージとして使用しているbuildspec.ymlファイルです。

version: 0.2

phases:
  install:
    runtime-versions:
      python: 3.7
  build:
    commands:
      - PHP_REPOSITORY_URI=$(cat imageDetail.json | python -c "import sys, json; print(json.load(sys.stdin)['ImageURI'].split('@')[0])")
      - IMAGE_TAG=$(cat imageDetail.json | python -c "import sys, json; print(json.load(sys.stdin)['ImageTags'][0])")
      - echo $PHP_REPOSITORY_URI:$IMAGE_TAG
  post_build:
    commands:
      - echo Writing image definitions file...
      - printf '[{"name":"container","imageUri":"%s"}]' $PHP_REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
    files: imagedefinitions.json

基本的に、これは、imageDetail.jsonファイルを読み取り、ECRリポジトリのURLとTAGを抽出し、ECS Deployステージ用にフォーマットされたjsonファイルを出力します。これは、カスタマイズなしの単なる標準ステージです。

8
Carlos Barros

私は同様のユースケースを持っていて、同じ問題にぶつかりました。私のユースケースに対処するソリューションで少し長い答え...

  1. 使用例:ツールアカウントには、CodeBuildおよびdocker Push to QA Accounts ECRを実行するCodePipelineがあります。画像には「コミットハッシュ」と「最新」の2つのタグがあります。 QAアカウントには、新しいイメージが利用可能になったときに実行されるパイプラインがあり、このパイプラインは新しいイメージをQAアカウントのFargateクラスターにデプロイします。
  2. 導入プラットフォーム:Amazon ECS標準導入アクション。
  3. 出典:ECR。
  4. 問題の原因:ECRソースの出力アーティファクト正しくイメージに関する情報のみが含まれ、ECS Standard Deployが期待するコンテナ名は含まれません。
  5. AWSへの提案:ECRをECSのソースとして使用する一般的なシナリオを考えると、コンテナ名を追加する機能(オプション)を持つという引数を作成できます出力アーティファクト-これにより、ECS Standard Deployの入力として受け入れられる出力アーティファクトを生成できます。

このように AWSの公式doco ECS標準デプロイメントでは、コンテナ名と画像URIを提供する-imagedefinitions.jsonファイルが必要です。次のようになります。

[
  {
    "name": "sample-app",
    "imageUri": "11111EXAMPLE.dkr.ecr.us-west-2.amazonaws.com/ecs-repo:latest"
  }
]

ただし、ECRソースは、以下のimageDetail.jsonサンプルと呼ばれる出力アーティファクトを生成します。これは、ECS Standard Deploy aka imagedefinitions.jsonの予想される入力形式と一致しません。これには、コンテナー名(name)が含まれ、展開は Deploy Failure のようなメッセージで失敗します。

{
    "ImageSizeInBytes": "44728918",
    "ImageDigest": "sha256:EXAMPLE11223344556677889900bfea42ea2d3b8a1ee8329ba7e68694950afd3",
    "Version": "1.0",
    "ImagePushedAt": "Mon Jan 21 20:04:00 UTC 2019",
    "RegistryId": "EXAMPLE12233",
    "RepositoryName": "dk-image-repo",
    "ImageURI": "ACCOUNTID.dkr.ecr.us-west-2.amazonaws.com/dk-image-repo@sha256:example3",
    "ImageTags": [
        "latest"
    ]
}

これを修正するために私が取ったアプローチは:

  1. ソースステージ:ECRソースに加えて、Z3にimagedefinitions.jsonを含むs3のソースを追加しました。

  2. ECS Deployステージアクションでは、ECS Standard Deployが理解できる形式でimagedefinitions.jsonを含むs3ソースからの出力アーティファクトを参照します。

注:imagedefinitions.jsonはs3バケットで静的であり、常に上記のイメージの最新のタグを参照します。したがって、QA画像定義バケットでは、最終的に画像定義Zip、つまりFargateサービスのインスタンスごとに1つになります。

一般的な参照用にパイプラインをここにエクスポートしました。

{
"pipeline": {
    "roleArn": "arn:aws:iam::ACCOUNTID:role/service-role/AWSCodePipelineServiceRole-REGION-PIPELINENAME",
    "stages": [
        {
            "name": "Source",
            "actions": [
                {
                    "inputArtifacts": [],
                    "name": "Source",
                    "region": "REGION",
                    "actionTypeId": {
                        "category": "Source",
                        "owner": "AWS",
                        "version": "1",
                        "provider": "ECR"
                    },
                    "outputArtifacts": [
                        {
                            "name": "SourceArtifact"
                        }
                    ],
                    "configuration": {
                        "ImageTag": "latest",
                        "RepositoryName": "PIPELINENAME"
                    },
                    "runOrder": 1
                },
                {
                    "inputArtifacts": [],
                    "name": "sourceimagedeffile",
                    "region": "REGION",
                    "actionTypeId": {
                        "category": "Source",
                        "owner": "AWS",
                        "version": "1",
                        "provider": "S3"
                    },
                    "outputArtifacts": [
                        {
                            "name": "PIPELINENAME-imagedefjson"
                        }
                    ],
                    "configuration": {
                        "S3Bucket": "BUCKETNAME",
                        "PollForSourceChanges": "true",
                        "S3ObjectKey": "PIPELINENAME.Zip"
                    },
                    "runOrder": 1
                }
            ]
        },
        {
            "name": "Deploy",
            "actions": [
                {
                    "inputArtifacts": [
                        {
                            "name": "PIPELINENAME-imagedefjson"
                        }
                    ],
                    "name": "Deploy",
                    "region": "REGION",
                    "actionTypeId": {
                        "category": "Deploy",
                        "owner": "AWS",
                        "version": "1",
                        "provider": "ECS"
                    },
                    "outputArtifacts": [],
                    "configuration": {
                        "ClusterName": "FARGATECLUSTERNAME",
                        "ServiceName": "PIPELINENAME",
                        "FileName": "imageDetail.json"
                    },
                    "runOrder": 1
                }
            ]
        }
    ],
    "artifactStore": {
        "type": "S3",
        "location": "codepipeline-REGION-555869339681"
    },
    "name": "PIPELINENAME"
}
6
kiran01bm