Earlier this year, we wrote an article showcasing how to create custom Compute instance templates on Exoscale using Packer.

The process described was relying on the exoscale-import post-processor to register a QEMU builder disk image file uploaded to a temporary Object Storage bucket.

Although this method is quite straightforward, it requires you to run a QEMU hypervisor locally on your computer to build the disk image, which is something you don’t necessarily can or want to do. Today, we’re introducing an even simpler alternative way to use Packer to create Exoscale custom templates, leveraging the recently announced Compute instance snapshot export functionality.

The new Exoscale Packer builder spins a temporary Compute instance, then following your configuration will then connect to it and perform the specified provisioning actions locally before stopping the instance and take a snapshot of its storage volume, eventually exporting the snapshot and register it as a new template. All the operations happen remotely on Exoscale – no need for any local tool other than Packer.

The new Exoscale Packer plugin

Use Case: Daily Refresh of a Base Compute template

To illustrate how to use the new Exoscale Packer plugin, let’s imagine a scenario where you want to periodically refresh a base Exoscale Compute template that your company uses for all Compute instance deployments.

This template should be generic enough to avoid pre-installing unnecessary components such as a web/database server. However it should provide core utilities such as Ansible to be able to enroll in your infrastructure as soon as a Compute instance using it is started.

Most importantly, the base layer software must be up-to-date with regards to security fixes, which is why even though changes to the template configuration itself rarely occur, the base OS should be refreshed regularly to benefit from software updates.

In this scenario, we have the base template Packer configuration versioned in a Git repository hosted on GitHub, and we’ll set up a GitHub Actions workflow scheduled to periodically rebuild our custom template on Exoscale.

To keep the article simple, the Packer template configuration is reduced to a minimum: we’re building upon a Ubuntu Linux 20.04 LTS (Focal Fossa), upgrading the base OS packages and installing Ansible.

variable "api_key" { default = "" }
variable "api_secret" { default = "" }

source "exoscale" "base" {
  api_key = var.api_key
  api_secret = var.api_secret
  instance_template = "Linux Ubuntu 20.04 LTS 64-bit"
  instance_disk_size = 10
  template_zone = "ch-gva-2"
  template_name = "base"
  template_username = "ubuntu"
  ssh_username = "ubuntu"
}

build {
  sources = ["source.exoscale.base"]
  provisioner "shell" {
    environment_vars = ["DEBIAN_FRONTEND=noninteractive"]
    inline = [
      "sudo apt-get update && sudo apt-get upgrade -y",
      "sudo apt-get install --no-install-recommends -y ansible",
    ]
  }
}

The next step is to set up the GitHub Actions workflow that will periodically rebuild the Compute template:

name: Build
on:
  push:
    branches: [master]
  schedule:
  - cron: '0 6 * * *'
jobs:
  build-base:
    runs-on: ubuntu-latest
    container:
      image: hashicorp/packer:light
      env:
        EXOSCALE_API_KEY: ${{ secrets.EXOSCALE_API_KEY }}
        EXOSCALE_API_SECRET: ${{ secrets.EXOSCALE_API_SECRET }}
    steps:
    - uses: actions/checkout@v2
    - name: Build base template
      run: |
        mkdir -p $HOME/.packer.d/plugins && wget -qO - https://github.com/exoscale/packer-builder-exoscale/releases/download/v0.1.0/packer-builder-exoscale_0.1.0_linux_amd64.tar.gz | tar -xvzf - -C $HOME/.packer.d/plugins packer-builder-exoscale
        packer build \
          -var api_key=$EXOSCALE_API_KEY \
          -var api_secret=$EXOSCALE_API_SECRET \
          base.pkr.hcl

Configured this way, a build job will be triggered every day at 6am UTC, and upon Git push to the master branch.

If we look at our custom templates, we can see the results of several GitHub Actions workflow runs over a few days:

$ exo vm template list --mine
┼──────────────────────────────────────┼──────┼──────────────────────────┼──────────┼───────────┼
│                  ID                  │ NAME │      CREATION DATE       │   ZONE   │ DISK SIZE │
┼──────────────────────────────────────┼──────┼──────────────────────────┼──────────┼───────────┼
│ 5571f0cc-d9a0-46e1-ae9d-dc19d2e57031 │ base │ 2020-08-12T08:18:47+0200 │ ch-gva-2 │ 10 GiB    │
│ 99ec04ce-84b8-40e9-8226-7e2d6aca49a8 │ base │ 2020-08-11T08:17:21+0200 │ ch-gva-2 │ 10 GiB    │
│ edaabe1e-c02c-4501-840d-a2032d3e44cb │ base │ 2020-08-10T08:17:50+0200 │ ch-gva-2 │ 10 GiB    │
┼──────────────────────────────────────┼──────┼──────────────────────────┼──────────┼───────────┼

Pack for the Road

For most Exoscale users, our new Packer builder plugin covers all the bases that they might have with regards to creating custom templates. For the edges cases, the exoscale-import can also be leveraged by taking care of the template registration but letting the users complete control on the disk image building process. Happy packing!