ลบเทมเพลตหลังจากผ่านไป 5 นาที

เทมเพลตนี้สร้างตัวแปรพารามิเตอร์ SSM จากนั้นพยายามลบออกหลังจากผ่านไป 5 นาที เทมเพลตที่ขึ้นต่อกันไม่สามารถลบฟังก์ชันได้ ดังนั้นทั้งสองสแต็กจึงไม่สามารถลบได้ ฉันต้องการทราบวิธีลบสแต็คหลังจากเวลาผ่านไป (ในกรณีนี้ 5 นาที)

AWSTemplateFormatVersion: '2010-09-09'
Description: Demo stack, creates one SSM parameter and gets deleted after 5 minutes.
Resources:
  DemoParameter:
    Type: "AWS::SSM::Parameter"
    Properties:
      Type: "String"
      Value: "date"
      Description: "SSM Parameter for running date command."
      AllowedPattern: "^[a-zA-Z]{1,10}$"
  DeleteAfterTTLStack:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      TemplateURL: 'https://datameetgeobk.s3.amazonaws.com/cftemplates/cfn-stack-ttl_updated.yaml.txt'
      Parameters:
        StackName: !Ref 'AWS::StackName'
        TTL: '5'

ฉันได้รับเทมเพลตนี้จาก:

https://aws.amazon.com/blogs/infrastructure-and-automation/scheduling-automatic-deletion-of-aws-cloudformation-stacks/


person shantanuo    schedule 19.12.2019    source แหล่งที่มา
comment
เป้าหมายที่แท้จริงของคุณคืออะไร? คุณเพียงต้องการสร้างค่า 'ชั่วคราว' ในที่เก็บพารามิเตอร์หรือไม่ จำเป็นต้องทำสิ่งนี้ผ่าน CloudFormation แน่นอนหรือไม่ โปรดบอกเราเพิ่มเติมเกี่ยวกับกรณีการใช้งานที่กว้างขึ้นของคุณ   -  person John Rotenstein    schedule 20.12.2019
comment
ฉันซื้ออินสแตนซ์ได้ทันทีโดยใช้เทมเพลต CFN ฉันต้องการลบอินสแตนซ์หลังจากผ่านไป 1 หรือ 2 วัน สิ่งนี้จะทำโดยอัตโนมัติ! ตามความรู้ของฉัน ไม่มีวิธีใดที่จะยุติอินสแตนซ์ที่ทำงานอยู่ (เฉพาะจุดหรืออย่างอื่น) หลังจากผ่านไป 48 ชั่วโมงอย่างแน่นอน ขวา?   -  person shantanuo    schedule 06.01.2020


คำตอบ (2)


ดูเหมือนว่าจะมีปัญหามากมายกับไฟล์เทมเพลตของโพสต์บนบล็อก คุณไม่สามารถลบสแต็กได้เนื่องจากบทบาท iam ในสแต็กที่ซ้อนกันไม่มีสิทธิ์เพียงพอที่จะลบทรัพยากรทั้งหมดในสแต็ก (lambda, บทบาท iam, เหตุการณ์, พารามิเตอร์ ssm ฯลฯ)

หากต้องการแก้ไขข้อผิดพลาดนี้ด้วยสิทธิ์ คุณจะต้องสร้างเทมเพลตที่ซ้อนกันใหม่พร้อมสิทธิ์เพิ่มเติมสำหรับ DeleteCFNLambdaExecutionRole ของคุณ ฉันได้ให้การอัปเดตด้วยนโยบายที่มีการจัดการ arn:aws:iam::aws:policy/AdministratorAccess แต่ฉันขอแนะนำเป็นอย่างยิ่ง ให้ค้นหาสิทธิ์ขั้นต่ำในการลบทรัพยากรของคุณ นโยบายที่ฉันเพิ่มนั้น ไม่ใช่ แนวทางปฏิบัติที่ดี แต่เนื่องจากฉันไม่ทราบกรณีการใช้งานทั้งหมดของคุณ จึงเป็นวิธีเดียวที่จะรับประกันว่าจะลบทุกอย่าง

AWSTemplateFormatVersion: '2010-09-09'
Description: Schedule automatic deletion of CloudFormation stacks
Metadata:
  AWS::CloudFormation::Interface:
    ParameterGroups:
      - Label:
          default: Input configuration
        Parameters:
          - StackName
          - TTL
    ParameterLabels:
      StackName:
        default: Stack name
      TTL:
        default: Time-to-live
Parameters:
  StackName:
    Type: String
    Description: Stack name that will be deleted.
  TTL:
    Type: Number
    Description: Time-to-live in minutes for the stack.
Resources:
  DeleteCFNLambdaExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service: ["lambda.amazonaws.com"]
          Action: "sts:AssumeRole"
      Path: "/"
      ManagedPolicyArns:
        - 'arn:aws:iam::aws:policy/AdministratorAccess'
  DeleteCFNLambda:
    Type: "AWS::Lambda::Function"
    DependsOn:
      - DeleteCFNLambdaExecutionRole
    Properties:
      FunctionName: !Sub "DeleteCFNLambda-${StackName}"
      Code:
        ZipFile: |
          import boto3
          import os
          import json

          stack_name = os.environ['stackName']

          def delete_cfn(stack_name):
              try:
                  cfn = boto3.resource('cloudformation')
                  stack = cfn.Stack(stack_name)
                  stack.delete()
                  return "SUCCESS"
              except:
                  return "ERROR" 

          def handler(event, context):
              print("Received event:")
              print(json.dumps(event))
              return delete_cfn(stack_name)
      Environment:
        Variables:
          stackName: !Ref 'StackName'
      Handler: "index.handler"
      Runtime: "python3.6"
      Timeout: "5"
      Role: !GetAtt DeleteCFNLambdaExecutionRole.Arn
  DeleteStackEventRule:
     DependsOn:
       - DeleteCFNLambda
       - GenerateCronExpression
     Type: "AWS::Events::Rule"
     Properties:
       Description: Delete stack event
       ScheduleExpression: !GetAtt GenerateCronExpression.cron_exp
       State: "ENABLED"
       Targets: 
          - 
            Arn: !GetAtt DeleteCFNLambda.Arn
            Id: 'DeleteCFNLambda' 
  PermissionForDeleteCFNLambda: 
    Type: "AWS::Lambda::Permission"
    Properties: 
      FunctionName: !Sub "arn:aws:lambda:${AWS::Region}:${AWS::AccountId}:function:DeleteCFNLambda-${StackName}"
      Action: "lambda:InvokeFunction"
      Principal: "events.amazonaws.com"
      SourceArn: !GetAtt DeleteStackEventRule.Arn
  BasicLambdaExecutionRole:
    Type: "AWS::IAM::Role"
    Properties:
      AssumeRolePolicyDocument:
        Version: "2012-10-17"
        Statement:
        - Effect: "Allow"
          Principal:
            Service: ["lambda.amazonaws.com"]
          Action: "sts:AssumeRole"
      Path: "/"
      Policies:
      - PolicyName: "lambda_policy"
        PolicyDocument:
          Version: "2012-10-17"
          Statement:
          - Effect: "Allow"
            Action:
            - "logs:CreateLogGroup"
            - "logs:CreateLogStream"
            - "logs:PutLogEvents"
            Resource: "arn:aws:logs:*:*:*"
  GenerateCronExpLambda:
    Type: "AWS::Lambda::Function"
    Properties:
      Code:
        ZipFile: |
          from datetime import datetime, timedelta
          import os
          import logging
          import json
          import cfnresponse

          def deletion_time(ttl):
              delete_at_time = datetime.now() + timedelta(minutes=int(ttl))
              hh = delete_at_time.hour
              mm = delete_at_time.minute
              cron_exp = "cron({} {} * * ? *)".format(mm, hh)
              return cron_exp

          def handler(event, context):
            print('Received event: %s' % json.dumps(event))
            status = cfnresponse.SUCCESS
            try:
                if event['RequestType'] == 'Delete':
                    cfnresponse.send(event, context, status, {})
                else:
                    ttl = event['ResourceProperties']['ttl']
                    responseData = {}
                    responseData['cron_exp'] = deletion_time(ttl)
                    cfnresponse.send(event, context, cfnresponse.SUCCESS, responseData)
            except Exception as e:
                logging.error('Exception: %s' % e, exc_info=True)
                status = cfnresponse.FAILED
                cfnresponse.send(event, context, status, {}, None)
      Handler: "index.handler"
      Runtime: "python3.6"
      Timeout: "5"
      Role: !GetAtt BasicLambdaExecutionRole.Arn

  GenerateCronExpression:
    Type: "Custom::GenerateCronExpression"
    Version: "1.0"
    Properties:
      ServiceToken: !GetAtt GenerateCronExpLambda.Arn
      ttl: !Ref 'TTL'

เมื่อคุณทำการเปลี่ยนแปลงนี้แล้ว คุณจะต้องอัปโหลดไปยัง s3 และอัปเดตข้อมูลอ้างอิงในสแต็กหลักเป็นเทมเพลตเวอร์ชันของคุณ

AWSTemplateFormatVersion: '2010-09-09'
Description: Demo stack, creates one SSM parameter and gets deleted after 5 minutes.
Resources:
  DemoParameter:
    Type: "AWS::SSM::Parameter"
    Properties:
      Type: "String"
      Value: "date"
      Description: "SSM Parameter for running date command."
      AllowedPattern: "^[a-zA-Z]{1,10}$"
    DependsOn: DeleteAfterTTLStack
  DeleteAfterTTLStack:
    Type: "AWS::CloudFormation::Stack"
    Properties:
      TemplateURL: 'https://your-bucket.s3.amazonaws.com/delete_resources.yaml'
      Parameters:
        StackName: !Ref 'AWS::StackName'
        TTL: '5'

คุณอาจต้องเพิ่มฟิลด์ DependsOn: DeleteAfterTTLStack ลงในแต่ละทรัพยากรเพื่อให้แน่ใจว่าสิทธิ์จะไม่ถูกลบก่อนที่ทรัพยากรทั้งหมดจะถูกลบออก มิฉะนั้นอาจเกิดข้อผิดพลาดในการอนุญาตได้

แม้ว่าสิ่งนี้ควรจะได้ผล แต่ฉันเห็นด้วยกับ @John Rotenstein ว่าการสร้างคลาวด์อาจไม่ใช่ทางออกที่ดีที่สุด ประการแรก การจัดการสิทธิ์อาจเป็นปัญหาใหญ่ เป็นเรื่องง่ายที่จะให้สิทธิ์มากเกินไปหรือน้อยเกินไปเมื่อกำหนดค่าเทมเพลตนี้

person Ben Bloom    schedule 14.01.2020

วิธีง่ายๆ ในการยุติอินสแตนซ์หลังจากระยะเวลาที่กำหนดคือการเรียกใช้คำสั่งบนอินสแตนซ์เองซึ่งจะเข้าสู่โหมดสลีปตามระยะเวลาที่ต้องการ จากนั้นจึงยุติอินสแตนซ์ สคริปต์นี้สามารถส่งผ่านข้อมูลผู้ใช้ได้

การยุติสามารถทำได้สองวิธี:

  • ตัวเลือกที่ 1: เมื่อเปิดใช้งานอินสแตนซ์ ให้ตั้งค่า Shutdown behavior = Terminate จากนั้นให้สคริปต์ปิดอินสแตนซ์
  • ตัวเลือกที่ 2: ให้สคริปต์ดึง ID อินสแตนซ์ผ่านข้อมูลเมตา จากนั้นออกคำสั่ง terminate-instances โดยส่ง ID (วิธีนี้ต้องใช้ข้อมูลรับรอง/บทบาท AWS)

