Recently I wrote an
article on how to get cloud-init working locally http://www.whiteboardcoder.com/2016/04/install-cloud-init-on-ubuntu-and-use.html [1]
The basic idea was
install cloud-init on a non-cloud install of Ubuntu. Then to create a meta-data and user-data file
at /var/lib/cloud/seed/nocloud-net then reboot. The user-data file is the cloud-config file
and the meta-data file is some presetting that I got to work partially.
Why would I do all of
this? I am used to using the AWS cloud
or OpenStack, both of which support cloud-init. I am planning on building an OpenStack box
at home… someday… but I keep getting delayed with life.
In the meantime I do
have an ESXi box built out and running at home.
It works great. But boy do I wish
I had a simple nice interface or command line tool that would allow me to tell
it to build a box of X size and run this cloud-init file.
Running cloud-init
locally I can kind of get that working well enough.
- Create a very base image with cloud-init installed
- Copy my meta-data and user-data (cloud-init) files to /var/lib/cloud/seed/nocloud-net
- Reboot (and let cloud-init do its thing)
- Move VM over to my ESXi server
But I think I can one up
it. From what I have been reading I
think I can set cloud-init to grab the meta-data and user-data files from a
URL. If I can get that working I can
put all my meta-data and user-data files in a git repo, for tracking, then put
the repo files on an internal nginx server I can link to. Then I just have to edit a cloud-init config
file to point in the right direction and I am good to go.
First a simple example (No URL)
First I want to show how
to get a local simple cloud-init working on a fresh Ubuntu 14.04 install.
Install cloud-init
>
sudo apt-get install cloud-init
|
Create the /var/lib/cloud/seed/nocloud-net/ folder
> sudo mkdir -p /var/lib/cloud/seed/nocloud-net
|
Make a very simple meta-data file
>
sudo vi /var/lib/cloud/seed/nocloud-net/meta-data
|
local-hostname: my-servername
|
(This will change the
servers name to my-servername)
Use write_files to create a new /etc/network/interfaces
file.
>
sudo vi /var/lib/cloud/seed/nocloud-net/user-data
|
#cloud-config
#
####################
##################################################
#
# Install packages
#
##################################################
packages:
- htop
- tree
##################################################
#
# Reboot the machine when done.
# This is done to make sure the mount script is
# working
#
##################################################
power_state:
delay: "now"
mode: reboot
message: First Reboot!
timeout: 30
##################################################
#
# Create groups
#
##################################################
groups:
- patman
##################################################
#
# Create users.
# * set their prefered
shell
# * Set their group
membership
# * give them admin permissions
# * Set their password
(copied from ecnrypted version @ /etc/shadow)
# * Input Public SSH
keys to allow access
#
##################################################
users:
- default
- name: patman
shell: /bin/bash
sudo: [ "ALL=(ALL)
ALL" ]
primary-group: patman
passwd: $6$C5Hpbc-NOTREALKEY
ssh-authorized-keys:
- ssh-rsa AAAAB3NzaC-NOTREALKEY
##################################################
#
# runcmd:
# List of commands to
execute
# If a command has a
verbose setting, it's a
# good idea to use
it. Just in case you
# Need to debug later.
# Output is logged to
#
/var/log/cloud-init-output.log
#
##################################################
runcmd:
##################################################
#
# passwd <username> -u
# When a user is created
and their password
# set... their password is locked in /etc/shadow
# (it has a '!' in front of their encrypted
# password, hard to see and a pain)
# This command unlocks it
#
##################################################
- 'passwd patman -u'
##################################################
#
# This fixes the hostname in /etc/hosts
# which removes annoying messages when you
# are trying to run commands using sudo
#
##################################################
- 'echo 127.0.0.1
`hostname` >> /etc/hosts'
##################################################
#
# write_files:
# Files to write out.
#
##################################################
write_files:
##################################################
#
# Set static IP address (would rather do this in meta-data but
it is no
# working at the moment)
# @
/etc/network/interfaces
#
##################################################
- path:
/etc/network/interfaces
permissions: '0644'
owner: root:root
content: |
auto lo
iface lo inet
loopback
#
#
auto eth0
iface eth0 inet
static
address
192.168.0.75
netmask
255.255.255.0
broadcast
192.168.1.255
gateway
192.168.0.1
dns-nameservers 8.8.8.8
|
What will this cloud-init file do? Let me go piece by piece
packages
##################################################
#
# Install packages
#
##################################################
packages:
- htop
- tree
|
This section tells it to install htop and tree
power_state (reboot)
##################################################
#
# Reboot the machine when done.
# This is done to make sure the mount script is
# working
#
##################################################
power_state:
delay: "now"
mode: reboot
message: First Reboot!
timeout: 30
|
This section tells it to reboot after cloud-init is done.
groups
##################################################
#
# Create groups
#
##################################################
groups:
- patman
|
This section is creates groups. I am creating a group for my user that has
the same name as my user.
users
##################################################
#
# Create users.
# * set their prefered
shell
# * Set their group
membership
# * give them admin permissions
# * Set their password
(copied from ecnrypted version @ /etc/shadow)
# * Input Public SSH
keys to allow access
#
##################################################
users:
- default
- name: patman
shell: /bin/bash
sudo: [ "ALL=(ALL)
ALL" ]
primary-group: patman
passwd: $6$C5Hpbc-NOTREALKEY
ssh-authorized-keys:
- ssh-rsa AAAAB3NzaC-NOTREALKEY
|
In this section you can add your user and get them set up
the way you want. I've set up the
default shell, my primary group, my password (as taken from /etc/shadow), and
my ssh public keys.
runcmd
##################################################
#
# runcmd:
# List of commands to
execute
# If a command has a
verbose setting, it's a
# good idea to use
it. Just in case you
# Need to debug later.
# Output is logged to
#
/var/log/cloud-init-output.log
#
##################################################
runcmd:
##################################################
#
# passwd <username> -u
# When a user is created
and their password
# set... their password is locked in /etc/shadow
# (it has a '!' in front of their encrypted
# password, hard to see and a pain)
# This command unlocks it
#
##################################################
- 'passwd patman -u'
##################################################
#
# This fixes the hostname in /etc/hosts
# which removes annoying messages when you
# are trying to run commands using sudo
#
##################################################
- 'echo 127.0.0.1 `hostname`
>> /etc/hosts'
|
Runcmd basically defines a bash script to run. This is useful to do some setup that
otherwise can't be done in other cloud-init modules.
This particular runcmd would result in this bash file being
created and run.
#!/bin/sh
passwd patman -u
echo 127.0.0.1 `hostname` >> /etc/hosts
|
These command unlock the user patman (who is created in a
locked state). It also updates the
/etc/hosts file to add the new hostname to it so you don't get that annoying
warning when running sudo commands in Ubuntu.
write_files
##################################################
#
# write_files:
# Files to write out.
#
##################################################
write_files:
##################################################
#
# Set static IP address (would rather do this in meta-data but
it is no
# working at the moment)
# @
/etc/network/interfaces
#
##################################################
- path:
/etc/network/interfaces
permissions: '0644'
owner: root:root
content: |
auto lo
iface lo inet
loopback
#
#
auto eth0
iface eth0 inet
static
address
192.168.0.75
netmask
255.255.255.0
broadcast
192.168.1.255
gateway
192.168.0.1
dns-nameservers 8.8.8.8
|
This section creates a new /etc/network/interfaces
file. In my case it will set a static IP
address to 192.168.0.75 on a reboot.
Then reboot it
> sudo reboot now
|
Now, I should also be able to login as patman at the static
IP address.
> ssh patman@192.168.0.75
|
And tree and htop should be installed.
OK that is all working… Now to figure out how to move it to
a URL and get cloud-init to use that URL.
Create a URL
You can come up with your own idea on where to store stuff
but here is my method.
I happen to have an nginx server running on one of my local
machines. I am going to make a directory
there and set It up to listen on port 8888 (which in my case is not available outside my
network).
> sudo vi
/etc/nginx/nginx.conf
|
I added this section to it.
server {
listen 8888;
location / {
root
/nginx/cloud-init/;
}
}
|
Let me make the folder
> sudo mkdir
/nginx/cloud-init
> sudo chown
www-data:www-data /nginx/cloud-init
|
And restart nginx
> sudo service nginx
restart
|
Within /nginx/cloud-init
I think I will eventually create some folder structure that makes sense for me
and my servers. But for now I will just
make a test folder there.
> cd
/nginx/cloud-init
> sudo mkdir test
|
Meta-data file/url
Create the meta-data
file
> sudo vi
test/meta-data
|
And place the following in it.
local-hostname: my-servername
|
User-data file/url
Create the user-data
file
> sudo vi
test/user-data
|
And place the following in it.
#cloud-config
#
####################
##################################################
#
# Install packages
#
##################################################
packages:
- htop
- tree
##################################################
#
# Reboot the machine when done.
# This is done to make sure the mount script is
# working
#
##################################################
power_state:
delay: "now"
mode: reboot
message: First Reboot!
timeout: 30
##################################################
#
# Create groups
#
##################################################
groups:
- patman
##################################################
#
# Create users.
# * set their prefered
shell
# * Set their group
membership
# * give them admin
permissions
# * Set their password
(copied from ecnrypted version @ /etc/shadow)
# * Input Public SSH
keys to allow access
#
##################################################
users:
- default
- name: patman
shell: /bin/bash
sudo: [ "ALL=(ALL)
ALL" ]
primary-group: patman
passwd: $6$C5Hpbc-NOTREALKEY
ssh-authorized-keys:
- ssh-rsa AAAAB3NzaC-NOTREALKEY
##################################################
#
# runcmd:
# List of commands to
execute
# If a command has a
verbose setting, it's a
# good idea to use
it. Just in case you
# Need to debug later.
# Output is logged to
#
/var/log/cloud-init-output.log
#
##################################################
runcmd:
##################################################
#
# passwd <username> -u
# When a user is created
and their password
# set... their password is locked in /etc/shadow
# (it has a '!' in front of their encrypted
# password, hard to see and a pain)
# This command unlocks it
#
##################################################
- 'passwd patman -u'
##################################################
#
# This fixes the hostname in /etc/hosts
# which removes annoying messages when you
# are trying to run commands using sudo
#
##################################################
- 'echo 127.0.0.1
`hostname` >> /etc/hosts'
##################################################
#
# write_files:
# Files to write out.
#
##################################################
write_files:
##################################################
#
# Set static IP address (would rather do this in meta-data but
it is no
# working at the moment)
# @ /etc/network/interfaces
#
##################################################
- path:
/etc/network/interfaces
permissions: '0644'
owner: root:root
content: |
auto lo
iface lo inet
loopback
#
#
auto eth0
iface eth0 inet
static
address 192.168.0.75
netmask
255.255.255.0
broadcast
192.168.1.255
gateway
192.168.0.1
dns-nameservers 8.8.8.8
|
Now, in my case I have a url for meta-data at
http://192.168.0.80:8888/test/meta-data
and a url for user-data at
http://192.168.0.80:8888/test/user-data
I think it should be ready now.
First Attempt (Failed miserably)
Now back to a very fresh install of Ubuntu 14.04.
First install cloud-init.
>
sudo apt-get install cloud-init
|
Now test and make sure you can reach the urls from this
server using wget. (use your own URLS
but here is my example)
>
wget http://192.168.0.80:8888/test/meta-data
> wget http://192.168.0.80:8888/test/user-data |
Looks like that is working just fine.
Tweak /etc/cloud/cloud.cfg
Here is where I am in some new territory, but I found this
gist that may be of some help https://github.com/number5/cloud-init/blob/master/doc/examples/cloud-config-datasources.txt
[2]
Looks like I can add a NoCloud section to the datasource
section and point it to my URL.
Let me edit it.
> sudo
vi /etc/cloud/cloud.cfg
|
Scrolling down a little I can see this datasource section
that is commented out.
Here is what I updated mine to.
datasource:
NoCloud:
# default seedfrom is
None
# if found, then it
should contain a url with:
# <url>/user-data and
<url>/meta-data
# seedfrom:
http://my.example.com/i-abcde
seedfrom:
http://192.168.0.80:8888/test
|
Save it and reboot.
> sudo
reboot now
|
OK that failed miserably… It took forever trying to get data
from EC2 urls that were not there then finally got to here and kinda got into a
wonky state that wiped my passwords so I could not get in.
SecondAttempt (Failed)
Now back to a very fresh install of Ubuntu 14.04.
First install cloud-init.
>
sudo apt-get install cloud-init
|
I found something interesting. If I look at /etc/cloud/cloud.cfg.d/90_dpkg.cfg
I can see that all the different datasources are
listed. Also I see a command I can run
to change that.
Let me try it
> sudo
dpkg-reconfigure cloud-init
|
Interesting I can set this here… But it looks like if I use
NoCloud option it won't use the URLS?
Maybe the URL option for NoCloud is a version 0.7.7 cloud-init thing and
14.04 is running 0.7.5?
But at any rate I am going do deselect all but NoCLoud and
hit OK.
Did /etc/cloud/cloud.cfg.d/90_dpkg.cfg change?
Yes it did!
I think if I ran this it would skip over checking EC2, etc
for meta-data/user-data and instead just use NoCloud…. But that the NoCloud
would only look into the directory /var/lib/cloud/seed
Let me edit it.
> sudo
vi /etc/cloud/cloud.cfg
|
Add in the following again.
datasource:
NoCloud:
# default seedfrom is
None
# if found, then it
should contain a url with:
# <url>/user-data and
<url>/meta-data
# seedfrom:
http://my.example.com/i-abcde
seedfrom: http://192.168.0.80:8888/test
|
> sudo
reboot now
|
Reboot, but I have a feeling it will not work.
Failed!
I found the issue !!
I think I found the issue!
I think the URL listed needs to end in with a '/'
datasource:
NoCloud:
# default seedfrom is
None
# if found, then it
should contain a url with:
# <url>/user-data and
<url>/meta-data
# seedfrom:
http://my.example.com/i-abcde
seedfrom:
http://192.168.0.80:8888/test/
|
Need to end the url with a '/'
Third Attempt (Total Success!!)
Now back to a very fresh install of Ubuntu 14.04.
First install cloud-init.
>
sudo apt-get install cloud-init
|
Edit /etc/cloud/cloud.cfg
> sudo
vi /etc/cloud/cloud.cfg
|
Add in the following again.
(With the ending in / )
datasource:
NoCloud:
# default seedfrom is
None
# if found, then it
should contain a url with:
# <url>/user-data and
<url>/meta-data
# seedfrom:
http://my.example.com/i-abcde
seedfrom:
http://192.168.0.80:8888/test/
|
Configure Cloud-init
> sudo
dpkg-reconfigure cloud-init
|
Select NoCloud
And select None: Failsafe
> sudo
reboot now
|
I should also be able to login as patman
> ssh patman@192.168.0.75
|
And tree and htop should be installed.
Working!
One tweak and it is working!
References
[1] Install cloud-init on Ubuntu and use locally… NoCloud
http://www.whiteboardcoder.com/2016/04/install-cloud-init-on-ubuntu-and-use.html
Accessed 04/2016
http://www.whiteboardcoder.com/2016/04/install-cloud-init-on-ubuntu-and-use.html
Accessed 04/2016
[2] cloud-config-datasources.txt
https://github.com/number5/cloud-init/blob/master/doc/examples/cloud-config-datasources.txt
Accessed 04/2016
https://github.com/number5/cloud-init/blob/master/doc/examples/cloud-config-datasources.txt
Accessed 04/2016
This comment has been removed by the author.
ReplyDeleteThank you very much!! It served me a lot, I was stuck with the metadata "problem", but with the nocloud-net config I was able to fix it. Regards from Perú! =)
ReplyDelete