如何在 CloudFormation 中將自訂資源與 Amazon S3 儲存貯體搭配使用?
5 分的閱讀內容
0
我想在 AWS CloudFormation 中將自訂資源與 Amazon Simple Storage Service (Amazon S3) 儲存貯體搭配使用。
解決方法
CloudFormation 範本會使用 AWS Lambda 支援的自訂資源。您針對 S3 儲存貯體的自訂資源使用 CloudFormation 範本時,您可以採用下列動作:
- 使用範本以建立 S3 儲存貯體中的資料夾。
- 建立 S3 儲存貯體之後,請使用範本複製、上傳或同步跨兩個儲存貯體的內容。
- 使用自己的程式碼修改範本。
**注意:**在下列解決方案中,Amazon S3 會在您刪除 CloudFormation 堆疊時,刪除所有 S3 儲存貯體內容。若要修改此行為,您必須修改 Lambda 程式碼。
取得 CloudFormation 範本
若要使用 Amazon S3 儲存貯體的自訂資源,請將下列 JSON 或 YAML 範本另存為檔案。
JSON:
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Working with custom resources and S3", "Parameters": { "S3BucketName": { "Type": "String", "Description": "S3 bucket to create.", "AllowedPattern": "[a-zA-Z][a-zA-Z0-9_-]*" }, "DirsToCreate": { "Description": "Comma delimited list of directories to create.", "Type": "CommaDelimitedList" } }, "Resources": { "SampleS3Bucket": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": {"Ref":"S3BucketName"} } }, "S3CustomResource": { "Type": "Custom::S3CustomResource", "DependsOn":"AWSLambdaExecutionRole", "Properties": { "ServiceToken": {"Fn::GetAtt": ["AWSLambdaFunction","Arn"]}, "the_bucket": {"Ref":"SampleS3Bucket"}, "dirs_to_create": {"Ref":"DirsToCreate"} } }, "AWSLambdaFunction": { "Type": "AWS::Lambda::Function", "Properties": { "Description": "Work with S3 Buckets!", "FunctionName": {"Fn::Sub":"${AWS::StackName}-${AWS::Region}-lambda"}, "Handler": "index.handler", "Role": {"Fn::GetAtt": ["AWSLambdaExecutionRole","Arn"]}, "Timeout": 360, "Runtime": "python3.9", "Code": { "ZipFile": "import boto3\r\nimport cfnresponse\r\ndef handler(event, context):\r\n # Init ...\r\n the_event = event['RequestType']\r\n print(\"The event is: \", str(the_event))\r\n response_data = {}\r\n s_3 = boto3.client('s3')\r\n # Retrieve parameters\r\n the_bucket = event['ResourceProperties']['the_bucket']\r\n dirs_to_create = event['ResourceProperties']['dirs_to_create']\r\n try:\r\n if the_event in ('Create', 'Update'):\r\n print(\"Requested folders: \", str(dirs_to_create))\r\n for dir_name in dirs_to_create:\r\n print(\"Creating: \", str(dir_name))\r\n s_3.put_object(Bucket=the_bucket,\r\n Key=(dir_name\r\n + '\/'))\r\n elif the_event == 'Delete':\r\n print(\"Deleting S3 content...\")\r\n b_operator = boto3.resource('s3')\r\n b_operator.Bucket(str(the_bucket)).objects.all().delete()\r\n # Everything OK... send the signal back\r\n print(\"Operation successful!\")\r\n cfnresponse.send(event,\r\n context,\r\n cfnresponse.SUCCESS,\r\n response_data)\r\n except Exception as e:\r\n print(\"Operation failed...\")\r\n print(str(e))\r\n response_data['Data'] = str(e)\r\n cfnresponse.send(event,\r\n context,\r\n cfnresponse.FAILED,\r\n response_data)" } } }, "AWSLambdaExecutionRole": { "Type": "AWS::IAM::Role", "Properties": { "AssumeRolePolicyDocument": { "Statement": [ { "Action": [ "sts:AssumeRole" ], "Effect": "Allow", "Principal": { "Service": [ "lambda.amazonaws.com" ] } } ], "Version": "2012-10-17" }, "Path": "/", "Policies": [ { "PolicyDocument": { "Statement": [ { "Action": [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents" ], "Effect": "Allow", "Resource": "arn:aws:logs:*:*:*" } ], "Version": "2012-10-17" }, "PolicyName": {"Fn::Sub": "${AWS::StackName}-${AWS::Region}-AWSLambda-CW"} }, { "PolicyDocument": { "Statement": [ { "Action": [ "s3:PutObject", "s3:DeleteObject", "s3:List*" ], "Effect": "Allow", "Resource": [ {"Fn::Sub": "arn:aws:s3:::${SampleS3Bucket}/*"}, {"Fn::Sub": "arn:aws:s3:::${SampleS3Bucket}"} ] } ], "Version": "2012-10-17" }, "PolicyName": {"Fn::Sub":"${AWS::StackName}-${AWS::Region}-AWSLambda-S3"} } ], "RoleName": {"Fn::Sub":"${AWS::StackName}-${AWS::Region}-AWSLambdaExecutionRole"} } } } }
YAML:
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AWSTemplateFormatVersion: 2010-09-09 Description: Working with custom resources and S3 Parameters: S3BucketName: Type: String Description: "S3 bucket to create." AllowedPattern: "[a-zA-Z][a-zA-Z0-9_-]*" DirsToCreate: Description: "Comma delimited list of directories to create." Type: CommaDelimitedList Resources: SampleS3Bucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref S3BucketName S3CustomResource: Type: Custom::S3CustomResource Properties: ServiceToken: !GetAtt AWSLambdaFunction.Arn the_bucket: !Ref SampleS3Bucket dirs_to_create: !Ref DirsToCreate AWSLambdaFunction: Type: "AWS::Lambda::Function" Properties: Description: "Work with S3 Buckets!" FunctionName: !Sub '${AWS::StackName}-${AWS::Region}-lambda' Handler: index.handler Role: !GetAtt AWSLambdaExecutionRole.Arn Timeout: 360 Runtime: python3.9 Code: ZipFile: | import boto3 import cfnresponse def handler(event, context): # Init ... the_event = event['RequestType'] print("The event is: ", str(the_event)) response_data = {} s_3 = boto3.client('s3') # Retrieve parameters the_bucket = event['ResourceProperties']['the_bucket'] dirs_to_create = event['ResourceProperties']['dirs_to_create'] try: if the_event in ('Create', 'Update'): print("Requested folders: ", str(dirs_to_create)) for dir_name in dirs_to_create: print("Creating: ", str(dir_name)) s_3.put_object(Bucket=the_bucket, Key=(dir_name + '/')) elif the_event == 'Delete': print("Deleting S3 content...") b_operator = boto3.resource('s3') b_operator.Bucket(str(the_bucket)).objects.all().delete() # Everything OK... send the signal back print("Operation successful!") cfnresponse.send(event, context, cfnresponse.SUCCESS, response_data) except Exception as e: print("Operation failed...") print(str(e)) response_data['Data'] = str(e) cfnresponse.send(event, context, cfnresponse.FAILED, response_data) AWSLambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Statement: - Action: - sts:AssumeRole Effect: Allow Principal: Service: - lambda.amazonaws.com Version: '2012-10-17' Path: "/" Policies: - PolicyDocument: Statement: - Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents Effect: Allow Resource: arn:aws:logs:*:*:* Version: '2012-10-17' PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-CW - PolicyDocument: Statement: - Action: - s3:PutObject - s3:DeleteObject - s3:List* Effect: Allow Resource: - !Sub arn:aws:s3:::${SampleS3Bucket}/* - !Sub arn:aws:s3:::${SampleS3Bucket} Version: '2012-10-17' PolicyName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambda-S3 RoleName: !Sub ${AWS::StackName}-${AWS::Region}-AWSLambdaExecutionRole
部署 CloudFormation 範本
若要部署 CloudFormation 範本,請使用 CloudFormation 主控台或 AWS Command Line Interface (AWS CLI)。
**注意:**如果您在執行 AWS CLI 命令時收到錯誤,請參閱對 AWS CLI 錯誤進行疑難排解。此外,請確定您使用的是最新的 AWS CLI 版本。
若要使用 CloudFormation 主控台,請完成下列步驟:
- 開啟 CloudFormation 主控台。
- 選擇建立堆疊,然後選擇使用新資源 (標準)。
- 在指定範本中,選擇上傳範本檔案。
- 選擇選擇檔案,選取下載的範本,然後選擇下一步。
- 在參數中,針對 S3BucketName,指定新儲存貯體的 S3 儲存貯體名稱。
- 針對 DirsToCreate,輸入要建立的資料夾和子資料夾的以逗號分隔清單。
**注意:**例如,輸入 dir_1,dir_2/sub_dir_2,dir_3 作為清單。 - 完成安裝精靈中的其餘步驟,然後選擇建立堆疊。
若要使用 AWS CLI,請完成下列步驟:
- 將下載的範本重新命名為 custom-resource-lambda-s3.template。
- 開啟作業系統 (OS) 中的命令列,然後導覽至在其中儲存範本的資料夾。
- 若要部署範本,請執行 create-stack 命令:
**注意:**將 custom-resource-lambda-s3.template 取代為您的範本、將 test-bucket-custom-resource 取代為 S3 儲存貯體,並且將 dir_1\,dir_2/sub_dir_2\,dir_3 取代為要建立的資料夾和子資料夾的清單。aws cloudformation create-stack \ --timeout-in-minutes 10 \ --disable-rollback \ --stack-name testing-custom-resource-s3 \ --template-body file://custom-resource-lambda-s3.template \ --capabilities CAPABILITY_NAMED_IAM \ --parameters \ ParameterKey=DirsToCreate,ParameterValue="dir_1\,dir_2/sub_dir_2\,dir_3" \ ParameterKey=S3BucketName,ParameterValue="test-bucket-custom-resource"
相關資訊
實作 Lambda 支援的 CloudFormation 自訂資源的部分最佳實務為何?
如何刪除 CloudFormation 中停滯於 DELETE_FAILED 狀態或 DELETE_IN_PROGRESS 狀態的 Lambda 支援的自訂資源?
AWS 官方已更新 2 個月前
沒有評論
相關內容
- 已提問 6 個月前lg...
- 已提問 2 個月前lg...
- AWS 官方已更新 3 年前
- AWS 官方已更新 4 年前