Как сделать так, чтобы скрипты запуска cloud-init запускались каждый раз при загрузке моего экземпляра EC2? - PullRequest
48 голосов
/ 25 июня 2011

У меня есть экземпляр EC2, использующий AMI на основе Amazon Linux AMI. Как и все такие AMI, он поддерживает систему cloud-init для запуска сценариев запуска на основе пользовательских данных, передаваемых в каждый экземпляр. В данном конкретном случае мой ввод данных пользователя является файлом включения, который содержит несколько других сценариев запуска:

#include
http://s3.amazonaws.com/path/to/script/1
http://s3.amazonaws.com/path/to/script/2

При первой загрузке моего экземпляра скрипт запуска cloud-init запускается правильно. Однако, если я выполню мягкую перезагрузку экземпляра (например, запустив sudo shutdown -r now), экземпляр вернется обратно без , запустив сценарий запуска во второй раз. Если я захожу в системные журналы, я вижу:

Running cloud-init user-scripts
user-scripts already ran once-per-instance
[  OK  ]

Это не то, что я хочу - я вижу полезность наличия сценариев запуска, которые запускаются только один раз за время существования экземпляра, но в моем случае они должны запускаться при каждом запуске экземпляра, как обычные сценарии запуска.

Я понимаю, что одним из возможных решений является ручное включение моих скриптов в rc.local после первого запуска. Однако это кажется обременительным, поскольку среды cloud-init и rc.d немного отличаются друг от друга, и теперь мне придется отлаживать сценарии при первом запуске и всех последующих запусках отдельно.

Кто-нибудь знает, как я могу сказать cloud-init всегда запускать мои скрипты? Это, безусловно, звучит как то, что разработчики cloud-init рассмотрели бы.

Ответы [ 6 ]

53 голосов
/ 04 мая 2012

В 11.10, 12.04 и более поздних версиях вы можете добиться этого, заставляя 'scripts-user' запускать 'всегда'.В /etc/cloud/cloud.cfg вы увидите что-то вроде:

cloud_final_modules:
 - rightscale_userdata
 - scripts-per-once
 - scripts-per-boot
 - scripts-per-instance
 - scripts-user
 - keys-to-console
 - phone-home
 - final-message

Это можно изменить после загрузки, или данные конфигурации облака, переопределяющие этот раздел, можно вставить через пользовательские данные.То есть в пользовательских данных вы можете указать:

#cloud-config
cloud_final_modules:
 - rightscale_userdata
 - scripts-per-once
 - scripts-per-boot
 - scripts-per-instance
 - [scripts-user, always]
 - keys-to-console
 - phone-home
 - final-message

Это также может быть "#included", как вы сделали в своем описании.К сожалению, сейчас вы не можете изменить «cloud_final_modules», а только переопределить его.Я надеюсь добавить возможность изменять разделы конфигурации в какой-то момент.

Есть немного больше информации об этом в документе cloud-config в http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/doc/examples/cloud-config.txt

В качестве альтернативы, вы можете поместить файлыв / var / lib / cloud / scripts / per-boot, и они будут запускаться по пути 'scripts-per-boot'.

19 голосов
/ 04 декабря 2011

В /etc/init.d/cloud-init-user-scripts, отредактируйте эту строку:

/usr/bin/cloud-init-run-module once-per-instance user-scripts execute run-parts ${SCRIPT_DIR} >/dev/null && success || failure

до

 /usr/bin/cloud-init-run-module always user-scripts execute run-parts ${SCRIPT_DIR} >/dev/null && success || failure

Удачи!

8 голосов
/ 06 июля 2017

