Skip to main content

Modelo

Não será abordado neste estudo modelos em Json, somente HCL2 que é o recomendado pela Hashicorp.

O Packer usa a HashiCorp Configuration Language - HCL - projetada para permitir descrições concisas das etapas necessárias para obter um arquivo de compilação.

Uma breve explicação sobre o modelo HCL2 https://developer.hashicorp.com/packer/guides/hcl

Tudo pode ser definido dentro de um único arquivo, mas é interessante separar os arquivos para uma melhor organização.

  • variables.pkr.hcl
  • packer.pkr.hcl
  • build1.pkr.hcl
  • build2.pkr.hcl

Tipos de bloco

A linguagem Packer - HCL2 inclui vários blocos integrados que você pode usar para configurar compilações. Um bloco é um contêiner para configuração.

Os blocos mais importantes podem ser divididos em alguns tipos principais:

  • build os blocos contêm configuração para uma combinação específica de construtores, provisionadores e pós-processadores usados ​​para criar um artefato de imagem específico.

  • source os blocos contêm configuração para plug-ins do construtor. Uma vez definidas, as fontes podem ser usadas e configuradas posteriormente pelo bloco "build".

  • provisioners blocos contêm configuração para plug-ins do provisionador. Esses blocos são aninhados dentro de um bloco de construção.

  • post-processors post-processorsos blocos contêm configuração para plug-ins de pós-processador e sequências de plug-ins de pós-processador. Eles também estão aninhados dentro de buildblocos.

  • variable os blocos contêm configuração para variáveis ​​que podem ser padronizadas na configuração ou definidas pelo usuário em tempo de execução.

  • locals os blocos contêm configuração para variáveis ​​que podem ser criadas usando funções HCL ou fontes de dados, ou compostas de variáveis ​​criadas nos blocos de variáveis.

  • packer fornecem informações ao núcleo do Packer sobre qual versão ele pode executar. O bloco "required_plugins" ajuda o núcleo do Packer

Variable

Um exemplo do bloco variable poderia estar definido dentro de um arquivo variables.pkr.hcl.

Como boa prática sempre tenha a descrição.

variable "project_name" {
type = string
description = "Project Name "
}

variable "region" {
type = string
default = "us-east-1"
description = "Region to create source in aws"
sensitive = false
# When a variable is sensitive all string-values from that variable will be
# obfuscated from Packer's output.
}

Locals

Arquivo utilizado para manipular variáveis internamente com interpolação ou até mesmo setar uma variável por função. Não é obrigatório, mas é uma questão de organização.

Eu particulamente prefiro declarar um arquivo separado para locals chamado locals.pkr.hcl

locals {
timestamp = regex_replace(timestamp(), "[- TZ:]", "")
}

# Use the singular local block if you need to mark a local as sensitive
local "mylocal" {
expression = "${var.secret_api_key}"
sensitive = true
}

Packer

Este único bloco é usado para configurar alguns comportamentos do próprio Packer, como a versão mínima necessária do Packer necessária para aplicar sua configuração.

É uma boa prática sempre definir uma versão mínima.

Gosto de isolar esse bloco em packer.pkr.hcl

packer {
required_plugins {
happycloud = {
version = ">= 2.7.0"
source = "github.com/hashicorp/happycloud"
}
}
required_version = ">= 1.8.5"
}

Data

Este bloco define fonte de dados como por exemplo buscar algum recurso na cloud para ser referenciado durante o processo de build

Gosto de manter estes bloco também separado em data.pkr.hcl quando necessários


Os dois blocos a seguir gosto de manter no mesmo arquivo que seria o main.pkr.hcl

Source

Os blocos sources definem a configuração do construtor, porém é no bloco build que eles são instanciados. Resumindo irá criar a base para o build acontecer. Se estamos falando de criar um ami baseada em outra, esse bloco irá declarar qual deve ser a configuração de uma ec2 quando o build instanciar.

Cada source deve ser único com o nome, mas podem ter os mesmos tipos.

## amazon-ebs é o tipo e ec2main é o nome para ser referenciado mais tarde pelo bloco build

source "amazon-ebs" "ec2main" {

ami_name = "${var.project_name}-${local.timestamp}"
ami_regions = var.ami_regions
instance_type = var.instance_type
region = var.region
source_ami_filter {
filters = {
name = var.image_name
virtualization-type = var.virtualization
root-device-type = "ebs"
}
owners = ["${var.image_owner}"]
most_recent = true
}
ssh_username = var.ssh_username
ssh_timeout = var.ssh_timeout
ssh_keep_alive_interval = var.ssh_keep_alive_interval
ssh_pty = var.ssh_pty
}

Cada tipo de source tem sua própria configuração. É necessário estudar cada um deles quando necessário serem usados.

Este bloco poderia ser todo declarado dentro de build, mas não fica organizado. Porém poderíamos somente reescrever alguns valores caso necessários. A vantagem disso é inclusive o reaproveitamento de código. Por isso gosto de manter no mesmo arquivo.

Build

É o principal bloco e somente com este bloco poderia conseguir uma compilação direto no packer caso todas as variáveis fossem setadas ou nenhum plugin extra fosse necessário.

Este bloco define quais construtores são iniciados, como fazer o provisionamento e se necessário o que fazer com o artefato gerado.


build {
# Name caso setado irá dar nome ao log, mas não é obrigatório
name = "buildname"

# lista de sources que será utilizado sem renomear nenhum atributo
sources = [
"source.amazon-ebs.ec2main",
]

# Caso tenha algum source que irá ser utilizado e queira renomear algo deve separar este e fazer a mudança
source "source.amazon-ebs.ec2secondary" {
output = "different value"
name = "differentname"
}

# Existem diferentes provisioners que é o que de fato executará para personalizar a imagem.

provisioner "shell" {
scripts = fileset(".", "scripts/{install,secure}.sh")
}

# Caso queira fazer algo com o artefato utilizar o post-processor
post-processor "shell-local" {
inline = ["echo Hello World from ${source.type}.${source.name}"]
}
}

Porem ser definidos vários provisioner e vários post-processor

Leitura extra

Vale a pena uma leitura rápida em Expressões e sintaxe