35

I am using openstack to create a VM using 'nova boot' command. My image is cloud-init enabled. I pass a --user-data script which is a bash shell format for cloud-init to run during VM boot up time. All this happens successfully. Now my use-case is to re-run cloud-init to execute the same user-data script without rebooting the VM. I saw /usr/bin/cloud-init options and they do talk about running specific modules but nothing is able to make it execute the same user-data script. How can this be achieved ? Any help would be appreciated.

user3532850
  • 351
  • 1
  • 3
  • 4
  • Does this answer your question? [How to run cloud-init manually?](https://stackoverflow.com/questions/23151425/how-to-run-cloud-init-manually) – Henke Oct 11 '20 at 06:26

5 Answers5

40

While re-running all of cloud-init without reboot isn't a recommended approach, the following commands will allow you to accomplish this on a system.

The commands have been updated so to re-run you need to clean out the existing config:

sudo cloud-init clean --logs

cloud-init typically runs multiple boot stages in order due to systemd service dependencies. If you want to repeat that process without a reboot you can run the following 4 commands:

  1. Detect local datasource (cloud platform):

    sudo cloud-init init --local

  2. Detect any datasources which require network up and run "cloud_init_modules" defined in /etc/cloud/cloud.cfg:

    sudo cloud-init init

  3. Run all cloud_config_modules defined in /etc/cloud/cloud.cfg:

    sudo cloud-init modules --mode=config

  4. Run all cloud_final_modules defined in /etc/cloud/cloud.cfg: sudo cloud-init modules --mode=final

Beware: things like ssh host keys maybe regenerated.

Chad Smith
  • 63
  • 4
Pierz
  • 7,064
  • 52
  • 59
  • 1
    Thank you. I've been looking for a way to force cloud-init to fully run on the next boot. `cloud-init clean` is what I've been looking for. Everywhere else suggests deleting files under /var/lib/cloud, which doesn't reset SSH keys (and likely some other things). – Brandon Bonds Jun 21 '19 at 21:48
21

In order for cloud-init to reset, you need to execute rm -rf /var/lib/cloud/instances.

Then re run the cloud-init start and it will run the full boot script process again.

Nakilon
  • 34,866
  • 14
  • 107
  • 142
benh57
  • 657
  • 5
  • 11
  • 12
    `start` does not seem to be a valid parameter on current versions – Gert van den Berg Sep 11 '19 at 12:26
  • I see no point in copypasting another answer over your one. If your one is outdated the more updated one will just get more upvotes eventually. If you don't want your answer to be then delete it but I would preserve it for the history. – Nakilon Jul 30 '21 at 13:14
  • Makes sense. Perhaps a note in my answer stating to check the below for more recent versions would be more appropriate? – benh57 Aug 03 '21 at 02:19
14

Since this keeps popping up in search results, what works for me:

  1. Delete semaphores in /var/lib/cloud/instances/i-xxxxxxx/sem. Cloud-init will not re-run if these files are present.

  2. Edit /var/lib/cloud/instances/i-xxxxxxxx/scripts/part-001. This is your user-data script.

  3. Execute only the user scripts module of cloud-init. This will not re-download user data but execute the already downloaded (and now, modified) script from step 2.

    sudo /usr/bin/cloud-init single -n cc_scripts_user

Community
  • 1
  • 1
kadrach
  • 408
  • 6
  • 11
  • CentOS 7.3.1611, cloud-init 0.7.5, I don't have anything in /var/lib/cloud/instances/i-xxxxxxxx/scripts @kadrach – Artem Jul 20 '17 at 21:43
  • Did you replace `i-xxxxxxxxxx` with the appropriate folder? It should be the identifier of the instance you are running this on (I've never seen more than one folder in there). – kadrach Jul 21 '17 at 06:32
  • yes I did, I figured out the issue by narrowing it down already, but cloud-init logs are way too minimalistic and very-well done – Artem Jul 23 '17 at 01:01
  • 1
    I also have nothing inside `/var/lib/cloud/instances/i-xxxxxxxx/scripts`. I have got the correct instance, but all the user data (entered by me when creating a VM in OpenStack) is in `cloud-config.txt` and `user-data.txt`. When I follow the instructions, #3 doesn't work, maybe because there's nothing inside the `/scripts` folder? Any ideas? @kadrach @Artem – MRichards Apr 05 '19 at 13:44
  • I'm not sure if there are implementation differences in how this is handled in other cloud providers, the above appears to work for EC2 instances with all images I've tried. I don't have access to OpenStack to check, unfortunately. – kadrach Apr 15 '19 at 02:13
  • 1
    Just to add a precision. In the case you want to run the module `cc_scripts_user`, delete the corresponding semaphore with `rm /var/lib/cloud/instance/sem/config_cc_scripts_user` – user1067920 Nov 21 '19 at 15:33
3

Given that this post was actively touched 6 months ago I wanted to provide a more complete answer here from cloud-init upstream.

The original question: "how to re-run a user-data script again at a later time with cloud-init" Generally user-scripts are only run once per-instance by the config module config-user-scripts. If the instance-id in metadata doesn't change it won't re-run.

The per-instance semaphores can be bypassed with the following command line by telling it to run the user-scripts module regardless of instance-id:

sudo cloud-init single --name scripts-user --frequency always

Per the other suggesting to re-running all of cloud-init without system reboot. It isn't a recommended approach because some parts of cloud-init are run at systemd generator timeframe to detect new datasource types. That said, the following commands will allow you to accomplish this without reboot on a system.

cloud-init supports a clean subcommand to remove all semaphore files and allow cloud-init to re-run all config modules again. Beware that this will mean SSH host-keys are regenerated and .ssh config files re-written so it could impact your ability to get back into the VM.

To clean all semaphores so cloud-init modules will all re-run on next boot:

sudo cloud-init clean --logs

cloud-init typically runs multiple boot stages in sequence due to systemd service dependencies. If you want to repeat that process without a reboot you can run the following 4 commands:

  1. Detect local datasource (cloud platform):

    sudo cloud-init init --local

  2. Detect any datasources which require network up and run "cloud_init_modules" defined in /etc/cloud/cloud.cfg:

    sudo cloud-init init

  3. Run all cloud_config_modules defined in /etc/cloud/cloud.cfg:

    sudo cloud-init modules --mode=config

  4. Run all cloud_final_modules defined in /etc/cloud/cloud.cfg:

    sudo cloud-init modules --mode=final

Chad Smith
  • 63
  • 4
0

To run the packages module of cloud-config part of cloud-init, you can run

# cloud-init-cfg all config

To run the runcmd module of cloud-config part of cloud-init, you can run

# cloud-init-cfg all final
jrwren
  • 17,465
  • 8
  • 35
  • 56