Building images with Packer, Google Build, and Google Build Triggers

André Passos
5 min readFeb 19, 2021

Tuning and creating a specific image is a typical problem that quite often happens in development environments. For instance, in our team we got the request of creating images with specific configurations added by our users. A typical example is that our software developers pick a certain image and install a set of applications. They don’t want to keep doing this for each new virtual machine. Instead, they would like to create a new image with all required tools installed and then use that image. This will make them spare some time.

Packer

In order to do this we use Packer. Packer is a free and open source tool for creating golden images for multiple platforms from a single source configuration. Packer has the concept of builders. Builders are responsive for creating machines and generating images from then to various platforms. In our case we will use the build for Google Cloud.

Packer allows you to use two types of templates (Hashicorp Configuration Language or JSON). In this case we will use JSON. The language in packer is quite straightforward. We create some variables that are going to be used to configure the builder. The builder type is “googlecompute”. This means we will be build a Google Cloud Compute Image. It’s quite easy to understand what is happening by just looking at the file. One point that worth mentioning is that packer will use ssh to connect to the machine created from that image and do the required customizations. In our case we need to provide a username and a password. Also, for security reasons we don’t want to expose an external IP. For that we set the attribute “omit_external_ip” to true. So how do we connect to the machine? For that we use IAP. IAP stands for Indentity-Aware Proxy, IAP lets you establish a central authorization layer for applications accessed by HTTPS, so you can use an application-level access control model instead of relying on network-level firewalls. For using IAP you need to provide an account file that has permissions to connect to the VM. That’s what we do with the “account_file” attribute. We provide a service account that has the necessary rights.

After setting up the builder now it is time to specify what you would like to do with the VM to setup the new image. In our case we would like to give full flexibility for our users to do whatever they want. So we came up with the strategy of allowing them to pass a bash script that is stored in a GCP Bucket and then execute that script. So this is how one of our provisioners looks like.

This will be executed on the VM with the steps defined in the inline. The first step on the inline downloads a script from a bucket and the last one just executes the script.

With this approach we keep our image creation process quite generic and the users have full flexibility to tune the image the way that they want. Now, how to execute this?

Google Cloud Build

Cloud Build is a service that executes your builds on Google Cloud Platform’s infrastructure. Cloud Build can import source code from a variety of repositories or cloud storage spaces, execute a build to your specifications, and produce artifacts such as Docker containers or Java archives. In our case we will use the Google Cloud Build to produce images.

The pipeline is quite simple. It has some substitution variables. These variables are the parameters that we need to pass to the pipeline. Then it just generates some files from some secrets that we store in our repo and starts using packer to build the image. If you remember from the previous step, our packer script was reading some environment variables. These variables are the ones that we are setting on the pipeline. Now the final step, how to trigger this without changing the code?

Google Cloud Build Trigger

A Cloud Build trigger automatically starts a build whenever you make any changes to your source code. You can configure the trigger to build your code on any changes to the source repository or only changes that match certain criteria. In our case we decided to use a manual trigger. So it means the user can specify when to run the pipeline. The first step you need to do is to create a trigger. There is good documentation on how to do it here: https://cloud.google.com/build/docs/automating-builds/create-manage-triggers#gcloud

However we couldn’t find any documentation on how to trigger a pipeline using triggers with substitution variables. After putting the question to google we figure out that gcloud doesn’t support this feature. As a work around you can use curl to achieve the same thing. To do that you can do it this way:

In our case the trigger name is called custom-image-creation and in this case we only pass two substitution variables (BASELINE and POSTFIX). To follow the status of the request you get the ID returned by the curl command and do a gcloud builds describe ID

Conclusion

Using this approach you are able to create images without major changes in your pipeline and in your repository. Users can trigger the changes using the cloud build trigger. A script using bash allows them to customize the image the way they want without worrying with the rest.

--

--