Packer is a tool for creating (golden) images from a configurable template.
Packer configuration file is a JSON file e.g. config.json.
config.json contains:
- variables
- builders
- provisioners
Example of configuration file used to create AWS AMI for multiple environments, by using Ansible as a provisioner:
config.json:
{
"variables": {
"env_name": "{{env `env_name`}}",
"instance_profile": "",
"ami_name": "asb-linux-al23-arm-{{timestamp}}",
"kms_key_id": "{{env `kms_key_id`}}",
"sg_default": "{{env `SG_DEFAULT`}}",
"current_user": "{{env `USER`}}"
},
"builders": [
{
"ami_name": "{{user `ami_name`}}",
"instance_type": "t4g.medium",
"region": "us-east-1",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "al2023-ami-2023.*-kernel-6.1-arm64",
"root-device-type": "ebs"
},
"owners": "amazon",
"most_recent": true
},
"ssh_username": "ec2-user",
"ssh_bastion_host": "bastion.mycorp.com",
"ssh_bastion_username": "{{user `current_user`}}",
"ssh_bastion_agent_auth": true,
"ssh_bastion_port": 22,
"ssh_timeout": "2m",
"ssh_clear_authorized_keys": "true",
"iam_instance_profile": "{{user `instance_profile`}}",
"type": "amazon-ebs",
"tags": {
"Name": "{{user `ami_name`}}",
"Environment": "{{user `env_name`}}"
},
"vpc_filter": {
"filters": {
"tag:Environment": "{{user `env_name`}}",
"isDefault": "false"
}
},
"subnet_filter": {
"filters": {
"tag:Name": "vpc-{{user `env_name`}}-private-us-east-*"
},
"most_free": true
},
"security_group_ids": [
"{{user `sg_default`}}"
],
"launch_block_device_mappings": [
{
"device_name": "/dev/xvda",
"encrypted": true,
"kms_key_id": "{{user `kms_key_id`}}",
"delete_on_termination": true,
"volume_type": "gp3"
}
]
}
],
"provisioners": [
{
"type": "shell",
"inline": [
"sudo dnf update -y",
"sudo dnf install -y python3"
]
},
{
"type": "ansible",
"host_alias": "packer",
"user": "ec2-user",
"inventory_directory": "ansible/env/aws/{{user `env_name`}}",
"playbook_file": "ansible/playbooks/playbook.yml",
"extra_arguments": [
"-D",
"--vault-password-file",
"./aws-{{user `env_name`}}-vault.pw",
"--scp-extra-args", "'-O'",
"--extra-vars",
"'ansible_python_interpreter=/usr/bin/python3'"
]
}
]
}
To run Packer:
$ packer build [-debug] config.json
AWS AMI gets created in the following way:
- a temporary SSH keypair is created
- new temporary EC2 instance is started. This instance is based on source AMI specified in configuration file
- SSH tunnel is established between local/dev host and remote EC2 instance
- provisioners are run e.g. Ansible is installing packages etc...
- once provisioners work is completed ephemeral key is removed from authorized_keys file on temp EC2 instance
- temp EC2 instance is terminated
- a snapshot of the root disk of that EC2 instance is created
- a new AMI is created based on that snapshot
- tags are added to snapshot
- tags are added to AMI
- temp SSH keypair is destroyed
---