我将保留ECS容器实例(我在谈论Docker主机 -在这里我不喜欢AWS术语)和部署是两个独立的部分。
启动您的ECS堆栈并运行。您可以通过CloudFormation和Auto-scaling组进行管理,这很好。只需将集群视为要部署到的平台,而不需要重新部署。
然后,对于CD,到目前为止,最简单的方法是更新服务定义以使用新的任务定义,并让ECS滚动为您更新容器。
每次启动任务时,ECS都会运行docker pull image:tag,即使它在本地具有该映像也可以确保它具有该image:tag的最新版本。因此,您所使用的图像标签确实无关紧要(无需在每个版本上都更改标签)。
这意味着您可以反复构建myimage:latest以轻松部署它。
您需要的是一个任务定义,其中image = myimage:latest。创建具有该任务定义的服务,并且每次ECS启动任务(您的服务实例)时,它将是您构建的最新“ myimage:latest”。
从那里,您只剩下一个难题,从CodeDeploy中,您可以调用某些东西(也许是lambda函数)来创建任务定义的新修订版并更新服务,而ECS将自动为该修订版创建新任务,并删除旧任务。
一个例子:
假设您已经创建了一个名为MyService的服务。您已将该服务配置为为任务定义MyTaskDefinition:1(修订版1)运行2个任务。在该任务定义中,您有一个容器定义,该图像被设置为“ myimage:latest”。
- 昨天您建立了myimage:latest,其ID(SHA)为365d8f7bf565。
- 您的容器实例ABC正在运行名为MyTaskDefinition - 1 -containerName-someLongId 的任务。当您检查该容器时,它正在运行图像“ sha256:365d8f7bf565 ..........”
- 您的另一个容器实例DEF正在运行另一个任务。它具有相似的名称(只是ID不同),但是运行的是同一张图片。
- 您将更改推送到存储库中。
- CodePipeline拾取更改,构建并将图像发布到ECR。
- 该新Docker映像也是myimage:latest,但其ID(SHA)为f7ec5e54ac96
- 现在,您需要在管道中添加一个步骤以使用Lambda函数和AWS NodeJS SDK来对集群进行一些调用:
- 创建一个新的任务定义(将与之前完全相同)。那将是MyTaskDefinition:2
- 更新您的MyService以使用MyTaskDefinition:2(而不是1)
- ECS将创建新任务。容器名称将为MyTaskDefinition - 2 -containerName-someLongId。当您检查这些容器时,您会看到它们将在运行“ sha256:f7ec5e54ac96 .......”。也许您在容器实例ABC上有2个任务,也许它们会被喷出(取决于您的服务的配置)
- 一段时间后,ECS将从ABC和DEF中删除旧任务MyTaskDefinition-1-containerName-someLongId。
注意:您实际上不需要创建新的任务定义。如果需要,可以取而代之的是检索服务的任务列表,然后手动将其逐一停止。在停止新任务之前,您应该等待ECS重新启动任务(即:停止第一个容器,等待ECS替换它,再停止第二个容器)。ECS重新启动容器时,它将抓取最新构建的myimage:latest,如前所述。我只是认为创建新的任务定义更容易且更不容易出错(无需等待和检查逻辑,如果您有新的任务定义,ECS将为您处理滚动更新)。