具有资源属性 CloudFormation 的 UserData 脚本

UserData script with Resource Attribute CloudFormation

主要问题:如何在云形成模板中引用依赖资源属性来构建用户数据脚本。

我试过的:

  1. 列出方法 here
  2. 示例来自 sub function

我正在为三节点 Kafka 集群构建 CloudFormation 模板。

我在这里采用的方法是在 EC2 实例上使用 UserData 脚本在集群的每个节点上配置 Zookeeper 和 Kafka。

我正在使用 Sub and Base64 函数用我的 NetworkInterface 的 PrimaryPrivateIpAddress 填充我的用户数据脚本,但它们显示为空字符串而不是实际值。我知道这些值已正确填充,因为它们是我在模板中输出的一部分。

我在下面包含了我的模板的资源块作为参考。为了简洁起见,我省略了一些无趣的部分。我还说明了我尝试过的几种不同的 EC2 资源块不一致的方法。

EC2I8MWW:
  Type: 'AWS::EC2::Instance'
  DependsOn:
    - EC2NI2E8ES
    - EC2NI2PFST
    - EC2NI54B66
  Properties:
    KeyName: !Ref DesiredKeyName
    InstanceType: !Ref InstanceType
    NetworkInterfaces:
      - NetworkInterfaceId: !Ref EC2NI54B66
        DeviceIndex: "0"
    UserData:
      Fn::Base64:
        Fn::Sub:
          - |
            #!/bin/bash
            CONF="/etc/zookeeper/conf.dist/zoo.cfg"
            PRIVATE_1=${Private1}
            PRIVATE_2=${Private2}
            PRIVATE_3=${Private3}
            echo "# Zookeeper configuration for Talentreef" > "$CONF"
            cat <<EOT >> "$CONF"
            maxClientCnxns=50
            tickTime=2000
            initLimit=10
            syncLimit=5
            EOT
            echo "server.1=$PRIVATE_1:2888:3888" >> $CONF
            echo "server.2=$PRIVATE_2:2888:3888" >> $CONF
            echo "server.3=$PRIVATE_3:2888:3888" >> $CONF
            service zookeeper-server init --myid=$NODE_ID
            chkconfig zookeeper-server on
          - {
            Private1: !GetAtt EC2NI2E8ES.PrimaryPrivateIpAddress,
            Private2: !GetAtt EC2NI2PFST.PrimaryPrivateIpAddress,
            Private3: !GetAtt EC2NI54B66.PrimaryPrivateIpAddress
            }
EC2I2JVJI:
  Type: 'AWS::EC2::Instance'
  DependsOn: EC2NI54B66
  Properties:
    KeyName: !Ref DesiredKeyName
    InstanceType: !Ref InstanceType
    BlockDeviceMappings:
      - DeviceName: /dev/xvdb
        Ebs:
          VolumeType: st1
          DeleteOnTermination: 'true'
          VolumeSize: '500'
      - DeviceName: /dev/xvda
        Ebs:
          VolumeType: gp2
          DeleteOnTermination: 'true'
          VolumeSize: '8'
    ImageId: !FindInMap
      - AWSRegionArch2AMI
      - !Ref 'AWS::Region'
      - !FindInMap
        - AWSInstanceType2Arch
        - !Ref InstanceType
        - Arch
    NetworkInterfaces:
      - NetworkInterfaceId: !Ref EC2NI2PFST
        DeviceIndex: "0"
    UserData:
      Fn::Base64: !Sub |
        #!/bin/bash
        CONF="/etc/zookeeper/conf.dist/zoo.cfg"
        cp $CONF /etc/zookeeper/conf.dist/zoo.cfg.bak-$(date +%s)
        echo "# Zookeeper configuration for Talentreef" > "$CONF"
        cat <<EOT >> "$CONF"
        maxClientCnxns=50
        tickTime=2000
        initLimit=10
        syncLimit=5
        server.1=${EC2NI2E8ES.PrimaryPrivateIpAddress}:2888:3888
        server.2=${EC2NI2PFST.PrimaryPrivateIpAddress}:2888:3888
        server.3=${EC2NI54B66.PrimaryPrivateIpAddress}:2888:3888
        EOT
        service zookeeper-server init --myid=$NODE_ID
        chkconfig zookeeper-server on
        service zookeeper-server start
