100 Days of DevOps — Day 27- Introduction to Packer

What is Packer?

Packer Template

Installing Packer on 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
packer
Usage: packer [--version] [--help] <command> [<args>]
Available commands are:
build build image(s) from template
console creates a console for testing variable interpolation
fix fixes templates from old versions of packer
fmt Rewrites HCL2 config files to canonical format
hcl2_upgrade transform a JSON template into an HCL2 configuration
init Install missing plugins or upgrade plugins
inspect see components of a template
validate check that a template is valid
version Prints the Packer version
{
"builders": [
{
"type": "amazon-ebs",
"region": "us-west-2",
"source_ami": "ami-0721c9af7b9b75114",
"instance_type": "t2.micro",
"ssh_username": "ec2-user",
"ami_name": "amazon-linux-packer-ami-1.0"
}
]
}
* type: Each Builder has a mandatory type field, as we are building this image on AWS we are going to use amazon-ebs type filed* region: Where we want to build this image, as AMI ID differ based on region
* source_ami: This is image going to be launched on AWS and our image is based on this(In this example I am using AWS AMI)
* instance_type: I am using t2.micro as it comes under AWS free tier
* ssh_username: We need to tell packer which ssh username to utilize, as we are using AWS AMI, username is ec2-user
* ami_name: Now we need to tell packer AMI it need to create
export AWS_ACCESS_KEY_ID=" "
export AWS_SECRET_ACCESS_KEY=" "
$ packer validate firsttemplate.packer
packer build -debug firsttemplate.packer
Debug mode enabled. Builds will not be parallelized.
amazon-ebs: output will be in this color.
==> amazon-ebs: Prevalidating any provided VPC information
==> amazon-ebs: Prevalidating AMI Name: amazon-linux-packer-ami-1.0
==> amazon-ebs: Pausing after run of step 'StepPreValidate'. Press enter to continue.
amazon-ebs:
Found Image ID: ami-0721c9af7b9b75114
==> amazon-ebs: Pausing after run of step 'StepSourceAMIInfo'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepNetworkInfo'. Press enter to continue.
==> amazon-ebs:
Creating temporary keypair: packer_60f60c69-0593-4a1b-ae16-04a19bca1517
amazon-ebs: Saving key for debug purposes: ec2_amazon-ebs.pem
==> amazon-ebs: Pausing after run of step 'StepKeyPair'. Press enter to continue.
==> amazon-ebs: Creating temporary security group for this instance: packer_60f60c80-6ecf-4d8c-56d1-d72222bddf4f
==> amazon-ebs: Authorizing access to port 22 from [0.0.0.0/0] in the temporary security groups...
==> amazon-ebs: Pausing after run of step 'StepSecurityGroup'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepIamInstanceProfile'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepCleanupVolumes'. Press enter to continue.
==> amazon-ebs: Launching a source AWS instance...
==> amazon-ebs: Adding tags to source instance
amazon-ebs: Adding tag: "Name": "Packer Builder"
amazon-ebs: Instance ID: i-0d1a1767d583be063
==> amazon-ebs: Waiting for instance (i-0d1a1767d583be063) to become ready...
amazon-ebs: Public DNS: ec2-34-210-120-197.us-west-2.compute.amazonaws.com
amazon-ebs: Public IP: 34.210.120.197
amazon-ebs: Private IP: 172.31.22.36
==> amazon-ebs: Pausing after run of step 'StepRunSourceInstance'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepGetPassword'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepCreateSSMTunnel'. Press enter to continue.
==> amazon-ebs: Using SSH communicator to connect: 34.210.120.197
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Pausing after run of step 'StepConnect'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepSetGeneratedData'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepProvision'. Press enter to continue.
==>
amazon-ebs: Pausing after run of step 'StepCleanupTempKeys'. Press enter to continue.
==> amazon-ebs: Stopping the source instance...
amazon-ebs: Stopping instance
==> amazon-ebs: Waiting for the instance to stop...
==> amazon-ebs: Pausing after run of step 'StepStopEBSBackedInstance'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepModifyEBSBackedInstance'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepDeregisterAMI'. Press enter to continue.
==> amazon-ebs:
Creating AMI amazon-linux-packer-ami-1.0 from instance i-0d1a1767d583be063
amazon-ebs: AMI: ami-0e4c3651dc6e441df
==> amazon-ebs: Waiting for AMI to become ready...
==> amazon-ebs: Pausing after run of step 'stepCreateAMI'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepAMIRegionCopy'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepModifyAMIAttributes'. Press enter to continue.
==> amazon-ebs: Pausing after run of step 'StepCreateTags'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepCreateTags'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepModifyAMIAttributes'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepAMIRegionCopy'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'stepCreateAMI'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepDeregisterAMI'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepModifyEBSBackedInstance'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepStopEBSBackedInstance'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepCleanupTempKeys'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepProvision'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepSetGeneratedData'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepConnect'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepCreateSSMTunnel'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepGetPassword'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepRunSourceInstance'. Press enter to continue.
==> amazon-ebs:
Terminating the source AWS instance...
==> amazon-ebs: Pausing before cleanup of step 'StepCleanupVolumes'. Press enter to continue.
==> amazon-ebs: Cleaning up any extra volumes...
==> amazon-ebs: No volumes to clean up, skipping
==> amazon-ebs: Pausing before cleanup of step 'StepIamInstanceProfile'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepSecurityGroup'. Press enter to continue.
==> amazon-ebs:
Deleting temporary security group...
==> amazon-ebs: Pausing before cleanup of step 'StepKeyPair'. Press enter to continue.
==> amazon-ebs:
Deleting temporary keypair...
==> amazon-ebs: Pausing before cleanup of step 'StepNetworkInfo'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepSourceAMIInfo'. Press enter to continue.
==> amazon-ebs: Pausing before cleanup of step 'StepPreValidate'. Press enter to continue.
Build 'amazon-ebs' finished after 28 minutes 27 seconds.
==> Builds finished. The artifacts of successful builds are:
-->
amazon-ebs: AMIs were created:
us-west-2: ami-0e4c3651dc6e441df
1: Pre-validating the existing image
2: Creating temporary Key Pair
3: Add port 22 in the security group
4: Creating a temporary instance
5: Building an AMI
6: Cleaning up all resources