cloud-init теперь поддерживает это изначально, см. Описания команд runcmd и bootcmd в документации (http://cloudinit.readthedocs.io/en/latest/topics/examples.html#run-commands-on-first-boot):

"runcmd":

#cloud-config

# run commands
# default: none
# runcmd contains a list of either lists or a string
# each item will be executed in order at rc.local like level with
# output to the console
# - runcmd only runs during the first boot
# - if the item is a list, the items will be properly executed as if
#   passed to execve(3) (with the first arg as the command).
# - if the item is a string, it will be simply written to the file and
#   will be interpreted by 'sh'
#
# Note, that the list has to be proper yaml, so you have to quote
# any characters yaml would eat (':' can be problematic)
runcmd:
 - [ ls, -l, / ]
 - [ sh, -xc, "echo $(date) ': hello world!'" ]
 - [ sh, -c, echo "=========hello world'=========" ]
 - ls -l /root
 - [ wget, "http://slashdot.org", -O, /tmp/index.html ]

"bootcmd":

#cloud-config

# boot commands
# default: none
# this is very similar to runcmd, but commands run very early
# in the boot process, only slightly after a 'boothook' would run.
# bootcmd should really only be used for things that could not be
# done later in the boot process.  bootcmd is very much like
# boothook, but possibly with more friendly.
# - bootcmd will run on every boot
# - the INSTANCE_ID variable will be set to the current instance id.
# - you can use 'cloud-init-per' command to help only run once
bootcmd:
 - echo 192.168.1.130 us.archive.ubuntu.com >> /etc/hosts
 - [ cloud-init-per, once, mymkfs, mkfs, /dev/vdb ]

также обратите внимание на пример команды «cloud-init-per» в bootcmd. Из его справки:

Usage: cloud-init-per frequency name cmd [ arg1 [ arg2 [ ... ] ]
   run cmd with arguments provided.

   This utility can make it easier to use boothooks or bootcmd
   on a per "once" or "always" basis.

   If frequency is:
      * once: run only once (do not re-run for new instance-id)
      * instance: run only the first boot for a given instance-id
      * always: run every boot
7 голосов
/ 25 июня 2011

Одной из возможностей, хотя и несколько хакерской, является удаление файла блокировки, который использует cloud-init, чтобы определить, был ли уже запущен пользовательский скрипт.В моем случае (Amazon Linux AMI) этот файл блокировки находится в /var/lib/cloud/sem/ и называется user-scripts.i-7f3f1d11 (хэш-часть в конце изменяется при каждой загрузке).Таким образом, следующий скрипт пользовательских данных, добавленный в конец файла включения, справится с задачей:

#!/bin/sh
rm /var/lib/cloud/sem/user-scripts.*

Я не уверен, окажет ли это какое-либо неблагоприятное влияние на что-либо еще, но это сработалов моих экспериментах.

1 голос
/ 09 января 2018

Я боролся с этой проблемой почти два дня, перепробовал все найденные решения и, наконец, соединив несколько подходов, получил следующее:

MyResource:
  Type: AWS::EC2::Instance
  Metadata:
    AWS::CloudFormation::Init:
      configSets:
        setup_process:
          - "prepare"
          - "run_for_instance"
      prepare:
        commands:
          01_apt_update:
            command: "apt-get update"
          02_clone_project:
            command: "mkdir -p /replication && rm -rf /replication/* && git clone https://github.com/awslabs/dynamodb-cross-region-library.git /replication/dynamodb-cross-region-library/"
          03_build_project:
            command: "mvn install -DskipTests=true"
            cwd: "/replication/dynamodb-cross-region-library"
          04_prepare_for_apac:
            command: "mkdir -p /replication/replication-west && rm -rf /replication/replication-west/* && cp /replication/dynamodb-cross-region-library/target/dynamodb-cross-region-replication-1.2.1.jar /replication/replication-west/replication-runner.jar"
      run_for_instance:
        commands:
          01_run:
            command: !Sub "java -jar replication-runner.jar --sourceRegion us-east-1 --sourceTable ${TableName} --destinationRegion ap-southeast-1 --destinationTable ${TableName} --taskName -us-ap >/dev/null 2>&1 &"
            cwd: "/replication/replication-west"
  Properties:
    UserData:
      Fn::Base64:
        !Sub |
          #cloud-config
          cloud_final_modules:
           - [scripts-user, always]
          runcmd:
           - /usr/local/bin/cfn-init -v -c setup_process --stack ${AWS::StackName} --resource MyResource --region ${AWS::Region}
           - /usr/local/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource MyResource --region ${AWS::Region}

Это настройка для процесса межрегиональной репликации DynamoDb.

0 голосов
/ 20 декабря 2018

пожалуйста, используйте приведенный ниже скрипт над вашим bash-скриптом.

пример: здесь я печатаю привет миру в мой файл

остановка экземпляра перед добавлением в userdata

Сценарий

Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
/bin/echo "Hello World." >> /var/tmp/sdksdfjsdlf
--//
...