我正在使用user_data对ECS中使用的主机进行初始配置以运行容器。我希望能够告诉AWS ECS在更新user_data后将容器迁移到新创建的主机。我怎么能这样做?
我正在使用Terraform进行AWS基础架构部署。
答案 0 :(得分:5)
我不认为ECS有内置的方法来做到这一点。结果,它通常需要一个相当繁琐的&手动过程(尽管可以编写脚本)。有几种不同的方法可以做到这一点,但这通常是最简单的方法:
user_data
。terraform apply
。user_data
的每个EC2实例:
user_data
代替已终止的EC2实例。完成此过程后,ASG中的所有实例都将运行新的user_data
。请注意,只要符合以下条件,就可以使用ECS任务的零停机时间来完成此操作:
如果您无法满足这些要求,那么您可能会遇到一些停机时间,或者您可能需要寻求一个更加混乱的选项,其中包括将ASG的大小加倍,等待新的EC2实例(将具有新的user_data
)在ASG中部署,将ECS任务的数量增加一倍,等待部署新的ECS任务(它们通常将部署到新的EC2实例上),然后再将每个任务减少一半(理论上) ,旧的ECS任务和旧的EC2实例将被终止,只留下新的EC2实例。
答案 1 :(得分:1)
虽然Yevgeniy' answer是正确的,但是如果重新创建实例,则无法让Terraform直接将容器迁移到新实例。使用Terraform的资源lifecycle configuration可以使用更清晰的选项。
假设您使用自动缩放组来支持您的ECS主机,您可以执行以下操作:
data "aws_ami" "ubuntu" {
most_recent = true
filter {
name = "name"
values = ["ubuntu/images/ebs/ubuntu-trusty-14.04-amd64-server-*"]
}
filter {
name = "virtualization-type"
values = ["paravirtual"]
}
owners = ["099720109477"] # Canonical
}
resource "aws_launch_configuration" "as_conf" {
name_prefix = "terraform-lc-example-"
image_id = "${data.aws_ami.ubuntu.id}"
instance_type = "t1.micro"
lifecycle {
create_before_destroy = true
}
}
resource "aws_autoscaling_group" "bar" {
name = "${aws_launch_configuration.as_conf.name}"
launch_configuration = "${aws_launch_configuration.as_conf.name}"
lifecycle {
create_before_destroy = true
}
}
(摘自Terraform' s launch configuration docs)
现在,当启动配置发生更改时,例如,如果用户数据或正在使用的AMI发生更改,这将强制Terraform创建新的启动配置,这会因为依赖于名称而强制启动新的自动扩展组
由于Terraform正在使用create_before_destroy
生命周期配置,它将在销毁之前创建新的启动配置和ASG。在上述简单设置中,只要AWS认为单个实例健康,ASG就会返回完成。
不幸的是,只显示EC2实例健康状况,而不是它成功运行任务。正如对此答案的评论中所提到的,ECS不会将任务自动平衡到集群中的新实例,因此Terraform将在旧的ASG中销毁运行ECS任务的实例,然后ECS可以将它们重新安排到新的ASG上造成停电的情况。
要解决此问题(并且还允许实例失败并通常以更好的方式替换),您可以使用ASG lifecycle hooks在实例标记为终止但在实际终止之前执行某些操作
有一个很好的AWS blog post关于做到这一点并且有一些[示例Lambda代码]响应钩子以排出标记为终止的容器实例,然后再完成生命周期钩子,然后允许ASG终止实例。排空容器实例后,ECS将自动将最少数量的健康任务重新安排到非排水实例(在新的ASG中)。
如果您的ECS任务已注册到负载均衡器,则一旦运行一组新任务,ECS将从负载均衡器取消注册任务,然后任务将在负载均衡器连接期间保留排水超时期限。