Tự động hóa pipeline Golden Image đa đám mây với HashiCorp Packer: Chuẩn hóa máy chủ trong CI/CD

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Các phương pháp khởi tạo máy chủ: Bake vs. Fry

Khi khởi chạy máy ảo trên AWS, Azure hoặc các nền tảng hypervisor on-premise, các đội ngũ platform thường lựa chọn giữa hai quy trình: Khởi tạo tức thì (“Fry”) và Đóng gói sẵn Image (“Bake”).

Mô hình “Fry” bắt đầu từ một image hệ điều hành nguyên bản (vanilla OS) như Ubuntu 22.04 LTS hoặc Amazon Linux 2023. Tại thời điểm boot máy, các công cụ như cloud-init, Ansible hoặc Chef sẽ chạy tuần tự.

Chúng tiến hành cài đặt package, tải binary ứng dụng, cấu hình monitoring agent và áp dụng các baseline bảo mật. Dù mô hình này giúp giảm thiểu dung lượng lưu trữ image, nó lại biến quá trình boot instance thành một điểm nghẽn dễ gãy đổ. Chỉ cần một lỗi tạm thời như timeout mirror apt hay chạm ngưỡng GitHub rate limit cũng có thể làm gián đoạn đợt autoscaling ngay giữa đợt tăng vọt lưu lượng truy cập tối thứ Sáu.

Mô hình “Bake” giải quyết triệt để vấn đề này với HashiCorp Packer. Toàn bộ bản vá OS, tinh chỉnh kernel, runtime và log agent đều được “nướng” (bake) trực tiếp vào một snapshot bất biến trước khi triển khai. Khi Auto Scaling Group (ASG) yêu cầu khởi tạo thêm 20 instance mới, mỗi VM chỉ mất chưa đầy 45 giây để boot xong vì mọi dependency đã nằm sẵn trên ổ đĩa.

Ưu và nhược điểm khi xây dựng Golden Image với Packer

Xem VM image như các build artifact đem lại cả lợi ích lẫn những đánh đổi rõ rệt cần lưu ý:

Ưu điểm

  • Autoscaling siêu nhanh và ổn định: Việc biên dịch sẵn runtime giúp rút ngắn thời gian khởi chạy VM từ 15–20 phút thiết lập xuống chỉ còn 35–50 giây.
  • Loại bỏ Configuration Drift: Kỹ sư không thể chỉnh sửa chắp vá môi trường production qua SSH một cách tùy tiện. Nếu cần cập nhật agent, bạn chỉ việc phát hành phiên bản image mới.
  • Template đa đám mây thống nhất: Với Packer HCL2, một file cấu hình dùng chung có thể tạo ra AWS AMI, Azure Managed Image và GCP disk image trong cùng một lần chạy CI duy nhất.
  • Bảo mật theo hướng Shift-Left: Các công cụ quét lỗ hổng như Trivy hoặc OpenSCAP sẽ kiểm tra snapshot image ngay trong build pipeline trước khi bất kỳ workload nào chạm tới môi trường production.

Nhược điểm cần cân nhắc

  • Chi phí lưu trữ image tăng nhanh: Việc lưu giữ các EBS snapshot không được dọn dẹp trên 5 AWS region với giá 0,05 USD/GB mỗi tháng sẽ đội chi phí lên rất nhanh. Bạn cần thiết lập lifecycle policy tự động để hủy đăng ký các AMI đã lỗi thời.
  • Chi phí thời gian cho pipeline: Dù instance khởi động gần như tức thì, quá trình build CI ban đầu sẽ mất từ 8 đến 15 phút để khởi chạy VM builder, thực thi provisioner, ghi snapshot và dọn dẹp tài nguyên.

Kiến trúc đề xuất: Packer HCL2 & CI/CD

Hãy tránh sử dụng các JSON template đã lỗi thời và chuyển hoàn toàn sang cú pháp HCL2 hiện đại của Packer. Hãy tổ chức repository của bạn thành các builder module hóa và các provisioner bằng bash script độc lập:

packer-golden-images/
├── .github/
│   └── workflows/
│       └── build-ami.yml
├── config/
│   ├── common-variables.pkrvars.hcl
│   └── security-baseline.sh
├── scripts/
│   └── install-telemetry.sh
└── templates/
    └── ubuntu-base.pkr.hcl

Việc xây dựng pipeline kiểm thử trong CI/CD thường bao gồm các tác vụ lặp đi lặp lại như kiểm tra checksum của binary, chuyển đổi manifest và tính toán kích thước subnet cho VPC build. Tôi thường sử dụng ToolCraft để thực hiện nhanh các bước kiểm tra này. Vì các tiện ích của nó chạy hoàn toàn ở phía client ngay trên trình duyệt, thông tin cấu hình mạng nội bộ và key riêng tư không bao giờ bị gửi lên máy chủ bên ngoài.

Trước khi chạy lệnh curl để tải một binary của bên thứ ba vào template, tôi dán chuỗi release của nhà cung cấp vào Hash Generator để xác minh mã SHA-256 ngay lập tức. Khi chuyển đổi các cấu hình Packer JSON cũ sang block HCL hiện đại, công cụ YAML ↔ JSON Converter giúp việc làm sạch cú pháp nhanh hơn đáng kể. Tương tự, việc tính toán subnet cho builder mà không bị trùng lặp với các dải CIDR của doanh nghiệp cũng trở nên dễ dàng nhờ Subnet Calculator.

Hướng dẫn triển khai từng bước

Dưới đây là thiết lập hoàn chỉnh từ đầu đến cuối giúp đóng gói một AMI Ubuntu 22.04 LTS trên AWS và tích hợp trực tiếp với GitHub Actions.

1. Định nghĩa Packer Template (`ubuntu-base.pkr.hcl`)

Template này cố định phiên bản AWS plugin, truy vấn registry AMI chính thức của Canonical và dọn sạch dữ liệu định danh riêng của instance trước khi tạo snapshot:

packer {
  required_plugins {
    amazon = {
      version = ">= 1.2.8"
      source  = "github.com/hashicorp/amazon"
    }
  }
}

variable "aws_region" {
  type    = string
  default = "us-east-1"
}

variable "environment" {
  type    = string
  default = "production"
}

data "amazon-ami" "ubuntu_lts" {
  filters = {
    name                = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
    root-device-type    = "ebs"
    virtualization-type = "hvm"
  }
  most_recent = true
  owners      = ["099720109477"] # ID tài khoản chính thức của Canonical
}

source "amazon-ebs" "base_linux" {
  ami_name      = "golden-linux-${var.environment}-{{timestamp}}"
  instance_type = "t3.micro"
  region        = var.aws_region
  source_ami    = data.amazon-ami.ubuntu_lts.id
  ssh_username  = "ubuntu"

  tags = {
    Name        = "Golden-Linux-Image"
    Environment = var.environment
    BuiltBy     = "Packer-CI"
  }
}

build {
  name    = "hardened-ubuntu"
  sources = ["source.amazon-ebs.base_linux"]

  # 1. Cập nhật các package của hệ điều hành và cài đặt các tiện ích bảo mật cốt lõi
  provisioner "shell" {
    inline = [
      "export DEBIAN_FRONTEND=noninteractive",
      "sudo apt-get update -y",
      "sudo apt-get upgrade -y",
      "sudo apt-get install -y fail2ban curl jq unattended-upgrades ufw"
    ]
  }

  # 2. Chạy script cài đặt telemetry và cấu hình bảo mật daemon
  provisioner "shell" {
    script = "./scripts/install-telemetry.sh"
  }

  # 3. Dọn dẹp build artifact và reset machine-id để tránh xung đột định danh khi nhân bản host
  provisioner "shell" {
    inline = [
      "sudo truncate -s 0 /etc/machine-id",
      "sudo rm -f /var/lib/dbus/machine-id",
      "sudo apt-get clean",
      "sudo rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*"
    ]
  }
}

