Packer, HashiCorp'un geliştirdiği ve cloud ortamları için golden image oluşturma sürecini otomatikleştiren bir araç. Geleneksel manuel VM hazırlama yöntemlerinin yerine, tek bir konfigürasyon dosyasından birden fazla platform için (AWS, Azure, VMware, VirtualBox, DigitalOcean, GCP) aynı anda veya sırayla image üretebiliyor. Bu yaklaşım, altyapının yeniden üretilebilirliğini sağlarken provisioning süresini dramatik şekilde düşürüyor.
Temel Kavramlar
Packer'ın çalışma mantığı üç temel yapı taşı üzerine kurulu. Builder, hedef platform için VM oluşturan ve image çıkaran bileşen. Her builder kendi yöntemiyle çalışır; AWS için AMI oluşturur, VirtualBox için OVA/OVF çıktısı verir. Provisioner, VM oluşturulduktan sonra içeriye yazılım yükleyen, konfigürasyon yapan katman. Bash scriptleri, PowerShell, Ansible, Chef, Puppet, Salt gibi araçlarla bu işlem gerçekleştirilir. Post-processor ise oluşturulan image üzerinde son işlemleri yapar; örneğin Vagrant box'a dönüştürme veya compress işlemi gibi.
Kurulum ve İlk Adımlar
Linux sistemlere HashiCorp deposundan paket olarak kurulabilir ya da resmi indirme sayfasından işletim sistemine uygun binary indirilip PATH'e eklenir. Kurulum sonrası packer version komutuyla doğrulama yapılır. Çalışma prensibi oldukça basit: HCL (HashiCorp Configuration Language) formatında yazılmış template dosyası packer build komutuna verilir, araç gerekli VM'i oluşturur, provisioner'ları çalıştırır ve son image'i paketler. Builder'lar Packer'ın güncel sürümlerinde plugin olarak dağıtılır; build öncesinde template dizininde packer init çalıştırmak gerekli pluginleri indirir.
Template Yapısı
Bir Packer template'i source ve build bloklarından oluşur. Source bloğu hangi platform için hangi parametrelerle VM oluşturulacağını tanımlar. Build bloğu ise hangi source'un kullanılacağını, hangi provisioner'ların çalışacağını ve post-processors zincirini belirtir.
source "virtualbox-iso" "ubuntu-server" {
guest_os_type = "Ubuntu_64"
iso_url = "https://releases.ubuntu.com/22.04/ubuntu-22.04.3-live-server-amd64.iso"
iso_checksum = "sha256:abc123..."
disk_size = 40960
memory = 2048
cpus = 2
ssh_username = "ubuntu"
ssh_password = "ubuntu"
ssh_port = 22
shutdown_command = "echo 'ubuntu' | sudo shutdown -P now"
vm_name = "ubuntu-server-base"
}
build {
name = "ubuntu-base"
sources = ["source.virtualbox-iso.ubuntu-server"]
provisioner "shell" {
execute_command = "chmod +x {{ .Path }} && {{ .Vars }} {{ .Path }}"
inline = [
"sudo apt-get update",
"sudo apt-get install -y curl wget git nginx",
"sudo systemctl enable nginx"
]
}
}
Yukarıdaki örnek VirtualBox için Ubuntu Server image oluşturur. Disk boyutu 40GB, bellek 2GB, 2 CPU ayrılmıştır. SSH ile bağlanıp shell provisioner çalıştırılır; apt-get ile temel yazılımlar kurulur ve nginx servisi aktive edilir.
Farklı Platformlar İçin Aynı Template
Packer'ın güçlü yanı tek bir template'den birden fazla builder ile image üretebilmesidir. AWS ve Azure için AMI oluşturmak istendiğinde source bloğu çoğaltılır, build bloğunda her ikisi de sources listesine eklenir. Build sürecinde builder'lar varsayılan olarak paralel çalışır ve her biri kendi platformuna özgü image'i üretir. Bu yaklaşım, farklı cloud sağlayıcılarında aynı base image'i kullanmayı sağlar ve configuration drift sorunlarını ortadan kaldırır.
source "amazon-ebs" "web-server" {
ami_name = "web-server-{{ timestamp }}"
instance_type = "t3.micro"
region = "us-east-1"
ssh_username = "ubuntu"
source_ami_filter {
filters = {
name = "ubuntu/images/*ubuntu-jammy-22.04-amd64-server-*"
root-device-type = "ebs"
virtualization-type = "hvm"
}
most_recent = true
owners = ["099720109477"]
}
}
source "azure-arm" "web-server" {
os_type = "Linux"
image_publisher = "Canonical"
image_offer = "0001-com-ubuntu-server-jammy"
image_sku = "22_04-lts-gen2"
location = "westeurope"
vm_size = "Standard_B1s"
}
build {
sources = [
"source.amazon-ebs.web-server",
"source.azure-arm.web-server"
]
provisioner "ansible" {
playbook_file = "./web-server.yml"
}
}
Provisioner Seçenekleri
Shell provisioner en basit yöntem; bash scriptleri veya inline komutlarla çalışır. Ansible provisioner, mevcut Ansible playbook'larını doğrudan kullanır ve karmaşık konfigürasyonları yönetilebilir kılar. Chef, Puppet ve Salt provisioner'ları bu araçları zaten kullanan ekipler için uygundur. File provisioner dosya kopyalama işlemi yapar; local dosyaları VM içine taşır. Windows ortamlar için PowerShell ve Windows Shell provisioner'ları mevcuttur.
Provisioner'ların çalışma sırası önemlidir. Birden fazla provisioner varsa sırayla yürütülür. Her provisioner VM'e SSH veya WinRM ile bağlanarak komut çalıştırır. Bağlantı parametreleri source bloğunda tanımlanır; özel key kullanımı, port ayarları ve timeout değerleri burada belirlenir.
Değişkenler ve Koşullu Mantık
HCL2'nin sunduğu değişken sistemi template'leri esnek kılar. Variable blokları ile input değerleri tanımlanır, build sırasında -var veya -var-file ile değerler aktarılır. Locals bloğu hesaplanan değerler için kullanılır. Conditional ifadeler ve for döngüleri ile dinamik konfigürasyonlar oluşturulabilir. Örneğin farklı region'lar için farklı AMI ID'leri tanımlanabilir veya debug modu aktifken ek provisioner'lar çalıştırılabilir.
Pipeline ve CI/CD Entegrasyonu
Packer, CI/CD pipeline'larına doğrudan entegre edilir. GitLab CI, Jenkins, GitHub Actions veya Terraform Cloud ile birlikte kullanılabilir. Image oluşturma süreci tamamen otomatik olduğundan, her commit sonrası güncel image üretilebilir. Bu yaklaşım immutable infrastructure prensibini destekler; her deployment yeni bir image üzerinden yapılır, mevcut VM'ler üzerinde değişiklik yapılmaz.
Best Practices
Image boyutunu minimal tutmak önemlidir; gereksiz paketler kurulmamalı, temizlik komutları provisioner'ların sonunda çalıştırılmalıdır. Provisioner'ı mümkün olduğunca az tutmak gerekir; çok sayıda küçük script yerine az sayıda kapsamlı script tercih edilmelidir. Image versiyonlama için timestamp veya git commit hash kullanılmalı, böylece hangi konfigürasyonun hangi image'e karşılık geldiği takip edilebilir olmalıdır. Sensitive veriler (parolalar, tokenlar) environment variable veya Vault entegrasyonu ile yönetilmeli, template içinde açık yazılmamalıdır.
