在 AWS 中为实例定义用户数据似乎对于执行各种引导类型的操作非常有用。不幸的是,出于 PCI 的原因,我必须使用并非源自提供的 AMI 之一的自定义 CentOS AMI,因此尚未安装和配置 cloud-init。我只希望它设置一个主机名并运行一个小型 bash 脚本。我如何让它工作?
4 回答
cloud-init 是一个非常强大但非常无证的工具。即使安装了它,默认情况下仍有许多处于活动状态的模块会覆盖您可能已经在 AMI 上定义的内容。以下是从头开始进行最小设置的说明:
指示
从标准存储库安装 cloud-init。如果您担心 PCI,您可能不想使用 AWS 的自定义存储库。
# rpm -Uvh https://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm # yum install cloud-init
编辑
/etc/cloud/cloud.cfg
yaml 文件,以反映您所需的配置。以下是包含每个模块文档的最小配置。#If this is not explicitly false, cloud-init will change things so that root #login via ssh is disabled. If you don't want it to do anything, set it false. disable_root: false #Set this if you want cloud-init to manage hostname. The current #/etc/hosts file will be replaced with the one in /etc/cloud/templates. manage_etc_hosts: true #Since cloud-init runs at multiple stages of boot, this needs to be set so #it can log in all of them to /var/log/cloud-init. syslog_fix_perms: null #This is the bit that makes userdata work. You need this to have userdata #scripts be run by cloud-init. datasource_list: [Ec2] datasource: Ec2: metadata_urls: ['http://169.254.169.254'] #modules that run early in boot cloud_init_modules: - bootcmd #for running commands in pre-boot. Commands can be defined in cloud-config userdata. - set-hostname #These 3 make hostname setting work - update-hostname - update-etc-hosts #modules that run after boot cloud_config_modules: - runcmd #like bootcmd, but runs after boot. Use this instead of bootcmd unless you have a good reason for doing so. #modules that run at some point after config is finished cloud_final_modules: - scripts-per-once #all of these run scripts at specific events. Like bootcmd, can be defined in cloud-config. - scripts-per-boot - scripts-per-instance - scripts-user - phone-home #if defined, can make a post request to a specified url when done booting - final-message #if defined, can write a specified message to the log - power-state-change #can trigger stuff based on power state changes system_info: #works because amazon's linux AMI is based on CentOS distro: amazon
如果有
defaults.cfg
in/etc/cloud/cloud.cfg.d/
,删除它。要利用此配置,请为新实例定义以下用户数据:
#cloud-config hostname: myhostname fqdn: myhostname.mydomain.com runcmd: - echo "I did this thing post-boot" - echo "I did this too"
您也可以通过替换 bash 脚本并将其放入正文中来简单地运行 bash 脚本
#cloud-config
,#!/bin/bash
但如果这样做,您应该从cloud_init_modules
.
补充说明
请注意,这是一个最小配置,cloud-init 能够管理用户、ssh 密钥、挂载点等。有关这些特定功能的更多文档,请查看下面的参考资料。
一般来说,cloud-init 似乎是根据指定的模块来做事的。一些模块,如“disable-ec2-metadata”,只需指定即可。其他的,比如“runcmd”,只有在 cloud.cfg 或 cloud-config 用户数据中指定了参数时才会执行。下面的大多数文档只告诉您每个模块可以使用哪些参数,而不是模块的名称,但默认的 cloud.cfg 应该有一个完整的模块列表开始。我发现禁用模块的最佳方法就是将其从列表中删除。
在某些情况下,“rhel”可能比“amazon”更适合“distro”标签。我还真不知道什么时候。
参考
- 如何安装 cloud-init:http ://web.archive.org/web/20140925130743/http://docs.openstack.org/grizzly/openstack-image/content/centos-image.html
- 模块参考(不完整):http ://cloudinit.readthedocs.org/en/latest/topics/examples.html
- 模块参考(不完整):https ://github.com/number5/cloud-init/blob/master/doc/examples/cloud-config.txt
- 一般设置说明:http ://web.archive.org/web/20150110200930/http://www.scalehorizontally.com/2013/02/24/introduction-to-cloud-init
- 主机名管理:http ://web.archive.org/web/20140805225413/http://docs.openstack.org/user-guide/content/user-data.html
这是关于如何在 AWS EC2 (CentOS) 上 使用cloud-init在启动期间运行脚本的简短教程。
本教程解释:
- 如何设置配置文件
/etc/cloud/cloud.cfg
- 云路径的
/var/lib/cloud/scripts
样子- 使用示例的云路径下的脚本文件,以及
- 如何检查脚本文件是否在实例启动期间执行
配置文件
下面的配置文件在 AWS CentOS6 上。对于 Amazon Linux,请参阅此处。
# cat /etc/cloud/cloud.cfg
manage_etc_hosts: localhost
user: root
disable_root: false
ssh_genkeytypes: [ rsa, dsa ]
cloud_init_modules:
- resizefs
- update_etc_hosts
- ssh
cloud_final_modules:
- scripts-per-once
- scripts-per-boot
- scripts-per-instance
- scripts-user
目录树
这是云路径的/var/lib/cloud/scripts
样子:
# cd /var/lib/cloud/scripts
# tree `pwd`
/var/lib/cloud/scripts
├── per-boot
│ └── per-boot.sh
├── per-instance
│ └── per-instance.sh
└── per-once
└── per-once.sh
脚本文件的内容
以下是示例脚本文件的内容。
这些文件必须在 user 下root
。请参阅我创建引导脚本的方法。
# cat /var/lib/cloud/scripts/per-boot/per-boot.sh
#!/bin/sh
echo per-boot: `date` >> /tmp/per-xxx.txt
# cat /var/lib/cloud/scripts/per-instance/per-instance.sh
#!/bin/sh
echo per-instance: `date` >> /tmp/per-xxx.txt
# cat /var/lib/cloud/scripts/per-once/per-once.sh
#!/bin/sh
echo per-once: `date` >> /tmp/per-xxx.txt
执行结果
在初次启动的情况下
# cat /tmp/per-xxx.txt
per-once: 1 January 3, 2013 Thursday 17:30:16 JST
per-boot: 1 January 3, 2013 Thursday 17:30:16 JST
per-instance: 1 January 3, 2013 Thursday 17:30:16 JST
在重新启动的情况下
# cat /tmp/per-xxx.txt
per-once: 1 January 3, 2013 Thursday 17:30:16 JST
per-boot: 1 January 3, 2013 Thursday 17:30:16 JST
per-instance: 1 January 3, 2013 Thursday 17:30:16 JST
per-boot: 1 January 3, 2013 Thursday 17:32:24 JST
从 AMI 开始的情况下
# cat /tmp/per-xxx.txt
per-once: 1 January 3, 2013 Thursday 17:30:16 JST
per-boot: 1 January 3, 2013 Thursday 17:30:16 JST
per-instance: 1 January 3, 2013 Thursday 17:30:16 JST
per-boot: 1 January 3, 2013 Thursday 17:32:24 JST
per-boot: 1 January 3, 2013 Thursday 17:44:08 JST
Expanding on the prior answer for anyone trying to create a CentOS AMI that is cloud-init
enabled (and capable of actually executing your CloudFormation scripts), you might have some success by doing the following:
- launch a marketplace CentOS AMI w/Updates - make sure cloud-init is present or
sudo yum install -y cloud-init
rm -rf /var/lib/cloud/data
rm -rf /var/lib/cloud/instance
rm -rf /var/lib/cloud/instances/*
- replace
/etc/cloud/cloud.cfg
with the configuration in the answer above but make sure you setdistro: rhel
- Add the CloudFormation helpers (http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-helper-scripts-reference.html)
- create an AMI image from this instance
Had a heck of a time trying to figure out why my UserData was not being invoked until I realized that the images in the marketplace naturally only run your UserData once per instance AND of course they had already run. Removing the indicators that those had already been executed along with changing the distro: rhel
in the cloud.cfg
file did the trick.
For the curious, the distro:
value should correspond to one of the python scripts in /usr/lib/python2.6/site-packages/cloudinit/distros
. As it turns out the AMI I launched had no amazon.py
, so you need to use rhel
for CentOS. Depending on the AMI you launch and the version of cloud-init, YMMV.
Thank you to those here who have already clarified so much about cloud-init! However, at least regarding AWS, one issue needs emphasis:
In other words, they will not run during subsequent boots. This is not always mentioned and I suspect is causing confusion. More on this: