TL;DR:请参阅底部的编辑。
我正在尝试为我们公司正在迁移到的新环境设置持续部署。
我正在使用 aws cloudformation 堆栈来包含我的所有基础设施。当我创建堆栈时,我的实例通过其AWS::AutoScaling::LaunchConfiguration
设置正确初始化,特别是 - AWS::CloudFormation::Init
。(这在我的 cloudformation JSON 模板中)。该启动配置/初始化脚本将拉下我的应用程序的 docker 容器并在我的 ec2 实例上运行它AWS::AutoScaling::AutoScalingGroup
。
当我提交到我的仓库时,我有一个.travis-ci.yml
文件设置来运行aws update-stack
命令。这将使任何进入我的堆栈的新实例在 init 脚本运行时都将运行最新版本的 docker。
如何使当前的堆栈实例无效并在 0 停机时间内引入新的堆栈实例?
现在,正如我的问题所述,我收到了 503 错误。这发生在我的旧实例失效且我的新实例正在“预热”的时间段内。
我希望我的新实例能够预热并且无法访问,然后一旦它们预热并准备好就添加它们,然后删除旧实例。
以下是我目前遇到此问题时所做的事情:
aws cloudformation update-stack \
--stack-name <stack-name> \
--template-body file://<template-file>.json \
--profile <my-profile> \
--parameters <params>
然后,可以:
# This rans for each INSTANCE_ID in the current stack.
aws autoscaling set-instance-health \
--profile <my-profile> \
--instance-id ${INSTANCE_ID} \
--health-status Unhealthy \
--no-should-respect-grace-period
或者:
aws autoscaling detach-instances \
--auto-scaling-group-name <auto-scaling-group-name> \
--no-should-decrement-desired-capacity \
--profile <my-profile> \
--instance-ids <instance-1> <instance-2>
如果您能提供任何关于如何在交换自动缩放组实例时消除停机时间的见解,我将不胜感激!
我也愿意创建实例,然后通过命令将它们添加到自动缩放组attach-instances
。但是我不知道如何使用预先存在的实例配置这些实例AWS::AutoScaling::LaunchConfiguration
,并且我希望保持我的流程 DRY,并且不重复该功能两次。
谢谢您的帮助!
编辑:
我找到了一个直接的解决方案来替换我的自动扩展组中的 EC2 实例。直接从AWS 文档:
AutoScalingReplacingUpdate 和 AutoScalingRollingUpdate 策略仅当您执行以下一项或多项操作时才适用:
- 更改 Auto Scaling 组的 AWS::AutoScaling::LaunchConfiguration。
- 更改 Auto Scaling 组的 VPCZoneIdentifier 属性
- 更改 Auto Scaling 组的 LaunchTemplate 属性
- 更新包含与当前 LaunchConfiguration 不匹配的实例的 Auto Scaling 组。
我意识到对我来说最简单的解决方案是将自动缩放组的名称更改为类似于以下内容:
"WebServerGroup":{
"Type":"AWS::AutoScaling::AutoScalingGroup",
"Properties":{
"AutoScalingGroupName": {
"Fn::Sub" : "MyWebServerGroup-${UniqueDockerTag}"
},
...
},
"UpdatePolicy":{
"AutoScalingRollingUpdate":{
"MaxBatchSize":"50",
"MinSuccessfulInstancesPercent": 100,
"PauseTime": "PT5M",
"WaitOnResourceSignals": true
},
"AutoScalingReplacingUpdate" : {
"WillReplace" : "true"
}
}
}
这${UniqueDockerTag}
是传递给我的模板的一个参数,它对于每个构建都是唯一的,因此对于我的用例来说,这是一个简单而有效的解决方案。
创建新的 AutoScalingGroup,创建完成后,删除旧的 AutoScalingGroup。这一切都在 0 停机时间内完成。
希望这能有所帮助!干杯!
答案1
您尝试执行的操作看起来像是滚动部署和蓝绿部署的结合。
如果我是你,我会在尝试解决你的特定问题之前考虑几个其他选项。
1. 使用 ECS(或 EKS)集群
您不应该管理一个 AutoScaling 组(其中每个实例都主动拉取容器)并替换 EC2 实例来部署新版本,而应该考虑使用 ECS 集群和 ECS 服务。
ECS 集群在哪里您运行容器。ECS 集群也是 EC2 实例的 AutoScaling 组,但它们不会主动拉取容器映像,而是加入 ECS 集群并等待指示该做什么。
这就是 ECS 服务的用武之地 - ECS 服务描述什么您想要运行的容器,即您的容器定义、参数等。然后,它会在可用的 ECS 集群节点上调度容器(ECS 任务)。
部署应用程序的新版本就像更新 ECS 服务定义一样简单 - 它可以作为滚动更新、一体化等完成。它与 ALB、ELB 等无缝集成,您当然可以实现零停机发布。
使用 ECS 将消除每次发布容器时替换 EC2 实例的需要,只需替换实际的容器。
2. 正确的蓝绿部署
另一种选择是适当的蓝绿部署,您可以构建一个全新的环境,然后通常在 DNS 级别切换流量。
这意味着您每次发布的 CloudFormation 模板都将包含完整的基础架构(ASG、LaunchConfig、ALB 等),并且最终会得到两个堆栈实例 - 例如 app-blue 和 app-green。当 Blue 处于活动状态时,您可以随意拆除并重新部署 Green。测试它,一旦满意,将 DNS 从 Blue ALB 切换到 Green ALB。在下一个版本中,您可以对 Blue 重复相同的操作。
再次,这样做的好处是您拥有一条简单的回滚路径(如果绿色部署出现故障,只需将 DNS 切换回蓝色 ALB),并且它再次允许零停机时间。
更新:刚刚宣布AWS re:Invent 2018-ECS 的蓝/绿部署支持。这项新功能可能会方便您的ECS 服务无需每次都构建完整的环境。
希望有帮助:)