サーバーの手動構築はやめよう:HashiCorp Packerによるゴールデンイメージ作成ガイド

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

午前2時の呼び出し:なぜ手動でのイメージ作成は失敗するのか

ページャーが鳴り響いたのは午前2時14分でした。オートスケーリンググループ内の重要な本番インスタンスが故障したのです。通常、これは大した問題ではありませんが、代替インスタンスが「ブートストラップ(起動処理)」のループに陥ってしまいました。原因は?libssl-devのサードパーティミラーがダウンしており、user-dataスクリプトがセキュリティパッチのインストールを完了できなかったのです。サービスを復旧させるためだけに、新しいOSに手動でパッチを当てるのに180分も費やすことになりました。

その夜、私は手痛い教訓を学びました。**実行時のブートストラップは大きなギャンブルである**ということです。スケールアウト時にapt-get installyum installに頼ることは、いつか必ず失敗する外部依存関係を導入することになります。ここで登場するのが「ゴールデンイメージ」です。依存関係、セキュリティパッチ、設定をあらかじめ1つのアーティファクトに「ベイク(焼き込み)」しておくことで、インフラの予測可能性を確保し、数秒でのスケーリングを可能にします。

実践において、これは現代のエンジニアリングに不可欠なスキルです。手動のスナップショットから自動パイプラインへ移行することは、ストレスを抱えたシステム管理者と、プロアクティブなDevOpsエンジニアの分かれ道となります。

イミュータブルなパイプラインのアーキテクチャ

Packerは、一時的な仮想マシン(「ビルダー」)を起動し、設定スクリプト(「プロビジョナー」)を実行し、VMをシャットダウンして再利用可能なイメージ(「アーティファクト」)として保存するという仕組みで動作します。

HCL(HashiCorp Configuration Language)を書き始める前に、レガシーな設定をクリーンアップする必要があることがよくあります。古いプロジェクトを移植する場合、YAML ↔ JSON コンバーターは、フォーマットを最新のHCL2構文に変換する際の大きな時間の節約になります。ブラウザ上で完全に動作するため、機密性の高いインフラロジックがマシン外に出る心配もありません。

Packerのインストール

Packerは単一のバイナリです。Linuxのコントロールノードでは、公式リポジトリ経由で1分以内にインストールが完了します:

curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
sudo apt-get update && sudo apt-get install packer

セットアップが正しく行われたか、バージョンを確認します:

packer version

初めてのゴールデンイメージを設定する

AWS(クラウド)とProxmox(オンプレミスの仮想化)という2つの標準的なユースケースを見てみましょう。現代のPackerは.pkr.hclファイルを使用します。これは古いJSON形式よりも格段に読みやすく、メンテナンスも容易です。

1. AWS AMIの構築

AmazonEC2FullAccess(または特定のAMI作成権限)を持つIAMユーザーが必要です。このテンプレートは、堅牢化されたUbuntu 22.04イメージを約8分で構築します。

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

source "amazon-ebs" "ubuntu-golden-image" {
  ami_name      = "golden-ubuntu-{{timestamp}}"
  instance_type = "t3.micro"
  region        = "us-east-1"
  source_ami_filter {
    filters = {
      name                = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners      = ["099720109477"] # Canonical社
  }
  ssh_username = "ubuntu"
}

build {
  name = "production-builder"
  sources = ["source.amazon-ebs.ubuntu-golden-image"]

  provisioner "shell" {
    inline = [
      "sudo apt-get update",
      "sudo apt-get upgrade -y",
      "sudo apt-get install -y docker.io nginx",
      "sudo systemctl enable nginx"
    ]
  }
}

2. Proxmoxテンプレートの構築

Proxmoxはオンプレミス環境における定番の選択肢です。ここでのテンプレート構築には、ISOファイルとAPIアクセスが必要です。これらのビルド用のネットワークを設定する際、私はIPサブネット計算機を使用して、ビルドブリッジ専用の範囲を割り当てています。これにより、一時的なビルド用VMが本番環境のVLANからIPを奪ってしまうのを防ぐことができます。

source "proxmox-iso" "proxmox-ubuntu" {
  proxmox_url = "https://192.168.1.10:8006/api2/json"
  username    = "root@pam"
  password    = "あなたのパスワード"
  node        = "pve-node-01"
  iso_file    = "local:iso/ubuntu-22.04-live-server-amd64.iso"
  
  ssh_username = "admin"
  ssh_password = "安全なパスワード"
  
  network_adapters {
    model  = "virtio"
    bridge = "vmbr0"
  }
}

検証とモニタリング

イメージを生成するのは始まりに過ぎません。本番環境に投入する前に、正しく動作することを確認する必要があります。私は以下の3ステップの検証プロセスに従っています:

  1. バリデーション: packer validate . を実行して構文エラーを検出します。複雑なネストされた変数を扱う場合、JSONフォーマッターを使用すると、括弧の閉じ忘れや不正な構造を即座に特定できます。
  2. インスペクション: packer inspect . を使用して、どの変数とビルダーがアクティブであるかを再確認します。
  3. 自動テスト: PackerをGitHub ActionsやGitLab CIに統合します。gossinspecによる基本的なテストに合格した場合のみ、AMIに「Production-Ready(本番対応)」のタグを付けます。

provisionerブロック内のシェルスクリプトのデバッグ、特にsedコマンドの複雑な正規表現などは面倒な作業になりがちです。私は12分かかるビルドを開始する前に、正規表現テスターを使用してパターンを検証しています。正規表現のタイポを見つけるためだけにビルドのフルサイクルを待つのは、生産性を大きく損なうからです。

最後に

マシンイメージの自動化は、サーバーに数ヶ月かけて手動でパッチを当てる際に発生する「設定のドリフト(乖離)」を排除します。ゴールデンイメージから起動されたすべてのインスタンスは、直前のものと全く同じクローンです。これにより、トラブルシューティングが大幅に容易になります。

もし、いまだにAWSコンソールをクリックしてAMIを作成しているなら、まずはスモールスタートから始めましょう。最も一般的なOSセットアップをPackerのHCLファイルに移行し、最初のビルドを実行してみてください。次にインシデントが発生し、インフラが数時間ではなく数秒で復旧したとき、午前2時のあなたは自分自身に感謝することでしょう。

Share: