Hapus template setelah 5 menit

Templat ini membuat variabel parameter SSM dan kemudian mencoba menghapusnya setelah 5 menit. Templat dependen tidak dapat menghapus fungsi tersebut dan oleh karena itu kedua tumpukan gagal dihapus. Saya ingin tahu cara menghapus tumpukan setelah waktu hidup (5 menit dalam kasus ini)

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'

Saya mendapatkan templat ini dari:

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


person shantanuo    schedule 19.12.2019    source sumber
comment
Apa tujuan sebenarnya Anda? Apakah Anda hanya ingin membuat nilai 'sementara' di Parameter Store? Apakah ini perlu dilakukan melalui CloudFormation? Harap beri tahu kami lebih banyak tentang kasus penggunaan Anda yang lebih luas.   -  person John Rotenstein    schedule 20.12.2019
comment
Saya membeli instans langsung menggunakan templat CFN. Saya ingin menghapus instance setelah 1 atau 2 hari. Ini akan melakukannya secara otomatis! Sesuai pengetahuan saya, tidak ada cara untuk menghentikan instance yang sedang berjalan (spot atau lainnya) tepat setelah 48 jam. Kanan?   -  person shantanuo    schedule 06.01.2020


Jawaban (2)


Tampaknya ada banyak masalah dengan file template postingan blog tersebut. Anda tidak dapat menghapus tumpukan karena peran iam di tumpukan bertumpuk tidak memiliki izin yang cukup untuk menghapus semua sumber daya di tumpukan (lambda, peran iam, peristiwa, parameter ssm, dll).

Untuk memperbaiki kesalahan izin ini, Anda perlu membuat templat bersarang baru dengan izin tambahan untuk DeleteCFNLambdaExecutionRole. Saya telah memberikan pembaruan dengan kebijakan terkelola arn:aws:iam::aws:policy/AdministratorAccess, namun saya sangat menyarankan untuk mengetahui hak istimewa paling rendah untuk menghapus sumber daya Anda. Kebijakan yang saya tambahkan bukan praktik yang baik, namun karena saya tidak mengetahui kasus penggunaan Anda secara lengkap, itulah satu-satunya cara untuk menjamin bahwa kebijakan tersebut akan menghapus semuanya.

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'

Setelah Anda melakukan perubahan ini, Anda perlu mengunggah ke s3 dan memperbarui referensi di tumpukan utama ke versi templat Anda.

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'

Anda mungkin perlu menambahkan bidang DependsOn: DeleteAfterTTLStack ke setiap sumber daya untuk memastikan izin tidak dihapus sebelum semua sumber daya dihapus, jika tidak, kesalahan izin dapat terjadi.

Meskipun ini seharusnya berhasil, saya setuju dengan @John Rotenstein bahwa cloudformation mungkin bukan solusi terbaik. Pertama, mengelola izin bisa menjadi masalah besar. Sangat mudah untuk memberikan izin terlalu banyak atau terlalu sedikit saat mengonfigurasi templat ini.

person Ben Bloom    schedule 14.01.2020

Cara sederhana untuk menghentikan sebuah instance setelah jangka waktu tertentu adalah dengan menjalankan perintah pada instance itu sendiri yang tidur selama jangka waktu yang diinginkan, lalu menghentikan instance tersebut. Skrip ini dapat diteruskan melalui Data Pengguna.

Pengakhiran dapat dilakukan dengan dua cara:

  • Opsi 1: Saat meluncurkan instance, setel Shutdown behavior = Terminate, lalu minta skrip mematikan instance tersebut
  • Opsi 2: Minta skrip mengambil ID instans melalui metadata, lalu keluarkan perintah terminate-instances, meneruskan ID tersebut (metode ini memerlukan kredensial/peran AWS)

Teknik populer lainnya adalah membuat stopinator, yang merupakan skrip atau fungsi Lambda yang berjalan secara rutin yang memeriksa tag pada instans untuk menentukan apakah akan menghentikan/mengakhiri instans. Misalnya:

  • Jalankan fungsi AWS Lambda setiap 6 jam
  • Fungsi tersebut harus melihat semua instance untuk mengidentifikasi instance yang akan dihentikan/dihentikan berdasarkan tag, waktu berjalan, dll (pada dasarnya, apa pun yang Anda inginkan)
  • Fungsi tersebut kemudian menghentikan/mengakhiri instance
person John Rotenstein    schedule 06.01.2020
comment
Kedua opsi tersebut a) Melewati skrip penghentian melalui data pengguna. atau b) Fungsi Lambda terlalu rumit bagi saya. Saya sangat berharap seseorang menjelaskan kepada saya bagaimana melakukan ini menggunakan tumpukan bersarang seperti yang dijelaskan dalam posting blog (resmi) itu. - person shantanuo; 07.01.2020
comment
Penggunaan CloudFormation akan jauh lebih rumit dibandingkan metode yang disarankan. Misalnya, di Linux, ini hanya masalah penggunaan sleep 172800; sudo shutdown now -h sebagai bagian dari skrip Data Pengguna. Metode ini juga dapat digunakan untuk instans yang diluncurkan di luar CloudFormation. Namun, jika instans diluncurkan oleh CloudFormation, mungkin masuk akal untuk menghapus tumpukan CloudFormation juga. - person John Rotenstein; 07.01.2020
comment
Apa yang begitu rumit? Sesuai dengan blog resmi, luncurkan sebagai tumpukan bersarang dari tumpukan utama Anda, dengan meneruskan nama tumpukan induk dan nilai TTL yang diinginkan. Sesederhana itu kecuali jika tidak berhasil dan sepertinya itulah yang terjadi karena tidak ada yang merespons bahkan setelah menawarkan hadiah. Saya ingin menggunakannya untuk berbagai tujuan (terutama saat latihan). - person shantanuo; 10.01.2020
comment
Saya penggemar berat pendekatan kedua di sini. AWS memiliki templat bawaan untuk tujuan tersebut di sini: aws.amazon.com/solutions/instance- penjadwal. Ini memungkinkan Anda mengatur jadwal untuk instans EC2 dan rds Anda. Anda bahkan dapat mengubah ukuran instans Anda berdasarkan jadwal. Anda juga dapat melakukannya dengan grup penskalaan otomatis. Jika Anda membuat sumber daya AWS::AutoScaling::ScheduledAction, Anda dapat mengontrol kapasitas instans Anda sesuai jadwal. - person Ben Bloom; 14.01.2020