无停机 AWS + ECS Cloudformation
No Down-Time AWS + ECS Cloudformation
伙计们。
我有一个小问题,到目前为止我还没有解决。
事情是这样的:我有一个在 ECS 上运行的小应用程序。
为了创建应用程序,我创建了一个 ASG 并在 LaunchConfig 上将实例注册到我的 ECS 集群.后来,我在我的ASG前面放了一个ALB,这样我的应用程序就可以在Internet上使用了;到目前为止一切都很好。当我想对我的 ECS 实例进行更新时,问题就来了。我的停机时间很短,只有 20 秒。
嗯,这不是完全停机,但发生的是我的 LB 在更新期间不断向我的 ECS1 发送请求滚动,所以我在浏览器上得到了一个非常好的 502。当然,一旦更新完成,一切都会好起来的。当更新我的 ECS2 实例时,同样的 502 也会发生。如果我刷新,我会得到一个可用的应用程序;如果我第二次刷新,我会得到 502,因为正如我所说,ALB 不断向我的 IN 发送请求PROGRESS(滚动更新)ECS 实例。
所以,我想我可以在更新 ECS 实例时注销它,然后,当它完成时,我可以重新注册它。但我正在使用 CloudFormation 来滚动更新,我真的不想手动做事。
我当前的健康检查每 30 秒进行一次,以便目标组将某个实例视为不健康,因此停止向其发送请求。
我怎样才能完成它?
谢谢!
有一个很棒的 article on the AWS blog 解释了如何完成此操作。他们甚至使用 CloudFormation 作为示例,因此不涉及手动步骤。
他们基本上使用与 SNS 和 Lambda 配对的 Autoscaling Groups Lifecycle hook 在 ASG 实例停止服务时触发连接耗尽。最重要的是,这在 CloudFormation 触发滚动更新时也有效。
They open sourced the solution on GitHub,你可以使用整个东西,也可以根据需要复制有趣的部分。
我找到了答案,希望这对以后的人有所帮助。
避免停机的关键是将LB注册到ECS服务,这样LB就会为我们做脏活。在容器更新之前,LB 将耗尽实例,因此不会向它发送请求。同时,只有一个实例,它是一个健康的实例。
当另一个实例耗尽时,LB 只向健康的实例发送请求。一旦实例被耗尽并从 LB 中注销,更新将在耗尽的实例上滚动。凉爽的!!不是吗?
因此,一旦完成更新,LB 将其重新注册,等待它通过健康检查,然后再次开始发送请求。
这个更新完之后,LB就要开始对剩下的那个做同样的事情了(Drain it, update it, and register it back)
我将与您分享对我有用的片段:
Resources:
ECSServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: ecs-service
PolicyDocument:
Statement:
- Effect: Allow
Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets',
'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress']
Resource: '*'
Service:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
DesiredCount: !Ref DesiredCount
TaskDefinition: !Ref TaskDefinition
LoadBalancers:
- ContainerName: nginx
ContainerPort: '80'
TargetGroupArn: !Ref TargetGroupARN
Role: !Ref 'ECSServiceRole'
DeploymentConfiguration:
MaximumPercent: 100
MinimumHealthyPercent: 50
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
...
从服务中调用 LB 确实有效。您还应该考虑设置一个 MinimumHealthyPercent 来告诉服务有多少实例必须始终运行并且 运行.
希望对您有所帮助!
伙计们。
我有一个小问题,到目前为止我还没有解决。 事情是这样的:我有一个在 ECS 上运行的小应用程序。 为了创建应用程序,我创建了一个 ASG 并在 LaunchConfig 上将实例注册到我的 ECS 集群.后来,我在我的ASG前面放了一个ALB,这样我的应用程序就可以在Internet上使用了;到目前为止一切都很好。当我想对我的 ECS 实例进行更新时,问题就来了。我的停机时间很短,只有 20 秒。
嗯,这不是完全停机,但发生的是我的 LB 在更新期间不断向我的 ECS1 发送请求滚动,所以我在浏览器上得到了一个非常好的 502。当然,一旦更新完成,一切都会好起来的。当更新我的 ECS2 实例时,同样的 502 也会发生。如果我刷新,我会得到一个可用的应用程序;如果我第二次刷新,我会得到 502,因为正如我所说,ALB 不断向我的 IN 发送请求PROGRESS(滚动更新)ECS 实例。
所以,我想我可以在更新 ECS 实例时注销它,然后,当它完成时,我可以重新注册它。但我正在使用 CloudFormation 来滚动更新,我真的不想手动做事。
我当前的健康检查每 30 秒进行一次,以便目标组将某个实例视为不健康,因此停止向其发送请求。
我怎样才能完成它?
谢谢!
有一个很棒的 article on the AWS blog 解释了如何完成此操作。他们甚至使用 CloudFormation 作为示例,因此不涉及手动步骤。
他们基本上使用与 SNS 和 Lambda 配对的 Autoscaling Groups Lifecycle hook 在 ASG 实例停止服务时触发连接耗尽。最重要的是,这在 CloudFormation 触发滚动更新时也有效。
They open sourced the solution on GitHub,你可以使用整个东西,也可以根据需要复制有趣的部分。
我找到了答案,希望这对以后的人有所帮助。
避免停机的关键是将LB注册到ECS服务,这样LB就会为我们做脏活。在容器更新之前,LB 将耗尽实例,因此不会向它发送请求。同时,只有一个实例,它是一个健康的实例。
当另一个实例耗尽时,LB 只向健康的实例发送请求。一旦实例被耗尽并从 LB 中注销,更新将在耗尽的实例上滚动。凉爽的!!不是吗?
因此,一旦完成更新,LB 将其重新注册,等待它通过健康检查,然后再次开始发送请求。 这个更新完之后,LB就要开始对剩下的那个做同样的事情了(Drain it, update it, and register it back)
我将与您分享对我有用的片段:
Resources:
ECSServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [ecs.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
Policies:
- PolicyName: ecs-service
PolicyDocument:
Statement:
- Effect: Allow
Action: ['elasticloadbalancing:DeregisterInstancesFromLoadBalancer', 'elasticloadbalancing:DeregisterTargets',
'elasticloadbalancing:Describe*', 'elasticloadbalancing:RegisterInstancesWithLoadBalancer',
'elasticloadbalancing:RegisterTargets', 'ec2:Describe*', 'ec2:AuthorizeSecurityGroupIngress']
Resource: '*'
Service:
Type: AWS::ECS::Service
Properties:
Cluster: !Ref Cluster
DesiredCount: !Ref DesiredCount
TaskDefinition: !Ref TaskDefinition
LoadBalancers:
- ContainerName: nginx
ContainerPort: '80'
TargetGroupArn: !Ref TargetGroupARN
Role: !Ref 'ECSServiceRole'
DeploymentConfiguration:
MaximumPercent: 100
MinimumHealthyPercent: 50
TaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
...
从服务中调用 LB 确实有效。您还应该考虑设置一个 MinimumHealthyPercent 来告诉服务有多少实例必须始终运行并且 运行.
希望对您有所帮助!