gpt4 book ai didi

linux - AWS 云信息 : How to reuse bash script placed in user-data parameter when creating EC2?

转载 作者:IT王子 更新时间:2023-10-29 00:45:20 33 4
gpt4 key购买 nike

在 Cloudformation 中,我有两个堆栈(一个是嵌套的)。

嵌套堆栈“ec2-setup”:

{
"AWSTemplateFormatVersion" : "2010-09-09",

"Parameters" : {
// (...) some parameters here

"userData" : {
"Description" : "user data to be passed to instance",
"Type" : "String",
"Default": ""
}

},

"Resources" : {

"EC2Instance" : {
"Type" : "AWS::EC2::Instance",
"Properties" : {
"UserData" : { "Ref" : "userData" },
// (...) some other properties here
}
}

},
// (...)
}

现在,在我的主模板中,我想引用上面提供的嵌套模板,并使用 userData 参数传递 bash 脚本。另外我不想内联用户数据脚本的内容,因为我想将它重用于少数 ec2 实例(所以我不想每次在主模板中声明 ec2 实例时都重复该脚本)。

我尝试通过将脚本的内容设置为参数的默认值来实现此目的:

{
"AWSTemplateFormatVersion": "2010-09-09",

"Parameters" : {
"myUserData": {
"Type": "String",
"Default" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash \n",
"yum update -y \n",

"# Install the files and packages from the metadata\n",
"echo 'tralala' > /tmp/hahaha"
]]}}
}
},
(...)

"myEc2": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "s3://path/to/ec2-setup.json",
"TimeoutInMinutes": "10",
"Parameters": {
// (...)
"userData" : { "Ref" : "myUserData" }
}

但是我在尝试启动堆栈时收到以下错误:

"Template validation error: Template format error: Every Default member must be a string."

该错误似乎是由于声明 { Fn::Base64 (...) } 是一个对象 - 而不是字符串(尽管它会导致返回 base64 编码的字符串)这一事实引起的。

如果我在调用嵌套模板时将脚本直接粘贴到参数部分(作为内联脚本)(而不是引用字符串集作为参数),则一切正常:

"myEc2": {
"Type": "AWS::CloudFormation::Stack",
"Properties": {
"TemplateURL": "s3://path/to/ec2-setup.json",
"TimeoutInMinutes": "10",
"Parameters": {
// (...)
"userData" : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash \n",
"yum update -y \n",

"# Install the files and packages from the metadata\n",
"echo 'tralala' > /tmp/hahaha"
]]}}
}

但我想将 userData 脚本的内容保留在参数/变量中以便能够重用它。

是否有机会重用这样的 bash 脚本,而无需每次都复制/粘贴它?

最佳答案

以下是有关如何在通过 CloudFormation 定义的多个 EC2 实例的用户数据中重用 bash 脚本的一些选项:

1。将默认参数设置为字符串

您最初尝试的解决方案应该可以工作,只需稍作调整:您必须将默认参数声明为字符串,如下所示(使用 YAML 而不是 JSON 可以/更轻松地声明内联多行字符串):

  AWSTemplateFormatVersion: "2010-09-09"
Parameters:
myUserData:
Type: String
Default: |
#!/bin/bash
yum update -y
# Install the files and packages from the metadata
echo 'tralala' > /tmp/hahaha
(...)
Resources:
myEc2:
Type: AWS::CloudFormation::Stack
Properties
TemplateURL: "s3://path/to/ec2-setup.yml"
TimeoutInMinutes: 10
Parameters:
# (...)
userData: !Ref myUserData

然后,在嵌套堆栈中,应用任何所需的 intrinsic functions ( Fn::Base64 以及 Fn::Sub 如果您需要在用户数据脚本中应用任何 RefFn::GetAtt 函数,这非常有用)在 EC2 实例的资源属性中:

  AWSTemplateFormatVersion: "2010-09-09"
Parameters:
# (...) some parameters here
userData:
Description: user data to be passed to instance
Type: String
Default: ""
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
UserData:
"Fn::Base64":
"Fn::Sub": !Ref userData
# (...) some other properties here
# (...)

2。将脚本上传到S3

您可以将单个 Bash 脚本上传到 S3 存储桶,然后通过在模板的每个 EC2 实例中添加最小用户数据脚本来调用该脚本:

  AWSTemplateFormatVersion: "2010-09-09"
Parameters:
# (...) some parameters here
ScriptBucket:
Description: S3 bucket containing user-data script
Type: String
ScriptKey:
Description: S3 object key containing user-data script
Type: String
Resources:
EC2Instance:
Type: AWS::EC2::Instance
Properties:
UserData:
"Fn::Base64":
"Fn::Sub": |
#!/bin/bash
aws s3 cp s3://${ScriptBucket}/${ScriptKey} - | bash -s
# (...) some other properties here
# (...)

3。使用预处理器从单一源内联脚本

最后,您可以使用模板预处理器工具,例如 troposphere或您自己的从更紧凑/更具表现力的源文件“生成”详细的 CloudFormation 可执行模板。这种方法将允许您消除源文件中的重复 - 尽管模板将包含“重复”的用户数据脚本,但这只会发生在生成的模板中,因此不会造成问题。

关于linux - AWS 云信息 : How to reuse bash script placed in user-data parameter when creating EC2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41433312/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com