TLDR: Các biến tạo mẫu có thể tái sử dụng. Xác định chúng bằng các loại và giá trị mặc định, ghi đè chúng khi chạy hoặc bằng các tệp biến. Cấu trúc các dự án với các thư mục rõ ràng, sử dụng kiểm soát phiên bản và triển khai thử nghiệm thích hợp trước khi triển khai image.
Các biến cho phép bạn viết mẫu một lần và sử dụng chúng trong nhiều ngữ cảnh - các vùng, môi trường, phiên bản hoặc nhà cung cấp đám mây khác nhau.
Xác định biến
variable "region" {
type = string
default = "us-east-1"
description = "AWS region to build in"
}
variable "instance_type" {
type = string
default = "t3.micro"
}
variable "app_version" {
type = string
# No default - must be provided
}
variable "enable_monitoring" {
type = bool
default = true
}
variable "tags" {
type = map(string)
default = {
Environment = "production"
ManagedBy = "packer"
}
}
Sử dụng biến
Các biến tham chiếu với var.name:
source "amazon-ebs" "app" {
region = var.region
instance_type = var.instance_type
ami_name = "myapp-${var.app_version}-{{timestamp}}"
tags = var.tags
}
provisioner "shell" {
environment_vars = [
"APP_VERSION=${var.app_version}",
"MONITORING=${var.enable_monitoring}"
]
script = "scripts/install.sh"
}
Cung cấp các giá trị biến
Dòng lệnh:
packer build -var="region=us-west-2" -var="app_version=1.2.3" template.pkr.hcl
EBiến môi trường:
export PKR_VAR_region="us-west-2"
export PKR_VAR_app_version="1.2.3"
packer build template.pkr.hcl
Các tệp biến (production.pkrvars.hcl):
region = "us-east-1"
app_version = "2.0.0"
instance_type = "t3.small"
tags = {
Environment = "production"
Project = "myapp"
CostCenter = "engineering"
}
Sử dụng với:
packer build -var-file="production.pkrvars.hcl" template.pkr.hcl
Biến nhạy cảm
Đánh dấu các biến là nhạy cảm để ẩn chúng khỏi đầu ra:
variable "api_token" {
type = string
sensitive = true
}
Các giá trị bị ẩn trong đầu ra Packer:
==> amazon-ebs.app: Setting API token to <sensitive>
Xác thực biến
Thêm quy tắc xác thực:
variable "region" {
type = string
validation {
condition = contains(["us-east-1", "us-west-2", "eu-west-1"], var.region)
error_message = "Region must be us-east-1, us-west-2, or eu-west-1."
}
}
variable "app_version" {
type = string
validation {
condition = can(regex("^[0-9]+\\.[0-9]+\\.[0-9]+$", var.app_version))
error_message = "Version must be in semantic versioning format (e.g., 1.2.3)."
}
}
Biến cục bộ
Tính giá trị từ các biến khác:
locals {
timestamp = formatdate("YYYY-MM-DD-hhmm", timestamp())
ami_name = "${var.app_name}-${var.app_version}-${local.timestamp}"
common_tags = merge(
var.tags,
{
BuildDate = local.timestamp
GitCommit = var.git_commit
}
)
}
source "amazon-ebs" "app" {
ami_name = local.ami_name
tags = local.common_tags
}
Cấu trúc dự án
Tổ chức các dự án Packer để bảo trì:
packer-templates/
├── builds/
│ ├── web-server/
│ │ ├── template.pkr.hcl
│ │ ├── variables.pkr.hcl
│ │ ├── production.pkrvars.hcl
│ │ ├── staging.pkrvars.hcl
│ │ └── README.md
│ └── database/
│ ├── template.pkr.hcl
│ └── variables.pkr.hcl
├── scripts/
│ ├── install-nginx.sh
│ ├── configure-monitoring.sh
│ └── cleanup.sh
├── files/
│ ├── nginx.conf
│ ├── app.service
│ └── motd
├── ansible/
│ ├── playbook.yml
│ └── roles/
├── Makefile
└── README.md
Makefile cho các tác vụ thông thường
.PHONY: init validate fmt build-staging build-prod
init:
packer init builds/
validate:
packer validate builds/
fmt:
packer fmt -recursive .
build-staging:
packer build \
-var-file="builds/web-server/staging.pkrvars.hcl" \
builds/web-server/
build-prod:
packer build \
-var-file="builds/web-server/production.pkrvars.hcl" \
builds/web-server/
test:
packer build -only="docker.*" builds/web-server/
Kiểm soát phiên bản
.gitignore:
# Packer cache
packer_cache/
*.box
*.ova
*.tar.gz
# Build artifacts
manifest.json
output-*/
# Credentials
*.pem
*.key
credentials.json
*.pkrvars.hcl
!example.pkrvars.hcl
# Terraform
.terraform/
*.tfstate
*.tfstate.backup
Đang thử nghiệm image
Xác thực trước khi xây dựng
# Validate syntax
packer validate template.pkr.hcl
# Format check
packer fmt -check template.pkr.hcl
Xây dựng thử nghiệm với Docker
Kiểm tra việc cung cấp cục bộ trước khi xây dựng đám mây:
source "docker" "test" {
image = "ubuntu:22.04"
commit = true
}
source "amazon-ebs" "prod" {
# ... AWS configuration
}
build {
sources = [
"source.docker.test",
"source.amazon-ebs.prod"
]
# Same provisioners for both
provisioner "shell" {
script = "install.sh"
}
}
Chỉ kiểm tra với Docker:
packer build -only="docker.test" template.pkr.hcl
Kiểm tra sau xây dựng
Khởi chạy một phiên bản và chạy thử nghiệm:
#!/bin/bash
# test-image.sh
AMI_ID=$(jq -r '.builds[0].artifact_id' manifest.json | cut -d: -f2)
# Launch instance
INSTANCE_ID=$(aws ec2 run-instances \
--image-id $AMI_ID \
--instance-type t3.micro \
--query 'Instances[0].InstanceId' \
--output text)
# Wait for instance
aws ec2 wait instance-running --instance-ids $INSTANCE_ID
# Get IP
IP=$(aws ec2 describe-instances \
--instance-ids $INSTANCE_ID \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text)
# Run tests
curl -f http://$IP/ || exit 1
ssh ubuntu@$IP 'systemctl is-active nginx' || exit 1
# Cleanup
aws ec2 terminate-instances --instance-ids $INSTANCE_ID
echo "Tests passed!"
Tích hợp CI/CD
Hành động GitHub
name: Build AMI
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Packer
uses: hashicorp/setup-packer@main
- name: Initialize Packer
run: packer init builds/
- name: Validate templates
run: packer validate builds/
- name: Build AMI
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
packer build \
-var="app_version=${GITHUB_REF#refs/tags/v}" \
-var-file="production.pkrvars.hcl" \
builds/web-server/
- name: Upload manifest
uses: actions/upload-artifact@v3
with:
name: manifest
path: manifest.json
CI GitLab
variables:
PACKER_VERSION: "1.10.0"
stages:
- validate
- build
validate:
stage: validate
image: hashicorp/packer:${PACKER_VERSION}
script:
- packer init builds/
- packer validate builds/
- packer fmt -check -recursive .
build-ami:
stage: build
image: hashicorp/packer:${PACKER_VERSION}
only:
- tags
script:
- packer build -var="app_version=$CI_COMMIT_TAG" builds/
artifacts:
paths:
- manifest.json
Thực tiễn tốt nhất về bảo mật
Không bao giờ có thông tin xác thực commit: Sử dụng các biến môi trường hoặc quản lý bí mật.
Sử dụng vai trò IAM: Đối với các bản dựng AWS, hãy sử dụng cấu hình phiên bản IAM thay vì khóa truy cập khi có thể.
Emã hóa hình ảnh: Kích hoạt mã hóa cho AMI và đĩa image:
source "amazon-ebs" "encrypted" {
encrypt_boot = true
kms_key_id = var.kms_key_id
}
Quét hình ảnh: Chạy trình quét bảo mật trên image được tích hợp sẵn trước khi triển khai.
Quyền tối thiểu: Phiên bản xây dựng chỉ cần các quyền mà chúng thực sự sử dụng.
Phiên bản xây dựng an toàn: Sử dụng mạng con riêng tư và nhóm bảo mật hạn chế quyền truy cập.
Tối ưu hóa hiệu suất
Sử dụng các loại phiên bản nhanh hơn: Thời gian xây dựng là tiền bạc. Sử dụng các phiên bản lớn hơn để xây dựng nhanh hơn.
Parallelize build: Xây dựng đồng thời nhiều nền tảng (mặc định).
Cache phụ thuộc: Tải xuống các tệp lớn một lần, sử dụng lại trên các bản dựng.
Dọn dẹp hiệu quả: Sử dụng find với -delete thay vì rm -rf cho các thư mục lớn.
Tiếp theo là gì
Bây giờ bạn đã biết cách tạo production-sẵn sàng Packer các mẫu có các biến, thử nghiệm và tích hợp CI/CD. Sử dụng các mẫu này để xây dựng cơ sở hạ tầng có phiên bản, đáng tin cậy image triển khai nhất quán trên các môi trường của bạn.