Overview
HashiCorp의 Packer에 대해서 공부해보려고 한다.
이전 게시글인 Vagrant에 사용할 image box를 Packer를 이용해서 만들어 볼것이다.
2022.08.25 - [Understand different OS Concepts/Virtualization] - Vagrant란?
https://github.com/somaz94/vagant-packer
Packer란?
Packer 는 단일 소스 템플릿에서 여러 플랫폼에 대해 동일한 머신 이미지를 생성할 수 있는 오픈 소스 도구이다.
일반적인 사용 사례는 조직 전체의 팀이 클라우드 인프라에서 사용할 수 있는 "Golden image"를 만드는 것다.
Packer 패키지 설치
# CentOS/RHEL
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
sudo yum -y install vagrant
sudo yum -y install qemu libvirt libvirt-devel ruby-devel gcc qemu-kvm libguestfs-tools
vagrant plugin install vagrant libvirt
vagrant plugin install vagrant-mutate
vagrant plugin install vagrant-parallels
# Ubuntu/Debian
wget -O- https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor -o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/hashicorp-archive-keyring.gpg] https://apt.releases.hashicorp.com $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install vagrant
sudo apt install -y qemu qemu-kvm libvirt-daemon libvirt-clients bridge-utils virt-manager
vagrant plugin install vagrant libvirt
vagrant plugin install vagrant-mutate
vagrant plugin install vagrant-parallels
Packer CLI 자동완성
packer -autocomplete-install
Packer error 조치(명령어 error)
packer --help
Usage: packer dbname
if dbname is not specified, will use compiled in default of (/usr/share/cracklib/pw_dict).
cd /usr/sbin/
ls -al |grep packer
-rwxr-xr-x. 1 root root 11328 Jun 10 2014 cracklib-packer
-rwxr-xr-x. 1 root root 7184 Jun 10 2014 cracklib-unpacker
lrwxrwxrwx. 1 root root 15 Feb 10 2022 packer -> cracklib-packer
rm -rf packer
ln -s /usr/bin/packer 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
plugins Interact with Packer plugins and catalog
validate check that a template is valid
version Prints the Packer version
Packer CLI
init
- Packer 플러그인 바이너리를 다운로드 사용
$ packer init -h
Usage: packer init [options] [config.pkr.hcl|folder/]
Install all the missing plugins required in a Packer config. Note that Packer
does not have a state.
This is the first command that should be executed when working with a new
or existing template.
This command is always safe to run multiple times. Though subsequent runs may
give errors, this command will never delete anything.
Options:
-upgrade On top of installing missing plugins, update
installed plugins to the latest available
version, if there is a new higher one. Note that
this still takes into consideration the version
constraint of the config.
plugins
- Packer 플러그인과 상호 작용하기 위한 하위 명령을 그룹화
packer plugins -h
Usage: packer plugins <subcommand> [options] [args]
This command groups subcommands for interacting with Packer plugins.
Related but not under the "plugins" command :
- "packer init <path>" will install all plugins required by a config.
Subcommands:
install Install latest Packer plugin [matching version constraint]
installed List all installed Packer plugin binaries
remove Remove Packer plugins [matching a version]
required List plugins required by a config
build
- packer build 명령은 템플릿을 사용하고 아티팩트 집합을 생성하기 위해 템플릿 내의 모든 빌드를 실행합니다.
packer build -h
Usage: packer build [options] TEMPLATE
Will execute multiple builds in parallel as defined in the template.
The various artifacts created by the template will be outputted.
Options:
-color=false Disable color output. (Default: color)
-debug Debug mode enabled for builds.
-except=foo,bar,baz Run all builds and post-processors other than these.
-only=foo,bar,baz Build only the specified builds.
-force Force a build to continue if artifacts exist, deletes existing artifacts.
-machine-readable Produce machine-readable output.
-on-error=[cleanup|abort|ask|run-cleanup-provisioner] If the build fails do: clean up (default), abort, ask, or run-cleanup-provisioner.
-parallel-builds=1 Number of builds to run in parallel. 1 disables parallelization. 0 means no limit (Default: 0)
-timestamp-ui Enable prefixing of each ui output with an RFC3339 timestamp.
-var 'key=value' Variable for templates, can be used multiple times.
-var-file=path JSON or HCL2 file containing user variables.
packer build somaz-os-test.vagrant.json
somaz-os-test: output will be in this color.
이 외에도 console, fix, fmt, inspect, validate, hcl2_upgrade 등이있다.
Packer Template
Packer의 동작은 Packer가 따를 일련의 선언과 명령으로 구성된 Packer 템플릿에 의해 결정된다.
Packer는 과거에는 JSON 템플릿을 사용했지만, Terraform 및 HashiCorp의 다른 제품에서 사용하는 것과 동일한 구성 언어인 HCL2를 사용하는 새로운 템플릿 구성 형식으로 전환하고 있다.
해당 형식은 원래 JSON 템플릿 형식보다 더 유연하고 모듈식이며 간결하다.
JSON 형식은 계속 지원되지만 Packer 코어의 특정 새 기능은 최신 HCL 형식에 대해서만 구현된다.
HCL 형식
HCL 언어의 구문은 다음과 같은 몇 가지 기본 요소로만 구성된다.
# This file was autogenerated by the 'packer hcl2_upgrade' command. We
# recommend double checking that everything is correct before going forward. We
# also recommend treating this file as disposable. The HCL2 blocks in this
# file can be moved to other files. For example, the variable blocks could be
# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
# once they also need to be in the same folder. 'packer inspect folder/'
# will describe to you what is in that folder.
# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
# executed together and the outcome will be unknown.
# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = "~> 1"
}
}
}
# All generated input variables will be of 'string' type as this is how Packer JSON
# views them; you can change their type later on. Read the variables type
# constraints documentation
# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
variable "cpu" {
type = string
default = "2"
}
variable "instance_type" {
type = string
default = "t2.micro"
}
variable "ram" {
type = string
default = "2048"
}
variable "region" {
type = string
default = "ap-northeast-2"
}
variable "user" {
type = string
default = "ec2-user"
}
variable "password" {
type = string
default = "somaz@2023"
}
# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
# from this block can be referenced in source and locals blocks.
# Read the documentation for data blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/data
# Read the documentation for the Amazon AMI Data Source here:
# https://www.packer.io/plugins/datasources/amazon/ami
data "amazon-ami" "autogenerated_1" {
filters = {
name = "amzn2-ami-hvm-*-x86_64-gp2"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["amazon"]
region = "${var.region}"
}
# "timestamp" template function replacement
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/source
source "amazon-ebs" "autogenerated_1" {
ami_name = "amazon-linux2-golden-image ${local.timestamp}"
force_deregister = true
instance_type = "${var.instance_type}"
region = "${var.region}"
source_ami = "${data.amazon-ami.autogenerated_1.id}"
ssh_interface = "public_ip"
ssh_username = "${var.user}"
tags = {
Name = "Amazon Linux 2 Golden Image"
}
}
# a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
sources = ["source.amazon-ebs.autogenerated_1"]
provisioner "shell" {
execute_command = "echo ' ${var.password}' | {{ .Vars }} sudo -E -S bash '{{ .Path }}'"
scripts = ["scripts/package.sh"]
}
}
JSON 형식
Json 템플릿
템플릿은 Packer의 다양한 구성 요소를 구성하는 키 집합이 있는 JSON 개체입니다.
템플릿 내에서 사용 가능한 키가 아래에 나열되어 있습니다. 각 키와 함께 필수 여부가 표시됩니다.
Json 템플릿 구조
{
"variables": {
"cpu": "2",
"ram": "2048",
"user": "ec2-user",
"region": "ap-northeast-2",
"instance_type": "t2.micro"
},
"builders": [
{
"type": "amazon-ebs",
"region": "{{user `region`}}",
"source_ami_filter": {
"filters": {
"virtualization-type": "hvm",
"name": "amzn2-ami-hvm-*-x86_64-gp2",
"root-device-type": "ebs"
},
"owners": ["amazon"],
"most_recent": true
},
"instance_type": "{{user `instance_type`}}",
"ssh_username": "{{user `user`}}",
"ami_name": "amazon-linux2-golden-image {{timestamp}}",
"ssh_interface": "public_ip",
"force_deregister": true,
"tags": {
"Name": "Amazon Linux 2 Golden Image"
}
}
],
"provisioners": [
{
"type": "shell",
"execute_command": "echo ' {{user `password`}}' | {{.Vars}} sudo -E -S bash '{{.Path}}'",
"scripts": [
"scripts/package.sh"
]
}
]
}
- builders( 필수 )는 이 템플릿에 대한 머신 이미지를 생성하는 데 사용할 빌더를 정의하고 해당 빌더 각각을 구성하는 하나 이상의 객체 배열입니다. 자세한 내용 은 템플릿에서 빌더 구성 에 대한 하위 섹션을 참조해보자.
- variables(선택 사항) 템플릿에 포함된 사용자 변수를 정의하는 하나 이상의 키/값 문자열의 개체입니다.자세한 내용 은 템플릿의 사용자 변수에 대한 하위 섹션을 참조해보자.
- provisioners(선택 사항) 각 빌더가 생성한 시스템에 대한 소프트웨어를 설치 및 구성하는 데 사용할 프로비저닝 도구를 정의하는 하나 이상의 개체 배열입니다. 자세한 내용 은 템플릿에서 프로비저닝 도구 구성 에 대한 하위 섹션을 참조해보자.
- post-processors(선택 사항) 빌드된 이미지와 함께 수행할 다양한 사후 처리 단계를 정의하는 하나 이상의 개체 배열입니다. 자세한 내용은 템플릿에서 포스트 프로세서 구성 에 대한 하위 섹션을 참조해보자.
Packer JSON 템플릿을 HCL2 업그레이드
Packer는 hcl2_upgrade 명령을 사용하여 기존 Packer JSON 템플리을 HCL2로 전환할 수 있다.
자세한 내용은 Github 링크를 참조하면 된다.
ubuntu-gce.json
{
"variables": {
"project_id": "somaz",
"source_image_family": "ubuntu-2004-lts",
"zone": "asia-northeast3-a",
"machine_type": "n1-standard-1",
"account_file": "/home/somaz/.ssh/somaz-key.json",
"password" : "somaz@2023"
},
"builders": [
{
"type": "googlecompute",
"project_id": "{{user `project_id`}}",
"source_image_family": "{{user `source_image_family`}}",
"zone": "{{user `zone`}}",
"machine_type": "{{user `machine_type`}}",
"ssh_username": "ubuntu",
"image_name": "ubuntu-golden-image-{{timestamp}}",
"image_description": "Ubuntu Golden Image",
"disk_type": "pd-ssd",
"disk_size": "10",
"network": "default",
"subnetwork": "default",
"tags": ["ubuntu", "golden-image"],
"use_internal_ip": false,
"account_file": "{{user `account_file`}}"
}
],
"provisioners": [
{
"type": "shell",
"execute_command": "echo '{{user `password`}}' | {{.Vars}} sudo -E -S bash '{{.Path}}'",
"scripts": [
"scripts/ubuntu-setup.sh"
]
}
]
}
Packer JSON 템플릿을 HCL2 업그레이드한다.
packer hcl2_upgrade -with-annotations ubuntu-gce.json
Successfully created ubuntu-gce.json.pkr.hcl
ubuntu-gce.json.pkr.hcl
# This file was autogenerated by the 'packer hcl2_upgrade' command. We
# recommend double checking that everything is correct before going forward. We
# also recommend treating this file as disposable. The HCL2 blocks in this
# file can be moved to other files. For example, the variable blocks could be
# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
# once they also need to be in the same folder. 'packer inspect folder/'
# will describe to you what is in that folder.
# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
# executed together and the outcome will be unknown.
# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
packer {
required_plugins {
googlecompute = {
source = "github.com/hashicorp/googlecompute"
version = "~> 1"
}
}
}
# All generated input variables will be of 'string' type as this is how Packer JSON
# views them; you can change their type later on. Read the variables type
# constraints documentation
# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
variable "account_file" {
type = string
default = "/home/somaz/.ssh/somaz.json"
}
variable "machine_type" {
type = string
default = "n1-standard-1"
}
variable "project_id" {
type = string
default = "somaz"
}
variable "source_image_family" {
type = string
default = "ubuntu-2004-lts"
}
variable "zone" {
type = string
default = "asia-northeast3-a"
}
variable "password" {
type = string
default = "somaz@2023"
}
# "timestamp" template function replacement
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/source
source "googlecompute" "autogenerated_1" {
account_file = "${var.account_file}"
disk_size = "10"
disk_type = "pd-ssd"
image_description = "Ubuntu Golden Image"
image_name = "ubuntu-golden-image-${local.timestamp}"
machine_type = "${var.machine_type}"
network = "default"
project_id = "${var.project_id}"
source_image_family = "${var.source_image_family}"
ssh_username = "ubuntu"
subnetwork = "default"
tags = ["ubuntu", "golden-image"]
use_internal_ip = false
zone = "${var.zone}"
}
# a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
sources = ["source.googlecompute.autogenerated_1"]
provisioner "shell" {
execute_command = "echo '${var.password}' | {{ .Vars }} sudo -E -S bash '{{ .Path }}'"
scripts = ["scripts/ubuntu-setup.sh"]
}
}
Reference
https://youngswooyoung.tistory.com/176
https://github.com/somaz94/vagant-packer
https://developer.hashicorp.com/packer/tutorials/configuration-language/hcl2-upgrade
'IaC > Infrastructure Provisioning' 카테고리의 다른 글
4. Terraform의 다양한 Function(함수) (0) | 2023.04.11 |
---|---|
3. Terraform 다양한 변수(variable, local, data...output, input) - AWS (0) | 2023.04.09 |
2. Terraform 변수 사용법(use-variable) - AWS (0) | 2023.04.05 |
1. Terraform 기초 : 설치 및 .tf 파일 설명 (0) | 2023.04.04 |
Vagrant란? (0) | 2022.08.25 |