Packer Variables

{
"variables": {
"aws_region": "us-west-2"
},
"builders": [{
"type": "amazon-ebs",
"region": "{{user `aws_region`}}"
}],
{
"variables": {
"aws_region": "{{env `AWS_REGION`}}"
}
packer build -var 'aws_region=us-west-2' <packer-file>
* It's specific to Amazon and it remove unwanted characters
* eg: {{ "v:01" | clean_ami_name }} in this case : is unwanted character
* Output: v-01
* Setting up unix timestamp
"ami_name": "centos-packer-example-1.0-{{isotime | clean_ami_name}}"

File Provisioner

* Here type is file
* We need to specify from where we need to copy the file(I created a file called mytestfile)
* Destination where we want to copy the file

Script Provisioners

# Linux* Local Shell
* Remote Shell(Run the script on the machine where packer is building)
# Windows* Powershell(Similar to Remote Shell)
* Windows Shell(batch script)
* Windows Restart
* Here we are using script provisioner
* Then script you are going to execute
#!/bin/bash -e
sudo cp /tmp/mytestfile /etc
NOTE: -e in the shebang, it ensures that script executes with the error code so that packer ensure that script exit with proper exit code, if you don't want to use this you need to use inline provisioner

Output

==> amazon-ebs: Connected to SSH!==> amazon-ebs: Uploading mytestfile => /tmp/mytestfile1 items:  18 B / 18 B [=================================================================================================================================================================================] 0s==> amazon-ebs: Provisioning with shell script: script.sh

Building Packer Image with Provisioners(Ansible)

# ansible.sh
#!/bin/bash -e
yum -y install epel-release
yum -y install ansible
# Ansible Playbook* There we are trying to install apache and make sure its up after reboot# Packer Template
* Is similar to other provisioner and it just try to execute ansible playbook
# Shell Script
* This is to make sure ansible is locally installed on that image

Packer with Docker

* This time builder type is docker
* image: This is going to pull centos latest image from dockerhub
* export_path: Finally its going to create tar file
$ cat mytest.tar |docker import - mydockerimage:latestsha256:3abe8a3fc0a9bfc004f62dae25bc7a7b45d1d55594f5befc9689d6cf51010467
$ docker imagesREPOSITORY                                                                              TAG                 IMAGE ID            CREATED             SIZEmydockerimage                                                                           latest              3abe8a3fc0a9        4 seconds ago       202MB
$ docker run -d -it mydockerimage:latest /bin/bashe85b1c9cedfc2137611165eddbe848fc1d557cee44c7b28bc069c30f062cf7cd$ docker psCONTAINER ID        IMAGE                  COMMAND             CREATED             STATUS              PORTS               NAMESe85b1c9cedfc        mydockerimage:latest   "/bin/bash"         8 seconds ago       Up 7 seconds                            romantic_swirles$ docker exec -it e85b1c9cedfc bash[root@e85b1c9cedfc /]#

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Prashant Lakhera

Prashant Lakhera

4.91K Followers

AWS Community Builder, Ex-Redhat, Author, Blogger, YouTuber, RHCA, RHCDS, RHCE, Docker Certified,4XAWS, CCNA, MCP, Certified Jenkins, Terraform Certified, 1XGCP