草庐IT

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

coder 2023-06-19 原文

在 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 Cloudformation : How to reuse bash script placed in user-data parameter when creating EC2?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41433312/

有关linux - AWS Cloudformation : How to reuse bash script placed in user-data parameter when creating EC2?的更多相关文章

随机推荐