我的服务使用的任务定义是拉动我图像的“最新”标记版本。
当我更新我的服务并“强制进行新部署”时,我会查看事件并看到:
service MYSERVICE was unable to place a task because no container instance met all of its requirements. The closest matching container-instance .... is already using a port required by your task
然后我去了我的群集并停止了所有任务。
然后返回我的服务并再次强制新部署更新。这似乎有效
每次要部署新映像时,是否必须停止所有任务并更新服务?或者有“正确”的方式来做到这一点吗?
只是跟进,正如答案中所述,我只需要使用动态端口映射。
最初,当我第一次启动时,我没有负载均衡器,因此我直接访问EC2实例以访问正在运行的容器。当然,为了做到这一点,我不得不在EC2主机上公开一个静态端口。
我添加了一个负载均衡器,但保留了静态端口映射,而不了解动态端口映射的工作原理。我所要做的就是更改我的任务定义,将主机端口设置为“0”。现在我在主机上没有静态端口映射,NLB为我做路由并按预期部署工作
答案 0 :(得分:3)
使用ECS(或任何其他协调器)时,建议您使用Dynamic Port Mapping。
基本上ECS会为您的容器分配一个随机的未分配端口。然后,ECS使用代理instrospection API或docker客户端本身提供检索该端口号的方法。但是我不会尝试检索端口,而是依赖于应用程序负载均衡器(ALB),它允许您使用单个端点独立于其动态分配的端口访问任何目标容器。更新服务时,ALB将无缝地转换到最新版本的容器,而不会中断。
最后,在容器内部,本地端口将保持不变,因此您不必以不同方式处理事物。
答案 1 :(得分:3)
如果没有动态端口,则每个容器只能部署一个服务实例,因为实例使用的端口不能被任何其他实例使用。更新服务时,它将尝试重新启动其所有实例,如果在单个EC2容器上启动了多个实例,则启动将失败。
最好在ECS集群中使用具有动态端口映射的docker容器。
答案 2 :(得分:3)
虽然其他答案都是正确的,但我认为它们不适用于您所遇到的问题。我之所以这么说,是因为这也是我的团队面临的一个问题,并且与尝试在同一个实例上启动多个容器没有任何关系 - 如果我理解正确的话,你就是这样的尝试从更新的任务定义中替换现有容器。如果要将同一容器的多个副本放在一个盒子上,请务必查看其他答案中的建议(除了下面的详细信息),但对于滚动部署,不需要动态端口。
[[完整性附注:您的强制部署可能会抛出您发布的错误,因为EC2只需要一段时间来清理ECS停止的资源。如果您尝试强制停止/启动任务,您会看到同样的问题 - 我们在尝试重新启动配置为分配> 50%的容器时看到了类似的错误可用的实例内存。在完全清理EC2实例并报告回ECS之前,您将获得这些类型的资源错误。我已经看到这需要花费5分钟。 ]
对于您的问题,遗憾的是,目前还没有来自AWS的任何强大的内置机制来执行滚动重启任务。但是, 可以滚动部署。
您可能已经意识到,您的服务依赖于指定的任务定义。请注意,它依赖于任务定义编号,并且不像EC2实例那样关心容器标记。
以下设置是启用滚动部署的神奇之处;您可以在服务设置中找到这些配置选项。
为了能够进行滚动部署,您必须至少运行2个任务。
n
的最低健康百分比 n
的最大百分比 因此,对于一个真实的例子,我们假设你有以下配置:
Number of tasks: 3
Minimum healthy percent: 50
Maximum percent: 100
如果更改服务所指向的任务定义,它将启动滚动部署。我们有3
个正在运行的任务,但允许>=50%
健康。 ECS将终止您的一项任务,使健康%降至66%
,仍高于50%
。一旦新任务出现,服务再次位于100%
,ECS可以继续将部署滚动到下一个实例。
同样,如果您的配置位于minimum % == 100
和maximum % == 150
(假设您有容量),则ECS将启动其他任务;一旦它上升,你的健康百分比为133%
,它可以安全地杀死其中一个旧任务。此过程将继续,直到您的新任务完全部署完毕。
答案 3 :(得分:1)
当由于自动扩展而启动相同微服务(容器)的新实例时,我也遇到了同样的问题,因为每个微服务的端口都是在application.yml中修复和配置的,并且当同一服务由于自动扩展而在相同的EC2上启动时然后它尝试获取其先前实例已经使用的相同端口(例如,如果我在端口3102上运行X作为微服务,如果由于aotoscaling而相同服务的另一个实例起来,那么它可能会在不同的EC2机器上运行或者在ECS集群中的相同EC2机器上,但是ECS根据CPU和RAM的可用性决定在哪里启动新的微服务实例,如果新实例在不同的EC2机器上运行,那么没有问题,因为端口将是空闲的,但是如果实例将起来在相同的ec2机器上它不会启动并喊出该端口已经在使用中)
为了解决这个问题,我们只需要更新ECS集群的任务定义,不需要在映像中进行任何更改,必须在任务定义中启用动态端口映射,以便任意数量的微服务实例可以在同一个Ec2上运行机强>
没有动态端口映射任务定义配置将
答案 4 :(得分:1)
首先,将期望计数设置为0
aws ecs update-service --cluster cluster_name --service service_name --desired-count 0
在执行以下命令后,您可以动态检查正在运行的容器实例的数量
aws ecs describe-services --cluster cluster_name --service service_name
然后在命令下运行
aws ecs update-service --cluster cluster_name --service service_name --desired-count 1