GoRapid Blog

Stories from people who build @GoRapid

Blog categories
  • Devops

tags
  • aws
  • gcp
  • cloud
  • packer
  • terraform-packer

How to create custom machine image using packer

21 August:

Packer is an open-source VM image creation tool from Hashicorp. It helps you automate the process of Virtual machine image creation on the cloud and on-prem virtualized environments.

To put it simply, whatever manual steps you perform to create a Virtual machine image can be automated through a simple Packer config template. You declare the state of the VM image you need, and Packer will build it for you.

Official documentation can be found here

Installing Packer

Packer can be downloaded for most operating systems as well as installed using common package managers. To install the precompiled binary, you will need to download the appropriate package for your OS. On most popular Linux distributions, you can run the following commands to install Packer using your native package manager.

# Debian and Ubuntu
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install packer 
# CentOS
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install packer 

Afterwards, verify that Packer is working, for example, with the command below.

packer --version 
1.7.4 
Configure cloud configuration for packer

If you are using GCP then first download the service account key from your gcp account. Now it can be exported in the shell with the command below

export GOOGLE_APPLICATION_CREDENTIALS=`pwd`/service_key_in_json 

For AWS, first set the profile in the file ~/.aws/config as

[profile packer]
region = ap-south-1 

If you are not working on multiple projects then default profile will be used.

Now pass the aws credentials for the selected profile in the file ~/.aws/credentials as

[packer]
aws_access_key_id = AKIA8MHFS43NV5SMVNS
aws_secret_access_key = 2xifokP9b7glKprarcwuFRqPDMK79OkANYeFp2iu 
Configuring templates

Packer uses the Hashicorp configuration language (HCL) format for the configuration files to define the template you wish to build. You can find an example configuration on our GitHub repository at /packer-plugin-upcloud/examples.

To start, you might want to make a new directory for arranging your Packer configurations, for example, ~/packer.

mkdir ~/packer 

Next create a new template with your favourite editor, for example using the following command.

vim packer.json 

Then copy and paste the example template

{
  "variables": {
    "project_id": "",
    "machine_type": "",
    "source_image": "",
    "region": "",
    "zone": "",
    "image_name": "",
    "disk_size": "",
    "disk_type": "",
    "ssh_username": ""
  },

  "builders": [
    {
      "type": "googlecompute",
      "project_id": "{{user `project_id`}}",
      "machine_type": "{{user `machine_type`}}",
      "source_image": "{{user `source_image`}}",
      "region": "{{user `region`}}",
      "zone": "{{user `zone`}}",
      "image_description": "docker image installed on ubuntu",
      "image_name": "{{user `image_name`}}",
      "disk_size": "{{user `disk_size`}}",
      "disk_type": "{{user `disk_type`}}",
      "ssh_username": "{{user `ssh_username`}}"
    }
  ],

  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "sleep 5",
        "sudo apt install -y apt-transport-https ca-certificates curl software-properties-common",
        "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -",
        "sudo add-apt-repository 'deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable' ",
        "sudo apt update",
        "apt-cache policy docker-ce",
        "sudo apt install -y docker-ce",
        "sudo systemctl status docker",
        "sudo usermod -aG docker {{user `ssh_username`}}",
        "gcloud auth configure-docker {{user `region`}}-docker.pkg.dev"
      ]
    }
  ]

} 

The basic template is almost ready to deploy. This packer template can be used to create docker image. However, you should take a look at the parameters in the source and build segments.

Now you need to create variable file , for example use the following command.

vim variables.json 

Then copy and paste the example variables

{
  "project_id": "siminvest",
  "machine_type": "n1-standard-1",
  "source_image": "ubuntu-2004-focal-v20210325",
  "region": "asia-southeast2",
  "zone": "asia-southeast2-a",
  "image_name": "ubuntu-docker",
  "disk_size": "20",
  "disk_type": "pd-standard",
  "ssh_username": "ubuntu"
} 
Building templates using Packer

After creating the tempalte, first you need to validate the packer template by following command

packer validate -var-file=variables.json packer.json 

Packer will then check through your template configuration file syntax. If you get no warnings, everything is in order.

You are then ready to build your template. Use the command below to generate your custom template based on the configuration file.

packer build -var-file=variables.json packer.json 

If you are using aws then you need to pass aws profile, for example using the following command.

