Как я могу создать пользовательский AMI для Linux с пакером, который принимает пользовательские данные - PullRequest
0 голосов
/ 03 июля 2018

Цель состоит в том, чтобы создать AMI, который конечный пользователь может настроить, включая внешнюю базу данных или другую конкретную конфигурацию экземпляра.

Я создал собственный образ, который извлекает некоторые активы из репозитория в рамках сборки Packer, а затем создает сервис, который запускает скрипт при следующей загрузке. Когда я запускаю экземпляр из этого AMI, я включаю скрипт пользовательских данных, который просто создает файл prop, а затем выводит некоторые значения в файл prop. Затем служебный скрипт создает файл поддержки из пользовательских данных, если он существует, или из значений по умолчанию, а затем запускает ресурсы с этими реквизитами.

Однако после запуска экземпляра файл не создается данными пользователя. Я нашел кое-что о том, что это запускается один раз для каждого экземпляра, но это новый экземпляр.

Я попытался извлечь пользовательские данные как часть служебного скрипта, wget http://169.254.169.254/latest/user-data, удалив файлы состояния, связанные с пользовательскими данными, как часть процесса сборки упаковщика, чтобы user_data снова запускался при создании экземпляра AMI, rm -Rf /var/lib/cloud/*, добавляя пользовательские данные с #cloud-boothook, чтобы они запускались каждый раз вместо первой загрузки. Однако файл tmp из сценария пользовательских данных отсутствует, а ресурсы начинаются только со значений по умолчанию.

Упаковщик build.json

...
{
  "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"
  ]
}
...

bootstrap.sh

<pull assets>
...
mv /tmp/myservice.service /lib/systemd/system/myservice.service
sudo systemctl enable myservice.service
...

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>
...

Terraform

...
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, ни файла, который должен был быть создан данными пользователя.

1 Ответ

0 голосов
/ 03 июля 2018

Сценарии пользовательских данных выполняются через cloud-init , демон, который может настраивать экземпляры во время создания / загрузки независимо от того, что запечено в образ.

Таким образом, если вы хотите использовать пользовательские данные, вы, вероятно, хотите убедиться, что cloud-init установлен в вашем образе. Самый простой вариант здесь - просто создать свой AMI из уже существующего AMI, в котором уже установлен cloud-init, например Amazon Linux, официальные Canonical UI для Ubuntu, официальные Red Hat, предоставленные образы Red Hat и т. Д. В качестве альтернативы вы должны иметь возможность установить его через менеджер пакетов вашего дистрибутива.

Если вам нужен минимальный способ выполнения сценариев пользовательских данных в AWS без cloud-init (например, для дистрибутивов, где 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, а затем убедится, что он выполняется только при первой загрузке с проверенным файлом семафора. для перед запуском.

...