具有资源属性 CloudFormation 的 UserData 脚本
Posted
技术标签:
【中文标题】具有资源属性 CloudFormation 的 UserData 脚本【英文标题】:UserData script with Resource Attribute CloudFormation 【发布时间】:2018-07-15 11:54:27 【问题描述】:主要问题:如何在云形成模板中引用相关资源属性来构建用户数据脚本。
我的尝试:
-
列出的方法here。
来自sub function 的示例
我正在为三节点 Kafka 集群构建 CloudFormation 模板。
我在这里采用的方法是使用 EC2 实例上的 UserData 脚本在集群的每个节点上配置 Zookeeper 和 Kafka。
我正在使用Sub 和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
如果我在这里做错了什么或者我必须改变我的方法,请告诉我。谢谢你的帮助。
【问题讨论】:
【参考方案1】:我认为你走在正确的道路上。我会稍微修改一下传递 3 个“私有”替代变量的方式,例如(我在模板中经常使用):
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
所以没有括号 也没有逗号
,
【讨论】:
谢谢!我在那里也遇到了一些糟糕的 bash,所以我也修复了它并且一切正常。 谢谢,它也解决了我在 Userdata 中使用 !GetAtt 的问题以上是关于具有资源属性 CloudFormation 的 UserData 脚本的主要内容,如果未能解决你的问题,请参考以下文章
具有 CloudFormation 的 Amazon DynamoDB 属性类型
AWS Cloudformation:有条件地创建资源的属性
AWS cloudformation 错误:模板验证错误:模板错误:资源 NotificationsTopic 不支持 Fn::GetAtt 中的属性类型 Arn