loading...

Packer: Building images on Google Cloud

mcrmonkey profile image ant Kenworthy ・4 min read

Installing the software we need to run our website or tools, can take some time to complete. This isn't ideal when our deployments are time sensitive, like when we need to scale up the web server pool to handle that sudden interest in your latest line of fancy socks.

We can solve this issue by pre-installing the software we need and setting the configuration options, which we can then turn in to an image we can deploy over and over again.

To make this entire process quicker, repeatable and something we can easily template - We'll use packer

What is Packer?

Packer is a Hashicorp tool that can be used to ease the creation of system images on cloud platforms or for other local tools like Vagrant ( another Hashicorp tool), Docker and VirtualBox.

Where can I get it ?

You can download the HashiCorp Packer tool from the download page on the packer website

There's also a handy guide on the hashicorp learning portal for how to install it on your operating system

How can I use it with the Google Cloud Platform?

You'll need to create a "builder" configuration in your packer file.
Here's a basic example:

{
  "builders": [
    {
      "type": "googlecompute",
      "project_id": "my project",
      "zone": "us-central1-a",
      "source_image_family": "debian-10",
      "ssh_username": "packer",
      "image_name": "packer-{{timestamp}}",
      "image_family": "socks-web"
    }
  ]
}

The options we have set above do the following things:

type
is the type of builder we're using. Here its googlecompute because we're talking to GCP

project_id
is the project where the final image will be stored

zone
Will be the zone we build our image in

source_image_family
This is the group of images where our base image will be taken from

ssh_username
The ssh username we'll use to talk to the instance that will create our image

image_name
The name of the image we will create.
The image name needs to be unique within our project so we're using the packer variable timestamp to do that.

image_family
The name of our image family. This is optional but is useful later on.

What is this image_family thing ?

Images can be stored in groups referred to as image families. When building instances we can ask GCP to get our image from our family which will return the latest image that was added to it.

If something is found to be wrong with a new image we can tag it as deprecated and the family will offer up a previous version next time we deploy an instance.

More info on image families can be found in the GCP documentation

How do I install that web server in my image?

You'll need to add a provisioner or two, to your packer config file.

Provisioner's are usually shell scripts or file uploads but could be a puppet, ansible, salt or chef operation.

Here's a complete example of our packer file including our new provisioners:

{
  "builders": [
    {
      "type": "googlecompute",
      "project_id": "my project",
      "zone": "us-central1-a",
      "source_image_family": "debian-10",
      "ssh_username": "packer",
      "image_name": "packer-{{timestamp}}",
      "image_family": "socks-web"
    }
  ],
  "provisioners": [                                                           
      {                                                                         
      "type": "file",                                                           
      "source": "./index.html",                                           
      "destination": "/tmp/index.html"                                            
      },
      {                                                                         
        "type": "shell",                                                        
        "inline": [                                                             
            "sudo apt-get update -qq",
            "sudo apt-get upgrade -qq",                                     
            "sudo apt-get install -qq apache2",
            "sudo cp /tmp/index.html /var/www/html/index.html",
         ]                                                                      
    }]
}

Here we copy our index.html file to /tmp, Update the cache for apt, perform a system upgrade to make sure we have all the updates installed then install apache and finally copy our index page in to place.

How do I build that image ?

You can now run the following command from the directory where you've saved the packer file:

packer build example.json

Packer will now go away and build that image for you and will store the resulting image as packer-xxxxxxxxx ( where xxxxxxxxx is a timestamped value ) The resulting image will be linked to the image family socks-web which you will then be able to reference in your terraform template for your project.

🎉 Tada!

Are there other things to know ?

Yes, there are a couple of things:

Networking

The example above assumes the project you are using contains a default networking setup with subnetworks available in your chosen zone. If these things aren't available the build process will fail and you'll need to add a network OR subnetwork option to the builder config which lines up with your chosen zone.

It also assumes that the default firewall rules are in place so packer can ssh to the instance it creates.
If you don't have the needed firewall rules to allow access your build process will time out while waiting to connect.

machine_type has been omitted from the example

It will default to n1-standard-1 but you may need to increase its size depending on what you're doing. A larger machine type will help it run faster.

Cost

There is a cost for storing your images.
At time of writing its about $0.050 for US and EU multi region storage but it can be as high as $0.075 is specific regions.

There will also be a cost for building the image.
This will vary based on the image size you use and where you choose to build it.
At time of writing the cost of the the given example should be in the region of $0.04749975 Per hour

Check the pricing page for more info.

To quote the pricing pages:

If you pay in a currency other than USD, the prices listed in your currency on Cloud Platform SKUs apply.

Make sure you check the cost before you run up a big bill

Cleaning up

If you don't want that image you've just created you can head over to images in the compute section of the console and delete the image you no longer want.

Note: You cannot delete public images from your project - They are free anyway 😃

Discussion

pic
Editor guide