[英]How can I create a custom Linux AMI with Packer that accepts user data
目标是通过包括外部数据库或其他特定于实例的配置来创建最终用户可以自定义的AMI。
我创建了一个自定义映像,它可以从repo中下载一些资产,作为Packer构建的一部分,然后创建一个在下次启动时运行脚本的服务。 当我从这个AMI启动实例时,我包含一个用户数据脚本,它只创建一个prop文件,然后将一些值回显到prop文件中。 然后,服务脚本根据用户数据(如果存在)或默认值创建prop文件,然后使用这些props启动资产。
但是,在我启动实例后,该文件不是由用户数据创建的。 我发现有些东西说这是每个实例id运行一次,但这是一个新实例。
我已经尝试将用户数据作为服务脚本的一部分获取, wget http://169.254.169.254/latest/user-data
,删除与用户数据相关联的状态文件,作为打包器构建过程的一部分,因此user_data将是在实例化AMI时再次运行rm -Rf /var/lib/cloud/*
,在#cloud-boothook
之前添加用户数据,以便每次运行而不是仅首次启动。 但是,用户数据脚本中的tmp文件不存在,资产仅以默认值开头。
...
{
"type": "file",
"source": "../scripts/bootstrap.sh",
"destination": "/tmp/bootstrap.sh"
},
{
"type": "file",
"source": "../scripts/myservice.service",
"destination": "/tmp/myservice.service"
},
{
"type": "shell",
"environment_vars": [
"REPO_USERNAME={{user `repo_user`}}",
"REPO_PASSWORD={{user `rep_password`}}"
],
"execute_command": "echo 'packer' | sudo -S sh -c '{{ .Vars }} {{ .Path }}'",
"inline": [
"cd /tmp",
"chmod +x bootstrap.sh",
"./bootstrap.sh"
]
}
...
<pull assets>
...
mv /tmp/myservice.service /lib/systemd/system/myservice.service
sudo systemctl enable myservice.service
...
if [ -ne ./user_data_retrieved_flag ]
then
wget http://169.254.169.254/latest/user-data
touch user_data_retrieved_flag
fi
if [ -e ./user-data ] && [ -ne ./user_data_processed_flag ]
then
chmod 755 ./user-data
./user-data
touch user_data_processed_flag
fi
if [ -e /tmp/my_props.properties ]
then
cat /tmp/my_props
mv /tmp/my_props /home/ubuntu/my_props
fi
<myResources.start>
...
...
resource "aws_instance" "my_instance" {
ami = "${var.my_custom_ami}"
...
user_data = <<EOF
#cloud-boothook
#!/bin/bash
touch /tmp/my_props
echo PROP1=${var.prop1} >> /tmp/my_props
echo PROP2_USER=${var.db_un} >> /tmp/my_props
chown ubuntu:ubuntu /tmp/my_props
chmod 777 /tmp/my_props
EOF
}
...
编辑:为了澄清,资产确实运行,所以我知道服务正在成功执行。 但是,它们使用默认道具,并且既没有configure.sh中提到的标志,也没有应该由用户数据创建的文件。
用户数据脚本通过cloud-init执行, cloud-init是一个守护程序,可以在创建/启动时配置实例,独立于图像的内容。
因此,如果您想使用用户数据,您可能希望确保在映像中安装了cloud-init。 这里最简单的选择是简单地从已经安装了cloud-init的预先存在的AMI创建AMI,例如Amazon Linux,官方Canonical提供的Ubuntu AMI,官方Red Hat提供的Red Hat图像等。或者你应该能够通过你的发行包管理器安装它。
如果您想要在没有 cloud-init的情况下在AWS中执行用户数据脚本的最小方式(例如对于没有 cloud-init的发行版,例如OpenBSD),您可以使用以下内容:
#!/bin/sh
# Ghetto cloud-init to execute EC2 user data scripts
ID="$(curl --silent 169.254.169.254/latest/meta-data/instance-id)"
if [ ! -f /var/lib/cloud/instance/boot-finished ] && [ "$(cat /var/lib/cloud/instance/boot-finished)" != "${ID}" ]; then
curl --silent 169.254.169.254/latest/user-data -o /tmp/user-data
chmod +x /tmp/user-data
/tmp/user-data >> /var/log/cloud-init-output.log 2>&1
mkdir -p /var/lib/cloud/instance/
echo "${ID}" > /var/lib/cloud/instance/boot-finished
fi
并将其作为守护进程运行,确保它在启动过程中很早就开始运行。
这将从EC2元数据端点抓取用户数据脚本然后执行它,将输出写入cloud-init的典型日志位置,然后确保它仅在首次启动时执行,并使用在运行之前检查的信号量文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.