【问题标题】:AWS ECS Blue/Green CodePipeline: Exception while trying to read the image artifactAWS ECS Blue/Green CodePipeline:尝试读取图像工件时出现异常
【发布时间】:2020-09-13 07:03:42
【问题描述】:

我想创建一个 CodePipeline,它从 CodeCommit 源构建容器映像,然后以蓝/绿方式将新映像部署到我的 ECS 服务(EC2 启动类型)。

  • 源阶段为 CodeCommit,其中已包含 appspec.json
    以及 taskdef.json
  • 构建阶段正在构建新的 容器并将其成功推送到 ECR,文件 imagedefinition.json 是这一步创建的 BuildArtifact, 包含容器和最近创建的图像及其 与 CodeCommit 提交 ID 对应的标签。
  • 部署阶段 由操作“Amazon ECS(蓝/绿)”组成,使用 SourceArtifact 和 BuildArtifact 作为 InputArtifacts,取 来自 SourceArtifact 和图像的 appspec 和 taskdef BuildArtifact 中的描述,以最终部署新的 蓝色/绿色方式的容器。

问题在于 BuildArtifact 中的图像定义。管道在部署阶段失败并出现错误:

"" 无效的动作配置 尝试从工件读取图像工件文件时出现异常:BuildArtifact。 ""

如何正确配置“Amazon ECS(蓝/绿)”部署阶段,以便它可以使用最近创建的映像并部署它....通过替换 taskdef.json 中的占位符 IMAGE_NAME ?

高度赞赏的任何提示:D

【问题讨论】:

    标签: amazon-ecs aws-code-deploy aws-codepipeline aws-codebuild blue-green-deployment


    【解决方案1】:

    Amazon ECS 蓝/绿(或 CodeDeployToECS)CodePipeline 操作需要 TaskDefinitionTemplateArtifact 参数(请参阅 [1])。

    除了上述文件注意之外,ECS 蓝/绿部署还需要 imageDetail.json(不是“imagedefinition.json”)。文件结构和详细信息可在此处获得 [2]。将此文件添加到部署工件/版本控制的根目录。如果您不想手动添加此文件,您可以使用 ECR 源操作到 CodePipeline 并使用您在 ECS 服务/taskdef.json 中使用的图像进行配置。为了清楚起见,所有这些都在 [2] 中进行了讨论。

    要了解这一切是如何组合在一起的,您还可以按照此处 [3] 的 ECS 蓝/绿部署分步说明进行操作。

    参考资料:

    [1] https://docs.aws.amazon.com/codepipeline/latest/userguide/reference-pipeline-structure.html#action-requirements : CodePipeline 管道结构参考 - CodePipeline 中的操作结构要求 [2] https://docs.aws.amazon.com/codepipeline/latest/userguide/file-reference.html#file-reference-ecs-bluegreen:图像定义文件参考 - 用于 Amazon ECS 蓝/绿部署操作的 imageDetail.json 文件 [3] https://docs.aws.amazon.com/codepipeline/latest/userguide/tutorials-ecs-ecr-codedeploy.html:教程:使用 Amazon ECR 源和 ECS-to-CodeDeploy 部署创建管道

    【讨论】:

    • 非常感谢@shariqmaws 的提示。该教程我已经阅读了好几遍,但它没有为我提供最后的提示,因为它使用 ECR 作为源,但我想将容器构建为管道本身的一部分。其他链接非常有帮助,因此我可以解决我的问题,提供最终解决方案作为单独的答案。
    【解决方案2】:

    在这里回答我自己的问题,希望它可以帮助面临同样情况的其他人。

    1. 文件 imagedefinitions.json 不适合部署操作“Amazon ECS Blue/Green”。为此,您必须在构建步骤中创建文件 imageDetail.json 并将其作为工件提供给部署步骤。如何 ?这是我的 buildspec.yaml 底部的样子:
          - 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. 在 CodePipeline 的 Deploy 阶段,使用 DefinitionArtifact 和 ImageArtifact 作为 Input Artifact,并在相应的“Amazon ECS 任务定义”和“AWS CodeDeploy AppSpec file部分进行配置”。

    确保您的 appspec.yaml 包含任务定义的占位符。这是我的 appspec.yaml:

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

    还要确保您的 taskdef.json 包含最终图像的占位符,例如

    ...
    "image": <IMAGE1_NAME>,
    ...
    
    1. 在“动态更新任务定义图像 - 可选”部分的蓝/绿部署阶段的代码管道配置中使用该占位符,方法是选择输入工件为“ImageArtifact”和占位符 @987654324 @

    【讨论】:

    • 次要注意,占位符不应包含方括号。
    • 我对占位符的使用有点困惑。我收到此错误:名为的图像 URI 容器: 与提供的任务定义文件中缺少的任何容器都不匹配。
    【解决方案3】:

    谢谢大家,这让我对解决问题有了一些了解。

    我想补充一点,当您使用aws clicloudformationTerraform配置codepipeline时,一些参数和选项在控制台中不可用,并在这些工具中设置一些变量,如空string "" 会导致异常错误。

    使用这些工具进行部署时,请始终检查控制台中的codepipeline 设置。

    所以当您定义 Image Artifact 但未定义占位符时会发生错误

    imageDetail.json 可以使用以下方法传入codedeploy

    • git 源(codecommit 或 github)存在于您的应用代码库中的文件
    • ECR 源 - 该文件将由 ECR 自动生成,但将使用 SHA256 而不是图像标签
    • CodeBuild source - 您使用 codebuild buildspec.yml 更新文件并将其传递给 codedeploy 阶段。

    【讨论】:

      【解决方案4】:

      我遇到了同样的问题。

      tl:dr

      我没有将带有 imageDetail.json 的正确输入工件传递给管道 CodeDeployToECS 操作。

      总结:

      我没有使用“”占位符签入任务定义的版本,而是动态生成任务定义输入到管道内的 CodeDeploy。

      项目早期的任务定义非常不稳定,新变量等被传递给容器。它在管道 (Cloudformation) 中生成和注册,然后通过 Codebuild 项目读出,用“”替换图像占位符,并通过管道工件传递到管道的下一个阶段。

      修复它:

      1. 我在生成 imageDetail.json 的管道中有一个 CodeBuild 项目:
         {"ImageURI":"########.dkr.ecr.eu-west-1.amazonaws.com/##/#####:2739511dd87d4e4e1f65ed69c9e779b63fb72e36-master-fbe73fdc-6213-4bd6-a784-dcc3d2ae7845"}
      

      它的管道输出名为“BuildDockerOutput”

      1. 我有另一个 Codebuild 项目产生:

      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"
            }
      
          ]
        }
      
      

      它的管道输出名为“PrepareCodeDeployOutputTesting”

      我的最终 CodeDeploy 操作如下所示:

                  - 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
      

      注意 CodeDeployToECS 的不同方面需要来自不同 InputArtifacts 的人工制品,特别是“Image1ArtifactName”

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-04
        相关资源
        最近更新 更多