Comment puis-je exécuter les scripts de démarrage de cloud-init à chaque démarrage de mon instance EC2?

J’ai une instance EC2 exécutant une AMI basée sur l’AMI Amazon Linux. Comme toutes ces AMI, il prend en charge le système cloud-init pour l’exécution de scripts de démarrage basés sur les données utilisateur transmises dans chaque instance. Dans ce cas particulier, mon entrée de données utilisateur se trouve être un fichier Include qui source plusieurs autres scripts de démarrage:

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

La première fois que je démarre mon instance, le script de démarrage de cloud-init s’exécute correctement. Cependant, si je redémarre doucement l’instance (en exécutant sudo shutdown -r now , par exemple), l’instance revient sans exécuter le script de démarrage la deuxième fois. Si je vais dans les journaux du système, je peux voir:

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

Ce n’est pas ce que je veux – je peux voir l’utilité d’avoir des scripts de démarrage qui ne fonctionnent qu’une seule fois par durée d’instance, mais dans mon cas, ils devraient être exécutés chaque fois que l’instance démarre, comme les scripts de démarrage normaux.

Je me rends compte que l’une des solutions possibles consiste à insérer manuellement mes scripts dans rc.local après la première exécution. Cela semble toutefois fastidieux, car les environnements cloud-init et rc.d sont subtilement différents et je devrais maintenant déboguer les scripts au premier lancement et tous les lancements suivants séparément.

Est-ce que quelqu’un sait comment je peux dire à cloud-init de toujours exécuter mes scripts? Cela semble certainement être quelque chose que les concepteurs de cloud-init auraient considéré.

En 11.10, 12.04 et versions ultérieures, vous pouvez atteindre cet objective en faisant en sorte que «script-user» s’exécute toujours. Dans /etc/cloud/cloud.cfg, vous verrez quelque chose comme:

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

Cela peut être modifié après le démarrage, ou les données cloud-config remplaçant cette strophe peuvent être insérées via des données utilisateur. Ie, dans les données utilisateur, vous pouvez fournir:

 #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 

Cela peut aussi être “inclus” comme vous l’avez fait dans votre description. Malheureusement, pour le moment, vous ne pouvez pas modifier les ‘cloud_final_modules’, mais seulement les remplacer. J’espère pouvoir append la possibilité de modifier les sections de configuration à un moment donné.

Il y a un peu plus d’informations à ce sujet dans le document cloud-config à l’ adresse http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/doc/examples/cloud-config. .SMS

Vous pouvez également placer des fichiers dans / var / lib / cloud / scripts / per-boot et ils seront exécutés par le chemin “scripts-per-boot”.

Dans /etc/init.d/cloud-init-user-scripts , éditez cette ligne:

 /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 

Bonne chance !

Une possibilité, bien que quelque peu piratée, consiste à supprimer le fichier de locking utilisé par cloud-init pour déterminer si le script utilisateur a déjà été exécuté ou non. Dans mon cas (Amazon Linux AMI), ce fichier de locking se trouve dans /var/lib/cloud/sem/ et s’appelle user-scripts.i-7f3f1d11 (la partie de hachage à la fin modifie chaque démarrage). Par conséquent, le script de données utilisateur suivant ajouté à la fin du fichier Include fera l’affaire:

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

Je ne suis pas sûr si cela aura des effets négatifs sur autre chose, mais cela a fonctionné dans mes expériences.

cloud-init le supporte maintenant en natif, voir les descriptions des commandes runcmd vs bootcmd dans la documentation ( 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 ssortingng # 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 ssortingng, 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 ] 

Notez également l’exemple de commande “cloud-init-per” dans bootcmd. De son aide:

 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 

J’ai lutté avec ce problème pendant près de deux jours, essayé toutes les solutions que je pouvais trouver et, finalement, combinant plusieurs approches, voici ce qui suit:

 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_west: 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} 

Ceci est la configuration du processus de réplication inter-régions DynamoDb.