在EC2终止上调用脚本

rah*_*pta 2 amazon-ec2 amazon-web-services 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钩子注册一个脚本,这个钩子在一个scale-in事件中被调用.

yur*_*rez 8

以下是基于本文的使用 Lifecycle Hooks、自动化和 Run Command 的解决方案:

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/*'
Run Code Online (Sandbox Code Playgroud)

部署这些所需的权限是

          - Sid: CreateDocument
            Effect: Allow
            Action:
              - "ssm:CreateDocument"
              - "ssm:GetDocument"
              - "ssm:DeleteDocument"
              - "ssm:ListTagsForResource"
            Resource: !Sub "arn:aws:ssm:<...>"
          - Sid: InstallLifecycleHook
            Effect: Allow
            Action:
              - "autoscaling:DeleteLifecycleHook"
              - "autoscaling:CreateLifecycleHook"
            Resource: !Sub "arn:aws:autoscaling:<...>"
          - Sid: ManageRules
            Effect: Allow
            Action:
              - "events:PutRule"
              - "events:ListRules"
              - "events:DescribeRule"
              - "events:DeleteRule"
              - "events:PutTargets"
              - "events:RemoveTargets"
            Resource: !Sub "arn:aws:events:<...>"
Run Code Online (Sandbox Code Playgroud)

可能还有更多;这些是我必须添加到我们现有的部署策略中的内容。它们也可能并非全部都是必需的,但我厌倦了重新部署和零碎添加它们,因此我添加了一些规则作为有根据的猜测。


Joh*_*ein 6

没有.

实例终止的事实在AWS基础架构中进行管理.Auto Scaling无法触及"进入"EC2实例以触发任何操作.

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

一个例子可能是:

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

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

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

更新后的版本:

感谢raevilman的想法:

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

更简单!


Shi*_*hur 5

是的,您可以使用 AWS 系统管理器在终止 EC2 实例上运行 shell 脚本。

  1. 为您的自动缩放组配置生命周期挂钩。您可以从EC2 控制台或 CLI执行此操作:

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

根据脚本运行所需的持续时间设置心跳超时值。现在,当您的 ASG 缩减时,您的实例将进入 Terminate:Wait 状态,在此期间您的脚本将运行。

  1. 设置一个 CloudWatch 事件,该事件在实例更改为 Terminating:Wait 状态时触发,它的目标是在您的实例上执行 shell 脚本的系统管理器运行命令。使用控制台

替代解决方案:当实例更改为 Terminating:Wait 状态时,您的 Lifecycle Hook 会向 SQS 发送带有 Instance-ID 的消息。SQS 在收到消息时触发 Lambda 函数,该函数将运行命令发送到系统管理器以在终止实例上执行 shell 脚本。

参考文献: 1 2 3