没有停机时间的AWS + ECS Cloudformation

时间:2017-12-28 21:13:21

标签: amazon-web-services docker amazon-ec2 amazon-cloudformation elastic-load-balancer

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

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

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

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

我怎么能完成它?

谢谢!

2 个答案:

答案 0 :(得分:0)

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

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

They open sourced the solution on GitHub,您可以使用整个内容,也可以根据需要复制有趣的部分。

答案 1 :(得分: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来告诉服务必须始终启动并运行多少个实例。

希望它有所帮助!