packer build --profile pelocal -var-file=variables.json packer.json 

If the image already exists and no rebuilding is required, it will have output something like the following:

==> googlecompute: Checking image does not exist...                                                                   
==> googlecompute: Image ubuntu-docker already exists.                                                                
==> googlecompute: Use the force flag to delete it prior to building.                                                 
       Build 'googlecompute' errored after 1 second 54 milliseconds: Image ubuntu-docker already exists.                     
       Use the force flag to delete it prior to building.                              
                                                                                
==> Wait completed after 1 second 54 milliseconds                               
                                                                                
==> Some builds didn't complete successfully and had errors:                    
==> googlecompute: Image ubuntu-docker already exists.                          
       Use the force flag to delete it prior to building.                              
                                                                                
==> Builds finished but no artifacts were created. 

If the image does not exist or requires rebuilding, the output will be something like following:

==> upcloud: Creating temporary SSH key ...
==> upcloud: Getting storage...
==> upcloud.test: Creating server based on storage "Ubuntu Server 20.04 LTS (Focal Fossa)"... 
...
==> Wait completed after 3 minutes 49 seconds

==> Builds finished. The artifacts of successful builds are:
--> upcloud.test: ubuntu-docker template created, UUID: 01f13bb4-ca38-4d7f-baa0-2bb14a18631d 

When the deployment process finishes, you should see an output similar to the example above.

Your new custom template is then available to deploy via your Cloud Control Panel or using any of our cloud management tools. For example, you can deploy the template to a new Cloud Server using Terraform and the following configuration.

resource "upcloud_server" "example" {
  hostname = "example"
  zone     = "nl-ams1"
  plan     = "2xCPU-4GB"
  
  template {
      storage = "ubuntu-docker"
      size    = 100
  }

  network_interface {
    type = "public"
  }
  
  connection {
    host        = self.network_interface[0].ip_address
    type        = "ssh"
    user        = "root"
    private_key = file("~/.ssh/id_rsa")
  }
} 
Conclusions

Congratulations, you should now have your own custom template visible at your Cloud's images tab. With the simple configuration process and the fast deployment, you can have a purpose build template ready in minutes.

Related Links:

packer documentation

How to create custom machine image using packer

21 August:

Packer is an open-source VM image creation tool from Hashicorp. It helps you automate the process of Virtual machine image creation on the cloud and on-prem virtualized environments.

To put it simply, whatever manual steps you perform to create a Virtual machine image can be automated through a simple Packer config template. You declare the state of the VM image you need, and Packer will build it for you.

Official documentation can be found here

Installing Packer

Packer can be downloaded for most operating systems as well as installed using common package managers. To install the precompiled binary, you will need to download the appropriate package for your OS. On most popular Linux distributions, you can run the following commands to install Packer using your native package manager.

# Debian and Ubuntu
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install packer 
# CentOS
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install packer 

Afterwards, verify that Packer is working, for example, with the command below.

packer --version 
1.7.4 
Configure cloud configuration for packer

If you are using GCP then first download the service account key from your gcp account. Now it can be exported in the shell with the command below

export GOOGLE_APPLICATION_CREDENTIALS=`pwd`/service_key_in_json 

For AWS, first set the profile in the file ~/.aws/config as

[profile packer]
region = ap-south-1 

If you are not working on multiple projects then default profile will be used.

Now pass the aws credentials for the selected profile in the file ~/.aws/credentials as

[packer]
aws_access_key_id = AKIA8MHFS43NV5SMVNS
aws_secret_access_key = 2xifokP9b7glKprarcwuFRqPDMK79OkANYeFp2iu 
Configuring templates

Packer uses the Hashicorp configuration language (HCL) format for the configuration files to define the template you wish to build. You can find an example configuration on our GitHub repository at /packer-plugin-upcloud/examples.

To start, you might want to make a new directory for arranging your Packer configurations, for example, ~/packer.

mkdir ~/packer 

Next create a new template with your favourite editor, for example using the following command.

vim packer.json 

Then copy and paste the example template

