GeKo
GeKo

Reputation: 201

AWS ECS Blue/Green CodePipeline: Exception while trying to read the image artifact

I wanted to create a CodePipeline which builds a container image from CodeCommit source and afterwards deploys the new image in Blue/Green fashion to my ECS service (EC2 launchtype).

The problem is with the image definition from the BuildArtifact. The pipeline fails in the Deploy phase with error:

"" Invalid action configuration Exception while trying to read the image artifact file from the artifact: BuildArtifact. ""

How to properly configure the "Amazon ECS (Blue/Green)" deploy phase, so that it can use the recently created image and deploy it....by replacing placeholder IMAGE_NAME inside taskdef.json ?

Any hint highly appreciated :D

Upvotes: 5

Views: 6971

Answers (4)

Ronan Cunningham
Ronan Cunningham

Reputation: 404

I ran into the same problem.

tl:dr

I was not passing the correct input artefact with the imageDetail.json to the pipeline CodeDeployToECS action.

Summary:

Instead of checking in a version of the task definition with the '<IMAGE1_NAME>' placeholder, I'm dynamically generating the task definition input to CodeDeploy inside the pipeline.

The task definition early in the project is quite volatile, with new variables etc being passed to the container. It's generated and registered within the pipeline (Cloudformation) and then read out via a Codebuild project, substituting the image placeholder with '<IMAGE1_NAME>' and passed to the next stage in the pipeline via a pipeline artefact.

Fixing it:

  1. I have a CodeBuild project within the pipeline that produces the imageDetail.json:
   {"ImageURI":"########.dkr.ecr.eu-west-1.amazonaws.com/##/#####:2739511dd87d4e4e1f65ed69c9e779b63fb72e36-master-fbe73fdc-6213-4bd6-a784-dcc3d2ae7845"}

It's pipeline output is named 'BuildDockerOutput'

  1. I have another Codebuild project that produces:

taskdef.json

{
  "containerDefinitions": [
    {
      "name": "ronantest1",
      "image": "<IMAGE1_NAME>",
                       ]
}

appspec.json

{
  "version": 0.0,
  "Resources": [
    {
      "TargetService": {
        "Type": "AWS::ECS::Service",
        "Properties": {
          "TaskDefinition": "<TASK_DEFINITION>",
          "LoadBalancerInfo": {
            "ContainerName": "ronantest1",
            "ContainerPort": "8080"
          }
        }
      }
    }
  ],
  "Hooks": [
      {
      "AfterAllowTestTraffic": "arn:aws:lambda:eu-west-1:######:function:code-deploy-after-allow-test-traffic"
      }

    ]
  }

It's pipeline output is named 'PrepareCodeDeployOutputTesting'

My final CodeDeploy action is like the following:

            - Name: BlueGreenDeploy
              InputArtifacts:
              - Name: BuildDockerOutput
              - Name: PrepareCodeDeployOutputTesting
              Region: !Ref DeployRegion1
              ActionTypeId:
                Category: Deploy
                Owner: AWS
                Version: '1'
                Provider: CodeDeployToECS
              RoleArn: !Sub arn:aws:iam::${TestingAccountId}:role/######/CrossAccountsDeploymentRole
              Configuration:

                AppSpecTemplateArtifact: PrepareCodeDeployOutputTesting
                AppSpecTemplatePath: appspec.json

                ApplicationName: !Ref ApplicationName
                DeploymentGroupName: !Ref ApplicationName
                
                TaskDefinitionTemplateArtifact: PrepareCodeDeployOutputTesting
                TaskDefinitionTemplatePath: taskdef.json

                Image1ArtifactName: BuildDockerOutput
                Image1ContainerName: "IMAGE1_NAME"
              RunOrder: 4

Note the different aspects of the CodeDeployToECS needed artefacts from different InputArtifacts, specifically 'Image1ArtifactName'

Upvotes: 1

Mohammed Almusaddar
Mohammed Almusaddar

Reputation: 787

Thanks, to all, this gives me some light into solving the issue.

I would like to add that when you use aws cli, cloudformation, or Terraform to configure codepipeline, some parameters and options are not available with the console and setting some variables in these tools like the empty string "" will cause an exception error.

Always check for codepipeline settings in the console when you deploy using these tools.

so the error occur when you defined Image Artifact but not define the placeholder

imageDetail.json can be passed into codedeploy using the following methods:

  • git source ( codecommit or github ) the file that exist in your app codebase
  • ECR source - the file will be autogenerated by ECR, but will use SHA256 instead of the image tag
  • CodeBuild source - you update the file using codebuild buildspec.yml and pass it down to codedeploy stage.

Upvotes: 0

GeKo
GeKo

Reputation: 201

answering my own question here, hopefully it helps others who facing the same situation.

  1. the file imagedefinitions.json is inappropriate for deploy action "Amazon ECS Blue/Green". For that you have to create file imageDetail.json within the build step and provide it as artifact to the deploy step. How ? This is how the bottom of my buildspec.yaml looks like:
      - printf '{"ImageURI":"%s"}' $REPOSITORY_URI:$IMAGE_TAG > imageDetail.json
artifacts:
  files: 
    - 'image*.json'
    - 'appspec.yaml'
    - 'taskdef.json'
  secondary-artifacts:
    DefinitionArtifact:
      files:
        - appspec.yaml
        - taskdef.json
    ImageArtifact:
      files:
        - imageDetail.json
  1. In the Deploy phase of CodePipeline, use DefinitionArtifact and ImageArtifact as Input Artifacts and configure them in the corresponding section "Amazon ECS task definition" and "AWS CodeDeploy AppSpec file".

Ensure that your appspec.yaml contains placeholder for the task definition. Here is my appspec.yaml:

version: 0.0

Resources:
  - TargetService:
      Type: AWS::ECS::Service
      Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo:
          ContainerName: "my-test-container"
          ContainerPort: 8000

Also ensure that your taskdef.json contains placeholder for the final image, like

...
"image": <IMAGE1_NAME>,
...
  1. use that placeholder in the codepipeline config of your blue/green deploy phase in the section "Dynamically update task definition image - optional" by choosing the input artifact as "ImageArtifact" and the placeholder <IMAGE1_NAME>

Upvotes: 7

shariqmaws
shariqmaws

Reputation: 8890

Amazon ECS Blue/Green (or CodeDeployToECS) CodePipeline action requires the TaskDefinitionTemplateArtifact parameter (see [1]).

In addition to the above file note an imageDetail.json is required for ECS Blue/Green deployments (not 'imagedefinition.json'). The file structure and details are available here [2]. Add this file to the root of your deployment artifact/version control. If you do not want to add this file manually you can use the ECR source action to the CodePipeline and configure this with the Image you are using in the ECS service/taskdef.json. This is all discussed at [2] for clarity.

To see how this is all brought together you can also follow the step by step instructions for ECS Blue/Green deployments here [3].

References:

[1] https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements : CodePipeline Pipeline Structure Reference - Action Structure Requirements in CodePipeline [2] https://docs.aws.amazon.com/codepipeline/latest/userguide/file-reference.html#file-reference-ecs-bluegreen : Image Definitions File Reference - imageDetail.json File for Amazon ECS Blue/Green Deployment Actions [3] https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html : Tutorial: Create a Pipeline with an Amazon ECR Source and ECS-to-CodeDeploy Deployment

Upvotes: 2

Related Questions