更新
我开始做的是在用户数据运行结束时创建一个标记文件。我让节点控制器为每个 ec2 节点生成一个 ssh 会话,并在另一端运行一个简单的忙等待循环作为命令,因此它仅在创建文件时返回。然后我只是 wait() 让所有 ssh 会话退出或直到发生等待超时。
它很丑,但它有效。令人沮丧的是,EC2 没有提供更好的设施来从实例内发出状态信号。
标签
一种可能的方法是让实例的用户数据脚本在实例完成时为其添加一个附加标签。您可以使用update 轮询实例,或者使用过滤器执行 describe-instances,该过滤器仅包含带有您用来指定用户数据已更新的标签的节点。
这要求您在发送用户数据脚本时包含有限的 API 密钥和机密。 不要使用您的常规 api 密钥和秘密,使用非常有限的 IAM 权限。此外,用户数据脚本可能希望在完成后删除其自身。
SNS / SQS
我也考虑过为此使用简单通知服务和/或 SQS,但这似乎有点矫枉过正。
与设置标签一样,它要求实例拥有自己的 EC2 凭据。
SNS 是仅推送的,因此您必须有一个 EC2 可以访问的端点。那是一种痛苦。 SQS 是拉式的,但没有消息路由,因此您需要为每组节点创建一个队列。您必须将唯一的队列名称传递给实例,或者让实例使用 EC2 凭证从标签中查询它,然后让实例使用该特定队列。
所以,是的,很痛苦。
控制台
无法获取控制台输出,EC2 在实例转换到“运行”状态后不久停止更新。
似乎没有任何方式(实例或客户端)强制更新。
标记文件
当 cloud-init 脚本完成时,它可以touch 一个标记文件,位于普通用户可以通过 shell 访问的位置。这有点烦人,因为它需要 ssh 进入每个节点,然后轮询创建标记文件。使用如下循环可以在一定程度上减轻轮询的痛苦:
while ! test -e 'cloud-init-complete'
do
inotifywait -qq -t 2 -e create -e moved_to . ||true
done
在安装 inotify-tools 包之后。如果您不将 inotify-tools 刻录到您的 AMI 中,您需要将 inotifywait 替换为简单的 sleep 并接受额外的延迟,或者执行以下操作:
while ! test -e 'cloud-init-complete'
do
if test -x /usr/bin/inotifywait; then
inotifywait -qq -t 2 -e create -e moved_to . ||true
else
sleep 2
fi
done
不过,这仍然需要到每台服务器的 ssh 连接,而且监控和轮询很麻烦。
更智能的东西?
我梦寐以求的解决方案是能够向 EC2 元数据服务发送额外请求,以设置特殊实例标签或自定义额外状态字段。