EC2I56LVQ:
  Type: 'AWS::EC2::Instance'
  DependsOn: EC2NI54B66
  Properties:
    KeyName: !Ref DesiredKeyName
    InstanceType: !Ref InstanceType
    BlockDeviceMappings:
      - DeviceName: /dev/xvdb
        Ebs:
          VolumeType: st1
          DeleteOnTermination: 'true'
          VolumeSize: '500'
      - DeviceName: /dev/xvda
        Ebs:
          VolumeType: gp2
          DeleteOnTermination: 'true'
          VolumeSize: '8'
    ImageId: !FindInMap
      - AWSRegionArch2AMI
      - !Ref 'AWS::Region'
      - !FindInMap
        - AWSInstanceType2Arch
        - !Ref InstanceType
        - Arch
    NetworkInterfaces:
      - NetworkInterfaceId: !Ref EC2NI2E8ES
        DeviceIndex: "0"
    UserData:
      Fn::Base64:
        Fn::Sub:
          - |
            CONF="/etc/zookeeper/conf.dist/zoo.cfg"
            cp $CONF /etc/zookeeper/conf.dist/zoo.cfg.bak-$(date +%s)
            echo "# Zookeeper configuration for Talentreef" > "$CONF"
            cat <<EOT >> "$CONF"
            maxClientCnxns=50
            tickTime=2000
            initLimit=10
            syncLimit=5
            EOT
            echo "server.1=${Private1}:2888:3888" >> $CONF
            echo "server.2=${Private2}:2888:3888" >> $CONF
            echo "server.3=${Private3}:2888:3888" >> $CONF
            service zookeeper-server init --myid=$NODE_ID
            chkconfig zookeeper-server on
          - {
            Private1: !GetAtt EC2NI2E8ES.PrimaryPrivateIpAddress,
            Private2: !GetAtt EC2NI2PFST.PrimaryPrivateIpAddress,
            Private3: !GetAtt EC2NI54B66.PrimaryPrivateIpAddress
            }
EC2NI54B66:
  Type: 'AWS::EC2::NetworkInterface'
  DependsOn: EC2NI2PFST
  Properties: {}
EC2NI2PFST:
  Type: 'AWS::EC2::NetworkInterface'
  DependsOn: EC2NI2E8ES
  Properties {}
EC2NI2E8ES:
  Type: 'AWS::EC2::NetworkInterface'
  Properties: {}

运行此脚本时,我在 zoo.cfg 文件中得到以下输出:

maxClientCnxns=50
tickTime=2000
initLimit=10
syncLimit=5
server.1=:2888:3888
server.2=:2888:3888
server.3=:2888:3888

如果我在这里做错了什么或者我是否必须改变我的方法,请告诉我。谢谢你的帮助。

我认为你走在正确的道路上。我只是稍微修改一下你传递 3 "private" 替代变量的方式,例如这样的东西(我在我的模板中经常使用):

UserData:
  Fn::Base64:
    Fn::Sub:
      - |
        CONF="/etc/zookeeper/conf.dist/zoo.cfg"
        cp $CONF /etc/zookeeper/conf.dist/zoo.cfg.bak-$(date +%s)
        echo "# Zookeeper configuration for Talentreef" > "$CONF"
        cat <<EOT >> "$CONF"
        maxClientCnxns=50
        tickTime=2000
        initLimit=10
        syncLimit=5
        EOT
        echo "server.1=${Private1}:2888:3888" >> $CONF
        echo "server.2=${Private2}:2888:3888" >> $CONF
        echo "server.3=${Private3}:2888:3888" >> $CONF
        service zookeeper-server init --myid=$NODE_ID
        chkconfig zookeeper-server on
      - Private1: !GetAtt EC2NI2E8ES.PrimaryPrivateIpAddress
        Private2: !GetAtt EC2NI2PFST.PrimaryPrivateIpAddress
        Private3: !GetAtt EC2NI54B66.PrimaryPrivateIpAddress

所以没有括号 {} 也没有逗号 ,