¿Cómo hago que los scripts de inicio de cloud-init se ejecuten cada vez que arranca mi instancia EC2?


Tengo una instancia EC2 ejecutando una AMI basada en la AMI de Amazon Linux. Como todas estas AMI, soporta el sistema cloud-init para ejecutar scripts de inicio basados en los Datos de usuario pasados a cada instancia. En este caso en particular, mi entrada de datos de usuario pasa a ser un archivo de Inclusión que las fuentes de varios otros scripts de inicio:

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

La primera vez que arranque mi instancia, el script de inicio cloud-init se ejecuta correctamente. Sin embargo, si hago un reinicio suave de la instancia (ejecutando sudo shutdown -r now, por ejemplo), la instancia regresa sin ejecutando el script de inicio la segunda vez. Si entro en los registros del sistema, puedo ver:

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

Esto no es lo que quiero can Puedo ver la utilidad de tener scripts de inicio que solo se ejecutan una vez por instancia de por vida, pero en mi caso estos deberían ejecutarse cada vez que se inicie la instancia, como los scripts de inicio normales.

Me doy cuenta de que una posible solución es hacer que mis scripts se inserten manualmente en rc.local después de correr la primera vez. Esto parece una carga, sin embargo, desde la nube-init y rc.los entornos d son sutilmente diferentes y ahora tendría que depurar los scripts en el primer lanzamiento y todos los lanzamientos posteriores por separado.

¿Alguien sabe cómo puedo decirle a cloud-init que ejecute siempre mis scripts? Esto ciertamente suena como algo que los diseñadores de cloud-init habrían considerado.

Author: Adrian Petrescu, 2011-06-25

5 answers

En 11.10, 12.04 y posteriores, puede lograr esto haciendo que 'scripts-user' ejecute 'always'. En / etc / cloud / cloud.cfg verás algo como:

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

Esto se puede modificar después del arranque, o los datos de cloud-config que anulan esta estrofa se pueden insertar a través de user-data. Es decir, en los datos de usuario puede proporcionar:

#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

Eso también puede ser '#incluido' como lo has hecho en tu descripción. Desafortunadamente, en este momento, no puede modificar el 'cloud_final_modules', sino que solo lo anula. Espero agregue la capacidad de modificar secciones de configuración en algún momento.

Hay un poco más de información sobre esto en el documento cloud-config en http://bazaar.launchpad.net/~cloud-init-dev/cloud-init/trunk/view/head:/doc/examples/cloud-config.txt

Alternativamente, puede poner archivos en /var/lib/cloud/scripts/per-boot , y serán ejecutados por la ruta 'scripts-per-boot'.

 47
Author: smoser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-04 10:57:27

En /etc/init.d/cloud-init-user-scripts, edita esta línea:

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

A

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

¡Buena suerte !

 18
Author: EvanG,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-04 20:38:30

Una posibilidad, aunque algo hackish, es eliminar el archivo de bloqueo que cloud-init utiliza para determinar si el script de usuario ya se ha ejecutado o no. En mi caso (Amazon Linux AMI), este archivo de bloqueo se encuentra en /var/lib/cloud/sem/ y se llama user-scripts.i-7f3f1d11 (la parte hash al final cambia cada arranque). Por lo tanto, el siguiente script de datos de usuario agregado al final del archivo de inclusión hará el truco:

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

No estoy seguro de si esto tendrá algún efecto adverso en cualquier otra cosa, pero ha funcionado en mis experimentos.

 7
Author: Adrian Petrescu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-06-25 19:55:51

Cloud-init admite esto ahora de forma nativa, consulte las descripciones de comandos runcmd vs bootcmd en la documentación (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 ]

También tenga en cuenta el ejemplo de comando "cloud-init-per" en bootcmd. De su ayuda:

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
 4
Author: Erich Eichinger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-08 08:30:28

Luché con este problema durante casi dos días, probé todas las soluciones que pude encontrar y finalmente, combinando varios enfoques, llegué con lo siguiente:

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}

Esta es la configuración para el proceso de replicación entre regiones de DynamoDB.

 0
Author: Enigo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-09 14:22:33