没有停机时间的AWS + ECS Cloudformation

问题描述 投票:0回答:2

家伙。

我有一个小问题,到目前为止我还没有解决。问题是:我有一个在ECS上运行的应用程序。为了创建应用程序,我创建了一个ASG,并在LaunchConfig上将实例注册到我的ECS集群。后来,我在我的ASG前放了一个ALB,这样我的应用程序就可以上网了;到目前为止都很好。当我想在我的ECS实例上滚动更新时,问题出现了。我的停机时间很短,只有20秒。

好吧,这不是一个完整的停机时间,但发生的事情是我的LB在更新滚动时不断向我的ECS1发送请求,所以我在浏览器上得到了相当不错的502。当然,一旦更新完成,一切顺利。当我的ECS2实例被更新时,会发生相同的502。如果我刷新,我得到一个工作的应用程序;如果我第二次刷新,我会得到我的502,因为正如我所说,ALB不断向我的IN PROGRESS(滚动更新)ECS实例发送请求。

所以,我想我可以在它被提升时取消注册ECS实例,然后,当它完成后,我可以将其注册回来。但我正在使用CloudFormation来推送更新,我真的不想手工做。

我目前的健康检查每30秒完成一次,以便目标组将实例视为不健康,因此,停止向其发送请求。

我怎么能完成它?

谢谢!

amazon-web-services docker amazon-ec2 amazon-cloudformation elastic-load-balancer
2个回答
0
投票

有一个伟大的article on the AWS blog解释如何实现这一目标。他们甚至使用CloudFormation作为例子,所以不涉及手动步骤。

它们基本上利用与SNS和Lambda配对的Autoscaling Groups Lifecycle hook来在ASG实例停止服务时触发连接耗尽。最重要的是,当CloudFormation触发滚动更新时,这也适用。

They open sourced the solution on GitHub,你可以使用整个东西或只是根据需要复制有趣的部分。


0
投票

我找到了答案,我希望这有助于将来的某些人。

避免停机的关键是将LB注册到ECS服务,以便LB为我们做肮脏的工作。在容器更新之前,LB将耗尽实例,因此不会向其发送请求。同时,只有一个实例,这是一个健康的实例。

当另一个实例耗尽时,LB仅向健康请求发送请求。一旦实例耗尽并从LB中取消注册,更新将在已耗尽的实例上滚动。凉!!不是吗?

因此,一旦完成更新,LB会将其注册回来,等待直到通过运行状况检查,然后再次开始发送请求。在更新之后,LB将开始对剩下的那个做同样的事情(将其排空,更新并重新注册)。

我将与您分享为我制作诀窍的片段:

 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来告诉服务必须始终启动和运行多少个实例。

希望能帮助到你!

© www.soinside.com 2019 - 2024. All rights reserved.