{
  "variables": {
    "project_id": "",
    "machine_type": "",
    "source_image": "",
    "region": "",
    "zone": "",
    "image_name": "",
    "disk_size": "",
    "disk_type": "",
    "ssh_username": ""
  },

  "builders": [
    {
      "type": "googlecompute",
      "project_id": "{{user `project_id`}}",
      "machine_type": "{{user `machine_type`}}",
      "source_image": "{{user `source_image`}}",
      "region": "{{user `region`}}",
      "zone": "{{user `zone`}}",
      "image_description": "docker image installed on ubuntu",
      "image_name": "{{user `image_name`}}",
      "disk_size": "{{user `disk_size`}}",
      "disk_type": "{{user `disk_type`}}",
      "ssh_username": "{{user `ssh_username`}}"
    }
  ],

  "provisioners": [
    {
      "type": "shell",
      "inline": [
        "sleep 5",
        "sudo apt install -y apt-transport-https ca-certificates curl software-properties-common",
        "curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -",
        "sudo add-apt-repository 'deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable' ",
        "sudo apt update",
        "apt-cache policy docker-ce",
        "sudo apt install -y docker-ce",
        "sudo systemctl status docker",
        "sudo usermod -aG docker {{user `ssh_username`}}",
        "gcloud auth configure-docker {{user `region`}}-docker.pkg.dev"
      ]
    }
  ]

} 

The basic template is almost ready to deploy. This packer template can be used to create docker image. However, you should take a look at the parameters in the source and build segments.

Now you need to create variable file , for example use the following command.

vim variables.json 

Then copy and paste the example variables

{
  "project_id": "siminvest",
  "machine_type": "n1-standard-1",
  "source_image": "ubuntu-2004-focal-v20210325",
  "region": "asia-southeast2",
  "zone": "asia-southeast2-a",
  "image_name": "ubuntu-docker",
  "disk_size": "20",
  "disk_type": "pd-standard",
  "ssh_username": "ubuntu"
} 
Building templates using Packer

After creating the tempalte, first you need to validate the packer template by following command

packer validate -var-file=variables.json packer.json 

Packer will then check through your template configuration file syntax. If you get no warnings, everything is in order.

You are then ready to build your template. Use the command below to generate your custom template based on the configuration file.

packer build -var-file=variables.json packer.json 

If you are using aws then you need to pass aws profile, for example using the following command.

packer build --profile pelocal -var-file=variables.json packer.json 

If the image already exists and no rebuilding is required, it will have output something like the following:

==> googlecompute: Checking image does not exist...                                                                   
==> googlecompute: Image ubuntu-docker already exists.                                                                
==> googlecompute: Use the force flag to delete it prior to building.                                                 
       Build 'googlecompute' errored after 1 second 54 milliseconds: Image ubuntu-docker already exists.                     
       Use the force flag to delete it prior to building.                              
                                                                                
==> Wait completed after 1 second 54 milliseconds                               
                                                                                
==> Some builds didn't complete successfully and had errors:                    
==> googlecompute: Image ubuntu-docker already exists.                          
       Use the force flag to delete it prior to building.                              
                                                                                
==> Builds finished but no artifacts were created. 

If the image does not exist or requires rebuilding, the output will be something like following:

==> upcloud: Creating temporary SSH key ...
==> upcloud: Getting storage...
==> upcloud.test: Creating server based on storage "Ubuntu Server 20.04 LTS (Focal Fossa)"... 
...
==> Wait completed after 3 minutes 49 seconds

==> Builds finished. The artifacts of successful builds are:
--> upcloud.test: ubuntu-docker template created, UUID: 01f13bb4-ca38-4d7f-baa0-2bb14a18631d 

When the deployment process finishes, you should see an output similar to the example above.

Your new custom template is then available to deploy via your Cloud Control Panel or using any of our cloud management tools. For example, you can deploy the template to a new Cloud Server using Terraform and the following configuration.

resource "upcloud_server" "example" {
  hostname = "example"
  zone     = "nl-ams1"
  plan     = "2xCPU-4GB"
  
  template {
      storage = "ubuntu-docker"
      size    = 100
  }

  network_interface {
    type = "public"
  }
  
  connection {
    host        = self.network_interface[0].ip_address
    type        = "ssh"
    user        = "root"
    private_key = file("~/.ssh/id_rsa")
  }
} 
Conclusions

Congratulations, you should now have your own custom template visible at your Cloud's images tab. With the simple configuration process and the fast deployment, you can have a purpose build template ready in minutes.

Related Links:

packer documentation