Cloud-Init and User-Data

From Dikapedia
Jump to: navigation, search

Cloud-Init


add notes: https://cloudinit.readthedocs.io/en/latest/topics/dir_layout.html


Cloud-init is the industry standard multi-distribution method for cross-platform cloud instance initialization. It is supported across all major public cloud providers, provisioning systems for private cloud infrastructure, and bare-metal installations.

Cloud instances are initialized from a disk image and instance data:

Cloud metadata User data (optional) Vendor data (optional) Cloud-init will identify the cloud it is running on during boot, read any provided metadata from the cloud and initialize the system accordingly. This may involve setting up the network and storage devices to configuring SSH access key and many other aspects of a system. Later on the cloud-init will also parse and process any optional user or vendor data that was passed to the instance.

For more information, see the cloud-init documentation.



Reference: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/amazon-linux-ami-basics.html#amazon-linux-cloud-init

The cloud-init package is an open-source application built by Canonical that is used to bootstrap Linux images in a cloud computing environment, such as Amazon EC2. Amazon Linux contains a customized version of cloud-init. It enables you to specify actions that should happen to your instance at boot time. You can pass desired actions to cloud-init through the user data fields when launching an instance. This means you can use common AMIs for many use cases and configure them dynamically at startup. Amazon Linux also uses cloud-init to perform initial configuration of the ec2-user account.



Amazon Linux uses the cloud-init actions found in /etc/cloud/cloud.cfg.d and /etc/cloud/cloud.cfg. You can create your own cloud-init action files in /etc/cloud/cloud.cfg.d. All files in this directory are read by cloud-init. They are read in lexical order, and later files overwrite values in earlier files.



There are several different formats supported by cloud-init. We pass a MIME file as part of instance user-data, and depending the format of the content of the user data file, the commands or scripts in the file will be executed at different point in time during the boot.

The Cloud-init service will save the scripts passed through user data in directory /var/lib/cloud/instances/<instance ID>/scripts directory. These scripts are executed in the final stage of the boot.


Configuration files and Logs


/etc/cloud/cloud.cfg - cloud-init configuration file. Has the cloud_final_modules.

/var/lib/cloud/scripts - Where to add scripts for cloud-init (i.e. scripts/per-boot, scripts/per-instance, scripts/per-once)

/var/log/cloud-init.log

/var/log/cloud-init-output.log <--- you would want to check this when troubleshooting boot up issues.


User-Data



User data and shell scripts
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html#user-data-shell-scripts


The cloud-init output log file (/var/log/cloud-init-output.log) captures console output so it is easy to debug your scripts following a launch if the instance does not behave the way you intended.


When a user data script is processed, it is copied to and run from /var/lib/cloud/instances/instance-id/. The script is not deleted after it is run. Be sure to delete the user data scripts from /var/lib/cloud/instances/instance-id/ before you create an AMI from the instance. Otherwise, the script will exist in this directory on any instance launched from the AMI.


If you are unable to run a *REGULAR* #!/bin/bash script in user-data on the first try, try removing /var/lib/cloud/instances/instance-id/*, then stop the instance, edit/add user-data, and then start the instance:

sudo rm -rf /var/lib/cloud/instances/*

Otherwise, use Mime multipart.



How to run user-data on every boot


https://aws.amazon.com/premiumsupport/knowledge-center/execute-user-data-ec2/ (MIME Multipart)


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/sleep 10
/bin/systemctl stop apache2
--//


How to run scripts on every boot WITHOUT using user-data


I found the way. Under /var/lib/cloud/scripts/ there are these directories:

$ ls -al /var/lib/cloud/scripts/
total 0
drwxr-xr-x 6 root root 72 Mar 15 14:18 .
drwxr-xr-x 8 root root 105 Mar 15 14:27 ..
drwxr-xr-x 2 root root 40 Mar 15 14:25 per-boot
drwxr-xr-x 2 root root  6 Mar 15 14:18 per-instance
drwxr-xr-x 2 root root  6 Mar 15 14:18 per-once
drwxr-xr-x 2 root root  6 Mar 15 14:18 vendor

Per cloud-init's official documentation, any scripts in the scripts/per-boot directory will be run every time the system is booted, any scripts in the scripts/per-instance directory will be run when a new instance is first booted, and any scripts in the scripts/per-once directory will be run only once.


For example, if I add a script under the per-boot directory, it will always run upon boot ups as long as the /etc/cloud/cloud.cfg file has these modules:

cloud_final_modules:
 - scripts-per-once
 - scripts-per-boot
 - scripts-per-instance
 - scripts-user
 - ssh-authkey-fingerprints
 - keys-to-console
 - phone-home
 - final-message
 - power-state-change


I tested out a simple script under the /var/lib/cloud/scripts/per-boot directory. This was my script, which simply creates a text file in the ec2-user home directory called "this_was_from_per_boot_cloud_init_script.txt":

$ cat /var/lib/cloud/scripts/per-boot/script_was_ran_per_boot.sh 
touch /home/ec2-user/this_was_from_per_boot_cloud_init_script.txt

Then I gave it executable permissions:

$ sudo chmod 744 /var/lib/cloud/scripts/per-boot/script_was_ran_per_boot.sh 

Then I rebooted the system:

$ sudo reboot

Upon boot up, I could see that the script was ran successfully because the file was created:

$ ls -al
total 16
drwx------ 3 ec2-user ec2-user 173 Mar 15 14:27 .
drwxr-xr-x 3 root   root   22 Mar 15 14:18 ..
-rw------- 1 ec2-user ec2-user 395 Mar 15 14:26 .bash_history
-rw-r--r-- 1 ec2-user ec2-user 18 Jul 15 2020 .bash_logout
-rw-r--r-- 1 ec2-user ec2-user 193 Jul 15 2020 .bash_profile
-rw-r--r-- 1 ec2-user ec2-user 231 Jul 15 2020 .bashrc
drwx------ 2 ec2-user ec2-user 29 Mar 15 14:18 .ssh
-rw-r--r-- 1 root   root    0 Mar 15 14:27 this_was_from_per_boot_cloud_init_script.txt   <------

As you can see, adding a script under /var/lib/cloud/scripts/per-boot/ will work.



Ardika: What is “Content-Type” block for? Ardika: MIME version and the lines underneath Rob: Bootstrapping it to load into cloud-init. UserData only runs at launch unless it's loaded this way Ardika: I see, so if we just did:

  1. !/bin/bash

/bin/sleep 10 /bin/systemctl stop apache2

Apache will still come up at launch UserData gets pushed as a giant block of base64 encoded mess. This tells the subsystem how to decode it

I found the doc: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/bootstrap_container_instance.html#multi-part_user_data

the UserData wouldn't run. I think it might work at initial launch. Haven't tested in a while


How to disable Iptables and UFW using user-data script (Nshn's way)


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
sudo service iptables stop
sudo chkconfig iptables off
sudo service firewalld stop
sudo chkconfig firewalld off
sudo ufw status
sudo ufw disable
echo "UserData is Executed"
--//
  • Tested, confirmed it works

How can I connect to my Amazon EC2 instance if I lost my SSH key pair after its initial launch


https://aws.amazon.com/premiumsupport/knowledge-center/user-data-replace-key-pair-ec2/


How can I send user-data output to the console logs on an EC2 instance?


#!/bin/bash -xe
exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1
yum -y update
echo "Hello from user-data!"

https://aws.amazon.com/premiumsupport/knowledge-center/ec2-linux-log-user-data/