เทคนิคยอดนิยมอีกประการหนึ่งคือการสร้าง stopinator ซึ่งเป็นสคริปต์หรือฟังก์ชัน Lambda ที่ทำงานเป็นประจำซึ่งจะตรวจสอบแท็กบนอินสแตนซ์เพื่อพิจารณาว่าจะหยุด/ยุติอินสแตนซ์หรือไม่ ตัวอย่างเช่น:

  • เรียกใช้ฟังก์ชัน AWS Lambda ทุก 6 ชั่วโมง
  • ฟังก์ชันควรตรวจสอบอินสแตนซ์ทั้งหมดเพื่อระบุอินสแตนซ์ที่จะหยุด/ยุติตามแท็ก เวลาทำงาน ฯลฯ (โดยพื้นฐานแล้ว สิ่งที่คุณต้องการ)
  • ฟังก์ชั่นจะหยุด / ยุติอินสแตนซ์
person John Rotenstein    schedule 06.01.2020
comment
ทั้งสองตัวเลือก ก) การส่งผ่านสคริปต์การยกเลิกผ่านข้อมูลผู้ใช้ หรือ b) ฟังก์ชั่น Lambda ซับซ้อนเกินไปสำหรับฉัน ฉันหวังว่าจะมีคนอธิบายวิธีการทำเช่นนี้โดยใช้สแต็คที่ซ้อนกันตามที่อธิบายไว้ในโพสต์บล็อก (อย่างเป็นทางการ) - person shantanuo; 07.01.2020
comment
การใช้ CloudFormation จะมากซับซ้อนกว่าวิธีที่แนะนำ ตัวอย่างเช่น บน Linux จะเป็นเรื่องของการใช้ sleep 172800; sudo shutdown now -h เป็นส่วนหนึ่งของสคริปต์ข้อมูลผู้ใช้ วิธีนี้ยังใช้ได้กับอินสแตนซ์ที่เปิดตัวภายนอก CloudFormation อย่างไรก็ตาม หาก CloudFormation เปิดใช้อินสแตนซ์ ก็อาจสมเหตุสมผลที่จะลบสแต็ก CloudFormation ด้วย - person John Rotenstein; 07.01.2020
comment
อะไรที่ซับซ้อนมาก? ตามบล็อกอย่างเป็นทางการ ให้เปิดใช้งานเป็นสแต็กที่ซ้อนกันจากสแต็กหลักของคุณ โดยส่งผ่านชื่อของพาเรนต์สแต็กและค่า TTL ที่ต้องการ มันง่ายอย่างนั้นเว้นแต่ว่ามันไม่ได้ผลและดูเหมือนว่าจะเป็นเช่นนั้น เพราะไม่มีใครตอบกลับแม้จะให้เงินรางวัลแล้วก็ตาม ฉันจะต้องการใช้เพื่อวัตถุประสงค์ต่างๆ (โดยเฉพาะระหว่างการฝึก) - person shantanuo; 10.01.2020
comment
ฉันเป็นแฟนตัวยงของแนวทางที่สองที่นี่ AWS มีเทมเพลตที่สร้างไว้ล่วงหน้าเพื่อจุดประสงค์นั้นที่นี่: aws.amazon.com/solutions/instance- กำหนดการ. ช่วยให้คุณสามารถกำหนดเวลาสำหรับอินสแตนซ์ ec2 และ rds ของคุณได้ คุณยังสามารถปรับขนาดอินสแตนซ์ของคุณตามกำหนดการได้อีกด้วย คุณยังดำเนินการนี้ให้สำเร็จได้ด้วยกลุ่มการปรับขนาดอัตโนมัติ หากคุณสร้างทรัพยากร AWS::AutoScaling::ScheduledAction คุณสามารถควบคุมความจุอินสแตนซ์ของคุณตามกำหนดเวลาได้ - person Ben Bloom; 14.01.2020