Packer
Control artifacts with channels
Just like software teams version and tag applications to track changes, you should version and tag parent artifacts. HCP Packer channels let you to label artifact versions to describe the quality and stability of the build. This gives you control over the artifact delivery, helping other teams dynamically query artifacts for their requirements. This workflow helps your infrastructure stay up to date with minimal manual effort and is less error-prone than manually referencing AMIs or using AWS tags.
In this tutorial, you will create a new channel in the HCP Packer registry. Next, you will query the channel and its build artifact metadata, then use the artifact to deploy an EC2 instance with Terraform. Next, you will update the channel to point to another version, and query the updated channel.
Prerequisites
To complete this tutorial, you must have completed the previous tutorials. In the previous tutorials, you:
- Created a service principal with Contributor access to HCP.
- Set your client ID and secret as environment variables.
- Configured your AWS credentials as environment variables.
- Built an artifact and push its metadata to HCP Packer.
In addition, you will need:
- Terraform 1.1.7+ installed locally.
Create another artifact version
In ubuntu-focal.pkr.hcl
, update the version number to 1.0.1
.
Tip
If you do not already have this file, complete the previous tutorial.
ubuntu-focal.pkr.hcl
packer {
## ...
}
variable "version" {
type = string
default = "1.0.1"
}
The amazon-ebs
source blocks use the version
variable to generate the AMI name. Since you changed the version number, Packer will generate a new AMI in each region.
ubuntu-focal.pkr.hcl
source "amazon-ebs" "basic-example-east" {
## ..
ami_name = "packer_AWS_{{timestamp}}_v${var.version}"
}
source "amazon-ebs" "basic-example-west" {
## ..
ami_name = "packer_AWS_{{timestamp}}_v${var.version}"
}
In your terminal, format the Packer template.
$ packer fmt ubuntu-focal.pkr.hcl
Stage your template file.
$ git add ubuntu-focal.pkr.hcl
Then, commit your changes.
$ git commit -m "Update artifact version"
Finally, build your artifact. Continue with the tutorial while Packer builds the artifact.
$ packer build ubuntu-focal.pkr.hcl
Tracking build on HCP Packer with fingerprint "01HMEZ0Y95E725FAD1N6Z3R5JD"
amazon-ebs.basic-example-east: output will be in this color.
amazon-ebs.basic-example-west: output will be in this color.
==> amazon-ebs.basic-example-east: Prevalidating any provided VPC information
==> amazon-ebs.basic-example-east: Prevalidating AMI Name: packer_AWS_1705604316_v1.0.1
==> amazon-ebs.basic-example-west: Prevalidating any provided VPC information
==> amazon-ebs.basic-example-west: Prevalidating AMI Name: packer_AWS_1705604316_v1.0.1
## ...
==> Wait completed after 3 minutes 29 seconds
==> Builds finished. The artifacts of successful builds are:
--> amazon-ebs.basic-example-east: AMIs were created:
us-east-2: ami-07a8e3b833ca6ca3c
--> amazon-ebs.basic-example-east: Published metadata to HCP Packer registry packer/learn-packer-ubuntu/versions/01HMEZ0YWFX5KE4MS4M4QEXKQM
--> amazon-ebs.basic-example-west: AMIs were created:
us-west-1: ami-060c0d170a406aa88
--> amazon-ebs.basic-example-west: Published metadata to HCP Packer registry packer/learn-packer-ubuntu/versions/01HMEZ0YWFX5KE4MS4M4QEXKQM
Add channels to the bucket
Visit the HCP Packer dashboard and select the learn-packer-ubuntu
artifact you created in the previous tutorial. Your bucket has one complete version and another that Packer is currently building.
Go to Channels in the left navigation menu and click New Channel. Create a new channel named production
and select the v1
version. Leave the Channel access as Unrestricted.
Query and deploy artifact
Wait until Packer finishes building the second version before continuing.
Once Packer completes the build, change into the tf-channel
directory.
$ cd tf-channel
Open tf-channel/main.tf
to review the Terraform configuration.
tf-channel/main.tf
provider "hcp" {}
data "hcp_packer_version" "ubuntu" {
bucket_name = "learn-packer-ubuntu"
channel_name = "production"
}
data "hcp_packer_artifact" "ubuntu_us_east_2" {
bucket_name = "learn-packer-ubuntu"
platform = "aws"
version_fingerprint = data.hcp_packer_version.ubuntu.fingerprint
region = "us-east-2"
}
This Terraform configuration contains two data sources:
The
hcp_packer_version
retrieves the channel's current version. Notice that this resource references the bucket name (learn-packer-ubuntu
) and channel (production
) you created in the previous steps.The
hcp_packer_artifact
retrieves a specific artifact from the version data source above. Remember that a version may contain multiple artifacts from different cloud providers and regions.
In addition, this configuration deploys an EC2 instance with the artifact you queried.
tf-channel/main.tf
resource "aws_instance" "app_server" {
ami = data.hcp_packer_artifact.ubuntu_us_east_2.external_identifier
instance_type = "t2.micro"
tags = {
Name = "Learn-HCP-Packer"
}
}
The Terraform provider for HCP uses the HCP_CLIENT_ID
, HCP_CLIENT_SECRET
, and HCP_PROJECT_ID
environment variables to authenticate to HCP. You configured these values in the previous tutorial.
Note
This tutorial uses the same service principal you configured previously with Contributor access to all HCP resources. HCP Packer lets you control access to individual buckets, and we recommend that you create a service principal that only has access to the buckets you need during your Terraform runs. Refer to HCP Packer permissions for more information.
Initialize your Terraform configuration.
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Reusing previous version of hashicorp/hcp from the dependency lock file
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/hcp v0.80.0...
- Installed hashicorp/hcp v0.80.0 (signed by HashiCorp)
- Installing hashicorp/aws v4.2.0...
- Installed hashicorp/aws v4.2.0 (signed by HashiCorp)
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Apply your configuration. Enter yes
when prompted to confirm the run.
$ terraform apply
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
+ create
Terraform will perform the following actions:
# aws_instance.app_server will be created
+ resource "aws_instance" "app_server" {
+ ami = "ami-0f7..."
## ...
+ }
Plan: 1 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ ubuntu_version = {
+ author_id = "packer"
+ bucket_name = "learn-packer-ubuntu"
+ channel_name = "production"
## ...
}
+ ubuntu_us_east_2 = {
+ bucket_name = "learn-packer-ubuntu"
## ...
}
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Creation complete after 23s [id=i-0a3ae53d111dd476f]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
ubuntu_version = {
"author_id" = "packer"
"bucket_name" = "learn-packer-ubuntu"
"channel_name" = "production"
"created_at" = "2024-01-18T18:44:16.668Z"
"fingerprint" = "01HMEY6Q765XFB19PBGY5FJKBK"
"id" = "01HMEY6QMW6H031QZ8EZPCNSMZ"
"name" = "v1"
"organization_id" = "982e1f67-b1b2-4f23-86c4-662f00fa8ff7"
"project_id" = "c8d1f392-bd75-4477-a666-c7b9705f2332"
"revoke_at" = "0001-01-01T00:00:00.000Z"
"updated_at" = "2024-01-18T18:48:46.526Z"
}
ubuntu_us_east_2 = {
"bucket_name" = "learn-packer-ubuntu"
"build_id" = "01HMEY6QWKN8H9R223769FG1P6"
"channel_name" = tostring(null)
"component_type" = "amazon-ebs.basic-example-east"
"created_at" = "2024-01-18T18:47:46.705Z"
"external_identifier" = "ami-0fe50da2394a934f9"
"id" = "01HMEYD4RHGFA887HXMKCFT0V8"
"labels" = tomap({
"build-source" = "learn-hcp-packer-get-started"
"build-time" = "2024-01-18T18:44:16Z"
"git_sha" = "a25bb28fdf785f0c4543659a62f8795b27fbcb32"
})
"organization_id" = "982e1f67-b1b2-4f23-86c4-662f00fa8ff7"
"packer_run_uuid" = "6faa1950-8a00-b5c4-19a1-ed5cdce2dd89"
"platform" = "aws"
"project_id" = "c8d1f392-bd75-4477-a666-c7b9705f2332"
"region" = "us-east-2"
"revoke_at" = tostring(null)
"version_fingerprint" = "01HMEY6Q765XFB19PBGY5FJKBK"
}
The ubuntu_version
output returns all metadata associated with the version. It shows that this is the first version (name = "v1"
) and that it is assigned to the production
channel.
The ubuntu_us_east_2
output returns the build for us_east_2
region. Notice that the external_identifier
maps to the AMI ID.
Update a channel to point to another version
Return to the Channels page in the HCP Packer portal.
Edit the production channel by clicking on the ... and selecting Changed assigned version. Then, update the channel to the second version.
View channel assignment history
Click on the production
channel name to view the channel's overview page.
Review the Assignment history section, which lists when you assigned each version to the channel.
Re-query channel artifact version
Now, re-apply your Terraform configuration. Enter yes
when prompted to confirm the run.
$ terraform apply
## ...
Plan: 1 to add, 0 to change, 1 to destroy.
## ...
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
aws_instance.app_server: Destroying... [id=i-0a3ae53d111dd476f]
aws_instance.app_server: Still destroying... [id=i-0a3ae53d111dd476f, 10s elapsed]
aws_instance.app_server: Still destroying... [id=i-0a3ae53d111dd476f, 20s elapsed]
aws_instance.app_server: Still destroying... [id=i-0a3ae53d111dd476f, 30s elapsed]
aws_instance.app_server: Destruction complete after 31s
aws_instance.app_server: Creating...
aws_instance.app_server: Still creating... [10s elapsed]
aws_instance.app_server: Still creating... [20s elapsed]
aws_instance.app_server: Creation complete after 22s [id=i-0127eeba25202f366]
Apply complete! Resources: 1 added, 0 changed, 1 destroyed.
Outputs:
ubuntu_version = {
"author_id" = "packer"
"bucket_name" = "learn-packer-ubuntu"
"channel_name" = "production"
"created_at" = "2024-01-18T18:58:36.047Z"
"fingerprint" = "01HMEZ0Y95E725FAD1N6Z3R5JD"
"id" = "01HMEZ0YWFX5KE4MS4M4QEXKQM"
"name" = "v2"
"organization_id" = "982e1f67-b1b2-4f23-86c4-662f00fa8ff7"
"project_id" = "c8d1f392-bd75-4477-a666-c7b9705f2332"
"revoke_at" = "0001-01-01T00:00:00.000Z"
"updated_at" = "2024-01-18T19:02:05.551Z"
}
ubuntu_us_east_2 = {
"bucket_name" = "learn-packer-ubuntu"
"build_id" = "01HMEZ0Z33Q04PH4JX3X41B2BZ"
"channel_name" = tostring(null)
"component_type" = "amazon-ebs.basic-example-east"
"created_at" = "2024-01-18T19:01:42.677Z"
"external_identifier" = "ami-07a8e3b833ca6ca3c"
"id" = "01HMEZ6N4NBRG1B5A2AZHZZPQR"
"labels" = tomap({
"build-source" = "learn-hcp-packer-get-started"
"build-time" = "2024-01-18T18:58:35Z"
"git_sha" = "a25bb28fdf785f0c4543659a62f8795b27fbcb32"
})
"organization_id" = "982e1f67-b1b2-4f23-86c4-662f00fa8ff7"
"packer_run_uuid" = "f6bf14ce-1b4e-1039-09a4-96a2b972d697"
"platform" = "aws"
"project_id" = "c8d1f392-bd75-4477-a666-c7b9705f2332"
"region" = "us-east-2"
"revoke_at" = tostring(null)
"version_fingerprint" = "01HMEZ0Y95E725FAD1N6Z3R5JD"
}
Since you updated the version the channel uses, the name
changed from v1
to v2
,
Destroy infrastructure
Run terraform destroy
to clean up your provisioned infrastructure. Respond
yes
to the prompt to confirm the operation.
$ terraform destroy
## ...
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
- destroy
Terraform will perform the following actions:
## ...
Plan: 0 to add, 0 to change, 1 to destroy.
## ...
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
## ...
Destroy complete! Resources: 1 destroyed.
Next steps
In this tutorial, you created a new channel in the HCP Packer registry. Next, you used Terraform to query the channel and its build artifacts metadata, then used the AMI ID to deploy an EC2 instance . Finally, you updated the channel to point to another version, and then queried the updated channel and build artifacts.
For more information on topics covered in this tutorial, check out the following resources:
- Read more about referencing artifact metadata in the HCP Packer documentation
- Visit the Terraform
hcp
provider for a full list of arguments and attributes for thehcp_packer_version
andhcp_packer_artifact
data resources - Visit the HCP Packer Glossary for additional descriptions of the terms covered in this tutorial