如何在外部文本指定的CloudFormation UserData中使用内部函数
问题根因
- CloudFormation 内置函数(
!Sub、Fn::Sub、!Ref等)仅能在CloudFormation模板的YAML/JSON结构内被解析执行,你将包含这类函数的内容放在外部文件作为参数传入时,CloudFormation只会将其识别为普通文本字符串,不会触发函数执行逻辑,因此变量替换无法生效。 - 你直接传入包含
!Sub标签的文本到EC2 UserData后,cloud-init服务解析UserData时无法识别CloudFormation专属的YAML标签,就会抛出你遇到的格式报错。
可行解决方案
核心逻辑是把函数解析逻辑放在CloudFormation模板内部执行,外部文件仅保留纯脚本内容和占位符:
步骤1:调整外部UserData文件(userdata.txt)
移除所有CloudFormation专属语法,仅保留脚本内容和变量占位符:
#!/bin/bash ENV_NAME=${EnvironmentName} hostnamectl set-deployment $ENV_NAME
如果需要使用cloud-config格式,按cloud-init官方规范编写即可,占位符保持
${变量名}格式不变。
步骤2:修改CloudFormation模板
在模板内对传入的UserData内容执行!Sub替换,再做Base64编码:
Parameters: EnvironmentName: Type: String Default: Development UserDataScript: Type: String Resources: Instance: Type: AWS::EC2::Instance Properties: ImageId: ami-0194c3e07668a7e36 UserData: Fn::Base64: !Sub !Ref UserDataScript
!Sub默认会自动匹配模板内的参数名、资源属性名作为替换变量,如果你需要自定义变量名,可以使用映射语法:UserData: Fn::Base64: !Sub - ${script_content} - script_content: !Ref UserDataScript my_env: !Ref EnvironmentName此时你的脚本内占位符就可以写
${my_env}。
步骤3:调整CLI创建命令
传入的UserData参数仅需对纯脚本文件做Base64编码即可,注意添加-w0参数避免Base64自动换行导致格式错误:
aws cloudformation create-stack --stack-name my-stack \ --template-body file://my-stack.yaml \ --parameters ParameterKey=UserDataScript,ParameterValue=$(base64 -w0 userdata.txt) ParameterKey=EnvironmentName,ParameterValue=Development
内容的提问来源于stack exchange,提问作者arkie
相关产品推荐
相关产品推荐

