linux – AWS Cloudformation:如何在创建EC2时重用放在user-data参数中的bash脚本?

前端之家收集整理的这篇文章主要介绍了linux – AWS Cloudformation:如何在创建EC2时重用放在user-data参数中的bash脚本?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

在Cloudformation中,我有两个堆栈(一个嵌套).

嵌套堆栈“ec2-setup”:

  1. {
  2. "AWSTemplateFormatVersion" : "2010-09-09","Parameters" : {
  3. // (...) some parameters here
  4. "userData" : {
  5. "Description" : "user data to be passed to instance","Type" : "String","Default": ""
  6. }
  7. },"Resources" : {
  8. "EC2Instance" : {
  9. "Type" : "AWS::EC2::Instance","Properties" : {
  10. "UserData" : { "Ref" : "userData" },// (...) some other properties here
  11. }
  12. }
  13. },// (...)
  14. }

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

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

  1. {
  2. "AWSTemplateFormatVersion": "2010-09-09","Parameters" : {
  3. "myUserData": {
  4. "Type": "String","Default" : { "Fn::Base64" : { "Fn::Join" : ["",[
  5. "#!/bin/bash \n","yum update -y \n","# Install the files and packages from the Metadata\n","echo 'tralala' > /tmp/hahaha"
  6. ]]}}
  7. }
  8. },(...)
  9. "myEc2": {
  10. "Type": "AWS::CloudFormation::Stack","Properties": {
  11. "TemplateURL": "s3://path/to/ec2-setup.json","TimeoutInMinutes": "10","Parameters": {
  12. // (...)
  13. "userData" : { "Ref" : "myUserData" }
  14. }

但是在尝试启动堆栈时出现以下错误

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

错误似乎是由于声明{Fn :: Base64(…)}是一个对象 – 而不是一个字符串(尽管它导致返回base64编码的字符串).

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

  1. "myEc2": {
  2. "Type": "AWS::CloudFormation::Stack","Properties": {
  3. "TemplateURL": "s3://path/to/ec2-setup.json","Parameters": {
  4. // (...)
  5. "userData" : { "Fn::Base64" : { "Fn::Join" : ["","echo 'tralala' > /tmp/hahaha"
  6. ]]}}
  7. }

但是我希望将userData脚本的内容保存在参数/变量中以便能够重用它.

有没有机会重复使用这样的bash脚本而不需要每次都复制/粘贴它?

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

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

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

  1. AWSTemplateFormatVersion: "2010-09-09"
  2. Parameters:
  3. myUserData:
  4. Type: String
  5. Default: |
  6. #!/bin/bash
  7. yum update -y
  8. # Install the files and packages from the Metadata
  9. echo 'tralala' > /tmp/hahaha
  10. (...)
  11. Resources:
  12. myEc2:
  13. Type: AWS::CloudFormation::Stack
  14. Properties
  15. TemplateURL: "s3://path/to/ec2-setup.yml"
  16. TimeoutInMinutes: 10
  17. Parameters:
  18. # (...)
  19. userData: !Ref myUserData

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

  1. AWSTemplateFormatVersion: "2010-09-09"
  2. Parameters:
  3. # (...) some parameters here
  4. userData:
  5. Description: user data to be passed to instance
  6. Type: String
  7. Default: ""
  8. Resources:
  9. EC2Instance:
  10. Type: AWS::EC2::Instance
  11. Properties:
  12. UserData:
  13. "Fn::Base64":
  14. "Fn::Sub": !Ref userData
  15. # (...) some other properties here
  16. # (...)

2.将脚本上传到S3

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

  1. AWSTemplateFormatVersion: "2010-09-09"
  2. Parameters:
  3. # (...) some parameters here
  4. ScriptBucket:
  5. Description: S3 bucket containing user-data script
  6. Type: String
  7. ScriptKey:
  8. Description: S3 object key containing user-data script
  9. Type: String
  10. Resources:
  11. EC2Instance:
  12. Type: AWS::EC2::Instance
  13. Properties:
  14. UserData:
  15. "Fn::Base64":
  16. "Fn::Sub": |
  17. #!/bin/bash
  18. aws s3 cp s3://${ScriptBucket}/${ScriptKey} - | bash -s
  19. # (...) some other properties here
  20. # (...)

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

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

猜你在找的Linux相关文章