2. Thêm script cấu hình bảo mật và telemetry

Lưu script này tại scripts/install-telemetry.sh. Script sẽ cài đặt Prometheus Node Exporter v1.7.0, đồng thời vô hiệu hóa đăng nhập SSH root và xác thực bằng mật khẩu:

#!/usr/bin/env bash
set -euo pipefail

echo "Đang cài đặt Prometheus Node Exporter..."
NODE_EXPORTER_VERSION="1.7.0"
curl -fsSL "https://github.com/prometheus/node_exporter/releases/download/v${NODE_EXPORTER_VERSION}/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64.tar.gz" \
  -o /tmp/node_exporter.tar.gz

tar -xzf /tmp/node_exporter.tar.gz -C /tmp/
sudo mv "/tmp/node_exporter-${NODE_EXPORTER_VERSION}.linux-amd64/node_exporter" /usr/local/bin/
rm -rf /tmp/node_exporter*

sudo useradd --system --no-create-home --shell /bin/false node_exporter 2>/dev/null || true

echo "Đang cấu hình bảo mật SSH daemon..."
sudo mkdir -p /etc/ssh/sshd_config.d
cat <<'EOF' | sudo tee /etc/ssh/sshd_config.d/99-golden-hardening.conf
PermitRootLogin no
PasswordAuthentication no
X11Forwarding no
MaxAuthTries 3
EOF

sudo chmod 600 /etc/ssh/sshd_config.d/99-golden-hardening.conf
echo "Hoàn tất cấu hình bảo mật."

3. Tự động hóa quá trình build với GitHub Actions

Kích hoạt build mỗi khi có push lên nhánh main hoặc chạy theo lịch cron hàng tuần để cập nhật các bản vá bảo mật mới nhất của hệ điều hành:

name: Build Golden AMI

on:
  push:
    branches:
      - main
    paths:
      - 'templates/**'
      - 'scripts/**'
  schedule:
    - cron: '0 3 * * 0' # Chạy định kỳ hàng tuần vào 03:00 UTC Chủ Nhật
  workflow_dispatch:

jobs:
  packer-build:
    name: Chạy xác thực & Build với Packer
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read

    steps:
      - name: Checkout mã nguồn
        uses: actions/checkout@v4

      - name: Thiết lập HashiCorp Packer
        uses: hashicorp/setup-packer@main
        with:
          version: "1.10.0"

      - name: Cấu hình thông tin xác thực AWS (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/packer-build-role
          aws-region: us-east-1

      - name: Khởi tạo các Packer plugin
        run: packer init templates/ubuntu-base.pkr.hcl

      - name: Kiểm tra cú pháp
        run: packer validate templates/ubuntu-base.pkr.hcl

      - name: Build AMI
        run: packer build -color=false templates/ubuntu-base.pkr.hcl

4. Sử dụng Golden Image trong Terraform hoặc OpenTofu

Trỏ cấu hình IaC của bạn đến image đã qua kiểm định mới nhất bằng cách dùng bộ lọc data source của AWS provider:

data "aws_ami" "latest_golden_image" {
  most_recent = true
  owners      = ["self"]

  filter {
    name   = "name"
    values = ["golden-linux-production-*"]
  }

  filter {
    name   = "tag:BuiltBy"
    values = ["Packer-CI"]
  }
}

Tự động hóa việc tạo base image giúp chuyển đổi quy trình khởi tạo VM từ một điểm nghẽn khó lường thành một tác vụ ổn định chỉ mất khoảng 40 giây. Khi kết hợp việc build lại image hàng tuần với quy trình kiểm thử lỗ hổng tự động trong CI, toàn bộ hệ thống máy chủ cloud của bạn sẽ luôn được vá lỗi kịp thời mà không làm gián đoạn các workload đang hoạt động.

Share: