使用CloudFormation::Init将本地.zip文件复制到新建EC2实例
解决CloudFormation::Init部署本地制品到EC2的问题
方法一:自定义CloudFormation宏替换本地路径为S3 URL
你可以通过自定义CloudFormation宏,自动替换AWS::CloudFormation::Init的sources字段中的本地路径为对应S3 URL,步骤如下:
上传本地制品到S3
先将本地的website.zip上传到目标S3桶:aws s3 cp applications/website.zip s3://your-target-bucket/path/website.zip创建宏对应的Lambda函数
编写Lambda函数遍历模板的Metadata部分,替换指定的本地路径。示例Python代码:import json def lambda_handler(event, context): template = event['fragment'] # 定位到Init的sources配置 init_sources = template.get('Metadata', {}).get('AWS::CloudFormation::Init', {}).get('config', {}).get('sources', {}) # 替换目标路径 for target_dir, local_path in init_sources.items(): if local_path == 'applications/website.zip': init_sources[target_dir] = 's3://your-target-bucket/path/website.zip' # 返回修改后的模板 return { 'requestId': event['requestId'], 'status': 'success', 'fragment': template }注册CloudFormation宏
通过CloudFormation模板注册上述Lambda函数为宏:AWSTemplateFormatVersion: '2010-09-09' Resources: ReplaceLocalPathMacro: Type: AWS::CloudFormation::Macro Properties: Name: ReplaceLocalPath FunctionName: !Ref ReplaceLocalPathLambda ReplaceLocalPathLambda: Type: AWS::Lambda::Function Properties: Runtime: python3.9 Handler: index.lambda_handler Code: ZipFile: | import json def lambda_handler(event, context): template = event['fragment'] init_sources = template.get('Metadata', {}).get('AWS::CloudFormation::Init', {}).get('config', {}).get('sources', {}) for target_dir, local_path in init_sources.items(): if local_path == 'applications/website.zip': init_sources[target_dir] = 's3://your-target-bucket/path/website.zip' return { 'requestId': event['requestId'], 'status': 'success', 'fragment': template } Role: !GetAtt LambdaExecutionRole.Arn LambdaExecutionRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole在Webserver模板中启用宏
在你的EC2堆栈模板开头添加Transform字段:AWSTemplateFormatVersion: '2010-09-09' Transform: ReplaceLocalPath # 剩余模板内容...部署时宏会自动替换
sources中的本地路径为S3 URL。
方法二:预上传制品+参数化引用
这是更轻量化的方案,无需自定义宏:
上传本地文件到S3
执行和方法一相同的s3 cp命令完成上传。修改模板添加参数
将S3 URL通过参数传入模板:AWSTemplateFormatVersion: '2010-09-09' Parameters: WebsiteArtifactS3Url: Type: String Description: S3 URL of the website.zip artifact Resources: WebServerInstance: Type: AWS::EC2::Instance Metadata: AWS::CloudFormation::Init: config: packages: yum: npm: [] sources: /home/ec2-user/developer-site: !Ref WebsiteArtifactS3Url # 实例其他配置...部署时传递参数
aws cloudformation deploy --stack-name WebServerStack --template-file your-template.yaml --parameter-overrides WebsiteArtifactS3Url=s3://your-target-bucket/path/website.zip
方法三:结合package命令与文本替换
如果模板中有其他需要cloudformation package处理的资源(如Lambda函数),可以先处理模板再替换路径:
模板中使用占位符
将本地路径替换为占位符:sources: /home/ec2-user/developer-site: {{WEBSITE_S3_URL}}运行package命令处理其他资源
aws cloudformation package --template-file your-template.yaml --s3-bucket your-package-bucket --output-template-file packaged-template.yaml上传制品并替换占位符
# 上传本地文件 aws s3 cp applications/website.zip s3://your-target-bucket/path/website.zip # 替换占位符 sed -i 's|{{WEBSITE_S3_URL}}|s3://your-target-bucket/path/website.zip|g' packaged-template.yaml部署处理后的模板
aws cloudformation deploy --stack-name WebServerStack --template-file packaged-template.yaml
内容的提问来源于stack exchange,提问作者Pedro Hoehl Carvalho
相关产品推荐
相关产品推荐

