由于正在使用端口,我无法将新容器部署到我的 ECS 集群

I can't deploy a new container to my ECS cluster because of ports in use

我的服务使用的任务定义正在拉取我的图像的 "latest" 标记版本。

当我更新我的服务时 "force new deployment" 我查看事件并看到:

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

然后我去了我的集群并停止了所有任务。

然后回到我的服务并再次更新强制新部署。这似乎奏效了

我每次要部署新映像时都必须停止所有任务并更新服务吗?还是有 "right" 方法来做到这一点?

编辑:因此,如果我停止一项任务,该服务将自动替换它。所以我可以更新我的服务和 "force new deploy" 然后一次停止一个任务以获得一种滚动更新。不确定是否有超越我自己的脚本的自动化功能

只是为了跟进,如答案中所述,我只需要使用动态端口映射。

最初,当我第一次开始时,我没有负载均衡器,所以我直接访问 EC2 实例来访问 运行 容器。当然,为了做到这一点,我必须在 EC2 主机上公开一个静态端口。

我添加了一个负载平衡器,但保留了静态端口映射,不了解动态端口映射的工作原理。我所要做的就是更改我的任务定义以将主机端口设置为“0”。现在我在主机上没有静态端口映射,NLB 为我进行路由并按预期部署工作

在使用 ECS(或任何其他编排器)时,我们鼓励您使用 Dynamic Port Mapping

基本上 ECS 会为您的容器分配一个随机的未分配端口。 ECS 然后提供检索该端口号的方法,使用代理内省 API 或 docker 客户端本身。但是我不会尝试检索端口,而是依赖应用程序负载均衡器 (ALB),它允许您使用单个端点独立于其动态分配的端口访问任何目标容器。更新服务时,ALB 将无缝过渡到最新版本的容器,不会造成任何中断。

最后,在容器内部,本地端口将保持不变,因此您不必以不同方式处理事情。

如果没有动态端口,每个容器只能部署一个服务实例,因为该实例使用的端口不能被任何其他实例使用。当您更新服务时,它会尝试重新启动其所有实例,如果在单个 EC2 容器上启动了多个实例,则启动将失败。

最好在 ECS 集群中使用 docker 具有动态端口映射的容器。

当同一微服务(容器)的新实例由于自动缩放而启动时,我也遇到了同样的问题,因为每个微服务的端口都是固定的并在 application.yml 中配置,并且当同一服务在同一时间启动时EC2 由于自动缩放然后它尝试获取其先前实例已使用的相同端口(例如,如果我在端口 3102 上将 X 作为微服务 运行ning,如果同一服务的另一个实例由于自动缩放而启动然后它可能会在不同的 EC2 机器上或在 ECS 集群中的同一台 EC2 机器上启动,但 ECS 根据 CPU 和 RAM 的可用性决定在哪里启动新的微服务实例,如果新实例在不同的 EC2 机器上启动,则不会问题是因为端口是免费的,但如果实例将在同一台 ec2 机器上启动,它将无法启动并大喊该端口已在使用中)

为了解决这个问题,我们只需要更新我们的 ECS 集群的任务定义,不需要更改图像,必须在任务定义中启用 动态端口映射,以便任意数量的微服务实例可以运行 在同一台 Ec2 机器上

没有动态端口映射任务定义配置将是

  1. 网络模式 - 主机
  2. 在端口映射中,容器端口将是:application.yml
  3. 中配置的应用程序端口

用于在 ECS 中启用动态端口映射

  • 更改网络模式:网桥
  • 配置端口映射,使主机端口为0,容器端口等同于application.yml
  • 中配置的应用程序端口

虽然其他答案是正确的,但我认为它们不适用于您遇到的问题。我这样说是因为这也是我的团队面临的一个问题,并且与尝试在同一实例上启动多个容器没有任何关系——如果我理解正确的话,你只是在尝试替换现有的容器更新的任务定义。如果你想把同一个容器的多个副本放在一个盒子上,一定要看看其他答案的建议(除了下面的细节),但对于滚动部署,动态端口绝不是必需的。

[[ 完整性的旁注:您的强制部署可能引发了您发布的错误,因为 EC2 只需要一段时间来清理 ECS 停止的资源。如果您试图强制停止/启动任务,您会看到同样的问题——我们在尝试重新启动配置为分配 >50% 的可用实例内存的容器时看到了类似的错误。在完全清理 EC2 实例并将其报告回 ECS 之前,您将遇到这些类型的资源错误。我已经看到这需要超过 5 分钟的时间。 ]]

关于您的问题,不幸的是目前 AWS 没有任何出色的 built-in 机制来执行任务的滚动重启。但是,您 可以 滚动 deploys.

您可能已经知道,您的服务依赖于指定的任务定义。请注意,它依赖于 任务定义编号 ,并且不像 EC2 实例那样关心 容器标签

以下设置是启用滚动部署的神奇之处;您可以在服务设置中找到这些配置选项。

为了能够进行滚动部署,您必须至少有 2 个任务 运行ning。

  • 任务数量 -- 您的服务想要的任务数量 运行 (n)
  • 最小健康百分比 -- 部署新任务时 n 的最小健康百分比
  • 最大百分比 -- 部署新任务时可以添加的最大百分比 n

举个真实的例子,假设您有以下配置:

Number of tasks: 3
Minimum healthy percent:  50
Maximum percent: 100

如果您更改服务指向的任务定义,它将启动滚动部署。我们有 3 运行ning 任务,但允许 >=50% 健康。 ECS 将终止您的一项任务,使健康百分比下降到 66%,仍然高于 50%。新任务出现后,服务再次处于 100%,ECS 可以继续将部署滚动到下一个实例。

同样,如果您的配置为 minimum % == 100,并且 maximum % == 150(假设您有容量),ECS 将 启动一个额外的任务;一旦启动,您就有了 133% 的健康百分比,并且它可以安全地终止其中一项旧任务。此过程一直持续到您的新任务完全部署为止。

首先,将 desired-count 设置为 0

aws ecs update-service --cluster cluster_name --service service_name --desired-count 0

执行以下命令后,可以动态查看运行ning容器实例的数量

aws ecs describe-services --cluster cluster_name --service service_name

然后运行下面的命令

aws ecs update-service --cluster cluster_name --service service_name --desired-count 1

毫无疑问,这是最好的选择,因为 ALB 速度慢且有缺陷。谢谢@erncnerky

首先,将desired-count设置为0

aws ecs update-service --cluster cluster_name --service service_name --desired-count 0 在下面的命令之后,您可以动态检查 运行ning 容器实例的数量

aws ecs describe-services --cluster cluster_name --service service_name 然后运行下面的命令

aws ecs update-service --cluster cluster_name --service service_name --desired-count 1 分享 编辑 跟随 编辑于 2019 年 8 月 23 日 8:58 2019 年 8 月 22 日在 14:26

回答

erncnerky 35233个银徽章99个铜徽章 这是可以做到的。但是如果你有不同的环境和不同的 desired-count 怎么办? – 瓦西里·沙库诺夫 2019 年 11 月 26 日 15:16