在EC2终止上调用脚本

时间:2018-05-09 05:21:21

标签: amazon-web-services amazon-ec2 lifecycle-hook

我必须在AWS自动缩放扩展事件期间采取某些操作.ec2实例应该能够将一些日志和报告保存到S3存储桶。这可能需要5到15分钟。

我已经有一个在终止时调用的脚本:

ln -s /etc/ec2-termination /etc/rc0.d/S01ec2-termination

然而,剧本在5分钟内突然结束。我正在考虑利用AWS LifeCycle钩子来延长EC2的使用寿命。 关于以类似于用户数据脚本的方式调用脚本的文档并不清楚。

有一些方法可以使用AWS lambda或SNS来接收通知。这可能会用于通知ec2。

但是,我想知道是否有一个更简单的解决方案来解决这个问题。有没有办法使用Lifecycle钩子注册脚本,并在渐变事件中调用。

6 个答案:

答案 0 :(得分:5)

没有

实例终止的事实在AWS基础架构中进行管理。 Auto Scaling没有能力进入"进入" EC2实例触发任何事情。

相反,您需要在实例上编写一些代码来检查实例是否处于终止状态,然后采取适当的措施。

一个例子可能是:

  • Lifecycle Hook通过Amazon SNS发送通知
  • Amazon SNS 触发AWS Lambda函数
  • Lambda函数可以向实例添加标记(例如,终止=是)
  • 每隔15秒触发一次EC2实例上的脚本,以检查与EC2实例关联的标记(正在运行的标记)。如果找到标记,则会触发关闭过程。

(请注意,在关机过程中脚本不会再次触发,否则它可能会每15秒尝试执行一次关机过程!)

或者,将关闭信息存储在Systems Manager Parameter Store或数据库中,但使用Tags似乎可以很好地扩展!

更新版本:

感谢raevilman的想法:

  • Lifecycle Hook通过Amazon SNS发送通知
  • Amazon SNS 触发AWS Lambda函数
  • Lambda函数调用AWS Systems Manager Run Command来触发实例上的代码

更简单!

答案 1 :(得分:4)

是的,您可以使用AWS Systems Manager在终止的EC2实例上运行shell脚本。

  1. 为您的Autoscaling组配置生命周期挂钩。您可以从EC2 console或CLI执行此操作:

    aws自动缩放put-lifecycle-hook
    --lifecycle-hook-name my-lifecycle-hook
    --auto-scaling-group-name My_AutoScalingGroup
    --lifecycle-transition自动缩放:EC2_INSTANCE_TERMINATING
    --default-result继续
    --region us-east-2

根据脚本运行的持续时间设置“心跳超时”值。 现在,当您的ASG扩大时,您的实例将进入Terminate:Wait状态,在此状态下您的脚本将运行。

  1. 设置一个CloudWatch事件,该事件在实例更改为Termination:Wait状态时触发,并以在您的实例上执行Shell脚本的System Manager Run Command为目标。使用console

另一种解决方案:当实例更改为“终止:等待”状态时,您的生命周期挂钩会将带有实例ID的消息发送到SQS。收到消息后,SQS会触发Lambda函数,该函数会将运行命令发送给系统管理器,以在终止实例上执行Shell脚本。

参考: 1 2 3

答案 2 :(得分:0)

根据您要实现的目标,使用这种方法,您只需要两件事,并且要简单得多):

  1. 生命周期挂钩向SQS发送通知
  2. 该应用读取SQS并执行操作

答案 3 :(得分:0)

以下是基于this article的使用生命周期挂钩,自动化和运行命令的解决方案:

Resources:
  MyTerminationHook:
    Type: AWS::AutoScaling::LifecycleHook
    Properties:
      AutoScalingGroupName: !Ref MyAutoScalingGroup
      DefaultResult: CONTINUE
      HeartbeatTimeout: 900
      LifecycleTransition: autoscaling:EC2_INSTANCE_TERMINATING

  MyTerminationDocument:
    Type: AWS::SSM::Document
    Properties:
      DocumentType: Automation
      Content:
        description: 'Run command before terminating instance'
        schemaVersion: '0.3'
        assumeRole: !GetAtt MyTerminationDocumentRole.Arn
        parameters:
          instanceId:
            type: String
        mainSteps:
          - name: RunCommand
            action: aws:runCommand
            inputs:
              DocumentName: AWS-RunShellScript
              InstanceIds:
                - '{{ instanceId }}'
              TimeoutSeconds: 60
              Parameters:
                commands: /etc/my-termination-script.sh
                executionTimeout: '900'
          - name: TerminateInstance
            action: aws:executeAwsApi
            inputs:
              Api: CompleteLifecycleAction
              AutoScalingGroupName: !Ref MyAutoScalingGroup
              InstanceId: '{{ instanceId }}'
              LifecycleActionResult: CONTINUE
              LifecycleHookName: !Ref MyTerminationHook
              Service: autoscaling

  MyTerminationRule:
    Type: AWS::Events::Rule
    Properties:
      EventPattern:
        source:
          - aws.autoscaling
        detail-type:
          - EC2 Instance-terminate Lifecycle Action
        detail:
          AutoScalingGroupName:
            - !Ref MyAutoScalingGroup
      Targets:
        - Id: my-termination-document
          Arn: !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${MyTerminationDocument}:$DEFAULT'
          RoleArn: !GetAtt MyTerminationRuleRole.Arn
          InputTransformer:
            InputPathsMap:
              instanceId: '$.detail.EC2InstanceId'
            InputTemplate: '{"instanceId":[<instanceId>]}'

  MyTerminationRuleRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: start-automation
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - ssm:StartAutomationExecution
                Resource: !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:automation-definition/${MyTerminationDocument}:$DEFAULT'

  MyTerminationDocumentRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: ssm.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: run-command-and-complete-lifecycle
          PolicyDocument:
            Version: 2012-10-17
            Statement:
              - Effect: Allow
                Action:
                  - autoscaling:CompleteLifecycleAction
                Resource: !Sub 'arn:aws:autoscaling:${AWS::Region}:${AWS::AccountId}:autoScalingGroup:*:autoScalingGroupName/${MyAutoScalingGroup}'
              - Effect: Allow
                Action:
                  - ssm:DescribeInstanceInformation
                  - ssm:ListCommands
                  - ssm:ListCommandInvocations
                Resource: '*'
              - Effect: Allow
                Action:
                  - ssm:SendCommand
                Resource: 'arn:aws:ssm:*::document/AWS-RunShellScript'
              - Effect: Allow
                Action:
                  - ssm:SendCommand
                Resource: !Sub 'arn:aws:ec2:${AWS::Region}:${AWS::AccountId}:instance/*'

答案 4 :(得分:0)

我知道这是一个迟到的答案

但是对于新的

在这里您可以找到满足您需求的 aws 博客

https://aws.amazon.com/blogs/infrastructure-and-automation/run-code-before-terminating-an-ec2-auto-scaling-instance/

答案 5 :(得分:0)

只是对我之前的评论进行更正。如果实例因 Auto Scaling 事件而终止,则 SSM 运行命令将对 Autoscaling 组中的实例起作用,而不是手动终止实例。