<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Alex Tomkins - cloud-init</title>
    <link>https://www.alextomkins.com/tag/cloud-init/</link>
    <atom:link href="https://www.alextomkins.com/tag/cloud-init/feed.xml" rel="self" type="application/rss+xml" />
    <description>Posts tagged with cloud-init</description>
    <language>en</language>
    
    
    
    
    
    
    
    <item>
      <title>Testing cloud-init with Vagrant</title>
      <link>https://www.alextomkins.com/2016/09/testing-cloud-init-with-vagrant/</link>
      <guid>https://www.alextomkins.com/2016/09/testing-cloud-init-with-vagrant/</guid>
      <pubDate>Sun, 18 Sep 2016 21:22:00 +0000</pubDate>
      <description><![CDATA[<p><a href="https://cloudinit.readthedocs.io/">cloud-init</a> is a standard tool in most cloud computing
environments as it's an easy way to provide configuration for provisioning server instances. You
provide a YAML config file and it'll use the data to configure the server as needed.</p>
<p>Testing cloud-init in a public can be a bit problematic and time consuming, having to relaunch
servers to test the config from a pristine state. It's possible to reset the cloud-init config on
the server - but if you want to test that your config file works as expected, it's best to test
from a freshly booted server.</p>
<p>Thanks to the <a href="https://atlas.hashicorp.com/ubuntu">Ubuntu Vagrant boxes</a> which are built with
cloud-init support, we can test our cloud-init configuration with
<a href="https://www.vagrantup.com/">Vagrant</a> easily. We'll be using the Ubuntu 16.04 Xenial Xerus box to
test with - as it's the latest Ubuntu LTS release.</p>
<h1>Creating a cloud-init ISO</h1>
<p>cloud-init can support multiple data sources for configuration, one of them being an CD image.
We'll be using this as an easy way to provide our config files. To generate this we can use
genisoimage/mkisofs.</p>
<p>To install on Debian/Ubuntu:</p>
<pre><code>$ sudo apt-get install genisoimage</code></pre>
<p>To install on OS X Macports:</p>
<pre><code>$ sudo port install cdrtools</code></pre>
<p>Next up we'll need our <code>user-data</code> file, the main cloud-init config file:</p>
<pre><code>#cloud-config
chpasswd:
  list: |
    ubuntu:RANDOM
  expire: False

manage_etc_hosts: localhost

ssh_authorized_keys:
  - ssh-rsa
    AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ==
    vagrant insecure public key</code></pre>
<p>This can be customised with the configuration you need to test, however in this example we're
adding the default Vagrant insecure public SSH key. Don't worry - Vagrant will replace it shortly
after rebooting.</p>
<p>Now we need a <code>meta-data</code> file:</p>
<pre><code>instance-id: iid-0123456789abcdef
local-hostname: ubuntu-xenial</code></pre>
<p>This is just the bare minimum - cloud providers usually provide more data. If you depend on other
data provided as metadata then just add it as needed.</p>
<p>To create the ISO image we'll create a <code>Makefile</code>:</p>
<pre><code>nocloud.iso: meta-data user-data
    mkisofs \
        -joliet -rock \
        -volid "cidata" \
        -output nocloud.iso meta-data user-data</code></pre>
<p>Don't forget - a Makefile must be indented with tabs and not spaces!</p>
<p>Now to create the ISO file, all we have to do is run:</p>
<pre><code>$ make</code></pre>
<p>And you'll have a brand new <code>nocloud.iso</code> ISO image.</p>
<h1>cloud-init Vagrantfile</h1>
<p>Now we can create a Vagrantfile to test our newly generated ISO image:</p>
<pre><code>$ vagrant init ubuntu/xenial64</code></pre>
<p>This will create a sample Vagrantfile, which we'll need to edit:</p>
<pre><code># -*- mode: ruby -*-
# vi: set ft=ruby :

CLOUD_CONFIG_PATH = File.join(File.dirname(__FILE__), "nocloud.iso")

Vagrant.require_version ">= 1.8.0"

Vagrant.configure(2) do |config|
    config.vm.box = "ubuntu/xenial64"

    # Disable SSH password for 16.04 - we'll add the insecure Vagrant key
    # (don't worry, it's just an example and gets replaced anyway)
    config.ssh.password = nil

    # Disable shared folders
    config.vm.synced_folder ".", "/vagrant", disabled: true

    # Tweak virtualbox
    config.vm.provider :virtualbox do |vb|
        # Attach nocloud.iso to the virtual machine
        vb.customize [
            "storageattach", :id,
            "--storagectl", "SCSI",
            "--port", "1",
            "--type", "dvddrive",
            "--medium", CLOUD_CONFIG_PATH
        ]

        # Speed up machine startup by using linked clones
        vb.linked_clone = true
    end
end</code></pre>
<p>This creates a new virtual machine based on the xenial64 Vagrant box, but replaces the CD/DVD port
with our <code>nocloud.iso</code> file.</p>
<p>All you have to do at this point is:</p>
<pre><code>$ vagrant up</code></pre>
<p>Vagrant will start up a virtual machine, customised with your cloud-init config file. If anything
goes wrong you can easily <code>vagrant destroy</code> the machine and try again - without the cost of
starting a new server in a public cloud.</p>
<h1>Using your own SSH keys</h1>
<p>If you're developing a user-data file and want to use your own SSH keys instead of Vagrant
replacing it on every boot, edit the Vagrantfile and add these lines:</p>
<pre><code>config.ssh.private_key_path = File.expand_path("~/.ssh/id_rsa")
config.ssh.insert_key = false</code></pre>
<p>Don't forget to edit the user-data file and add your own public key to <code>ssh_authorized_keys</code>, and
run <code>make</code> to generate a new ISO image.</p>
<h1>Conclusion</h1>
<p>Testing cloud-init with Vagrant is quick and easy once you've got everything setup.</p>
<p>Source code for this is available in the
<a href="https://github.com/tomkins/cloud-init-vagrant">cloud-init-vagrant</a> repo on GitHub.</p>
]]></description>
    </item>
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  </channel>
</rss>
