Deploy An Auto-provisioned VPS

How to Deploy an Auto-provisioned VPS on Rapid.Space

This HowTo explains how to use packer and ansible to generate easily multiple VM images to ease the installation of many VMs.

Packer

When you want to deploy many VMs and you don't want to lose time installing each VM manually from the ISO installation image, you can use Packer to generate an custom image before hand. Then, you will be able to boot directly on this image instead of the regular ISO installation image. This can save you a lot of time.

Packer needs a template to build the image. This template is in JSON format and details everything you want to build inside your VM image. At the core of this template, there will be the ISO installation image you want to build, and then you can specify many things to do the installation automatically with all the parameters you chose. The documentation for packer template can be found here: https://www.packer.io/docs/templates/.

An example of template file


{
  "variables": {
    "user": "slapos",
    "password": "slapos",
    "domain": "",
    "disk_size": "100",
    "name": "image",
    "custom_script": "scripts/empty.sh"
  },

  "builders":
  [
    {
      "name": "debian10-{{ user `disk_size`}}G-{{ user `name`}}",

      "type": "qemu",
      "format": "qcow2",
      "accelerator": "kvm",
      "disk_size": "{{ user `disk_size`}}000",

      "iso_url": "https://cdimage.debian.org/debian-cd/current/amd64/iso-cd/debian-10.2.0-amd64-netinst.iso",
      "iso_checksum": "36de671429939e90f2a31ce3fbed0aaf",
      "iso_checksum_type": "md5",

      "http_directory": "http",

      "ssh_username": "{{user `user`}}",
      "ssh_password": "{{user `password`}}",
      "ssh_wait_timeout": "1800s",
      "shutdown_command": "echo '{{user `password`}}'|sudo -S shutdown -h now",

      "headless": true,
      "boot_wait": "2s",
      "boot_command": [
        "",
        "auto preseed/url=http://{{ .HTTPIP }}:{{ .HTTPPort }}/preseed-debian10.cfg ",
        "debian-installer=en_US.UTF-8 locale=en_US keymap=fr ",
        "netcfg/get_hostname={{ .Name }} ",
        "netcfg/get_domain={{ user `domain`}} ",

        "fb=false debconf/frontend=noninteractive ",

        "passwd/user-fullname={{user `user`}} ",
        "passwd/user-password={{user `password`}} ",
        "passwd/user-password-again={{user `password`}} ",
        "passwd/username={{user `user`}} ",

        ""
      ]
    }
  ],

  "provisioners": [
    {
      "type": "shell",
      "execute_command": "echo '{{user `password`}}' | {{.Vars}} sudo -E -S bash '{{.Path}}'",
      "scripts": [
        "scripts/update.sh",
        "scripts/packages.sh",
        "scripts/network-debian.sh",
        "scripts/cleanup.sh",
        "{{ user `custom_script` }}"
      ]
    }
  ]
}

Let's look at an example of template file (this file is our debian10.json template).

The "builder" section is the most important and the only one mandatory. There are also 2 other sections:

  • "variables" which defines variables we use in other sections. It can be useful to do some minor variations of your images
  • "provisionners" which is the step executed after the installation itself and let you execute some command inside the newly installed system via ssh. This step will let us customize everything we want inside the image (user, packages, etc.)

Please note that the file preseed.cfg needs to be located inside a directory named http. This http directory needs to be alongside the template. For example, look at our http directory at https://lab.nexedi.com/nexedi/slapos.package/tree/master/packer/http. For more information about the preseed file see: https://wiki.debian.org/fr/DebianInstaller/Preseed

When you wrote your template (like the one above), you can make sure it syntaxically correct using the command packer validate debian10.json

Once the file is validated, you can use the command packer build debian10.json to build the image.

Please note that packer supports any operating systems. You just need to look how to automatically install the OS of your choice and then configure a template for it. Of course, there are a lot of available template examples (see "Templates" chapter in https://www.packer.io/community-tools.html). 

Automate the building of images with Ansible

If you need to build many different images, you can use Ansible to generate them all instead of generating them one by one. For example, you may want to build images for several distributions (Ubuntu, CentOS, Debian) or with several disk sizes (50G, 100G, 200G, ...).

Building each image manually with the command "packer build" can be tedious. You can simply create an Ansible playbook to generate them all.

An example of Ansible task

- shell: PATH=$PATH:/opt/packer/ packer build debian10.json >> log/debian10.log
args:
creates: output-debian10
ignore_errors: True

Here is an example of Ansible task to create an image with packer. 

As you can see this task will simply call packer and save the output image in output-debian10 directory.

 

An example of Ansible task

- shell: gzip output-debian10/packer-debian10
args:
creates: output-debian10/packer-debian10.gz
ignore_errors: True

Then if you want to compress the image (since RapidSpace VM service can boot from a compressed image) to save space on your disk. 

And you can also imagine to create a task to upload this image to a web server to be used by RapidSpace VM.

If you want to see a real example of playbook we are using at nexedi to generate our images, you can have a look at https://lab.nexedi.com/nexedi/slapos.package/blob/master/packer/build-vm-bootstrap.yml.

Run Playbook

If your playbook is named build.yml, you can run it with this simple command:

ansible-playbook build.yml -i localhost

 

Thank You

  • Nexedi SA
  • 147 Rue du Ballon
  • 59110 La Madeleine
  • France
  • +33629024425

For more information, please contact Jean-Paul, CEO of Nexedi (+33 629 02 44 25).