首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >5分钟后移除模板

5分钟后移除模板
EN

Stack Overflow用户
提问于 2019-12-19 07:40:31
回答 2查看 756关注 0票数 2

此模板创建SSM参数变量,然后尝试在5分钟后删除它。依赖模板无法删除函数,因此这两个堆栈都无法删除。我想知道如何在生命结束后移除堆栈(在本例中为5分钟)。

代码语言:javascript
复制
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/

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-14 20:45:05

博客帖子的模板文件似乎有很多问题。您无法删除堆栈,因为嵌套堆栈中的iam角色没有足够的权限来删除堆栈中的所有资源(lambda、iam角色、事件、ssm参数等)。

若要使用权限修复此错误,您需要创建一个新的嵌套模板,该模板具有DeleteCFNLambdaExecutionRole的附加权限。我已经在托管策略arn:aws:iam::aws:policy/AdministratorAccess中提供了更新,但是我强烈建议找到删除资源的最少特权。我添加的策略是而不是良好实践,但是由于我不知道您的全部用例,这是保证它将删除所有内容的唯一方法。

代码语言:javascript
复制
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,并更新主堆栈中对模板版本的引用。

代码语言:javascript
复制
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的观点,即cloudformation可能不是最好的解决方案。首先,管理权限可能是一个巨大的痛苦点。在配置此模板时,很容易授予太多或太少的权限。

票数 5
EN

Stack Overflow用户

发布于 2020-01-06 22:44:51

在给定时间段后终止实例的一种简单方法是在实例本身上运行一个命令,该命令在所需的时间段内休眠,然后终止该实例。此脚本可以通过用户数据传递。

终止可以通过两种方式进行:

  • Option 1:启动实例时,设置Shutdown behavior = Terminate,然后让脚本关闭instance
  • Option 2:让脚本通过元数据检索实例ID,然后发出terminate-instances命令,传递ID (此方法需要AWS credentials/role)

)

另一种流行的技术是创建一个停止器,它是一个脚本或Lambda函数,定期运行,检查实例上的标记以确定是否停止/终止实例。例如:

  • 每6小时运行一次AWS函数(
  • )该函数应该根据标记、运行时间等来识别停止/终止的实例,然后停止/终止实例

(基本上是您想要的)。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59405215

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档