AWS ECS Blue/Green CodePipeline:尝试读取图像工件时出现异常

Posted

技术标签:

【中文标题】AWS ECS Blue/Green CodePipeline:尝试读取图像工件时出现异常【英文标题】:AWS ECS Blue/Green CodePipeline: Exception while trying to read the image artifact 【发布时间】: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

【问题讨论】:

【参考方案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】:

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

    文件 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
    在 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>,
...
    在“动态更新任务定义图像 - 可选”部分的蓝/绿部署阶段的代码管道配置中使用该占位符,方法是选择输入工件为“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 项目读出,用“”替换图像占位符,并通过管道工件传递到管道的下一个阶段。

修复它:

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

它的管道输出名为“BuildDockerOutput”

    我有另一个 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”

【讨论】:

以上是关于AWS ECS Blue/Green CodePipeline:尝试读取图像工件时出现异常的主要内容,如果未能解决你的问题,请参考以下文章

PCL进阶:点云渲染渐变赋色(Blue>Green>Yellow>Red)

如何让 CodeDeploy Blue/Green 为自定义指标创建 CloudWatch 警报?

计算数组数组中的项目

如何在 AWS ECS 集群的服务中运行 AWS ECS 任务,而不是将服务从 Circle CI 的“aws-ecs/run-task”中排除

Unity图集优化原理

[AWS][容器][ECS] ECS动手实验101