ujunのブログ

PackerでAMIを作ると流れるようにできるしChefの確認も流れるようにできた

HashiCorpのPackerの使い勝手の良さはすごくいい。

AWS環境でしか使っていないが、とても手軽にAMIをbakeできる。(bakeという単語を公式で使っていた)。 特に、Windows機のAMIをbakeするのに威力を発揮してくれた。

そもそも、Windowsに限らずだが、後のインスタンス構築の手間を省く目的でpre-bakedなAMIを作るとき、 本当にとっかかりの段階ではだいたい以下のようなサイクルを手元で回したくなるはずである(自分だけ?)。

Chefなどのプロビジョニングツールのレシピを書く
↓
( Chef Serverにレシピをupload ) 
↓
EC2インスタンス再作成して適用 
↓
失敗。。。調査。。
↓
Chefなどのプロビジョニングツールのレシピを書く
↓
( Chef Serverにレシピをupload ) 
↓
EC2インスタンス再作成して適用 
↓
失敗。。。調査。。
↓
・・・
・・・
↓
成功
↓
AMI化して完了

この時、Windowsだと圧倒的に困るのが、とにかくterminate/startが遅いことで、インスタンス再作成だけで数分とか数十分とか必要なことも。 せめて、terminateくらいは素早くやらせてほしい。

すばやく環境を構築/破棄するという観点では、Terraformを使っていると環境の構築/破棄がコマンド1つでとても簡単に行えるが、それでもapplyとdestroyを繰り返すのは、ずっと続けているとなんかアホらしくなってくる。

あと、applyしている途中で誤りに気づいてCtrl-cとかしたくても怖くてできない。 だいたい、applyのログ追ってれば、こりゃダメだって途中で気づくことも経験上よくある。しかし、Ctrl-cしたくてもterraformだと少し怖いし変にリソースが残るのが嫌なので、それはできない。

Packerだとこうだ。

簡単なtemplate(example.json)を用意する。

{
  "variables":{
    "home": "{{env `HOME`}}"
  },
  "builders": [
    {
      "type": "amazon-ebs",
      "region": "ap-northeast-1",
      "access_key": "{{user `aws_access_key`}}",
      "secret_key": "{{user `aws_secret_key`}}",
      "source_ami": "ami-d34f47b4",
      "instance_type": "t2.small",
      "ami_name": "hoge {{timestamp}}",
      "communicator": "winrm",
      "winrm_username": "Administrator"
    }
  ],
  "provisioners": [
    {
      "guest_os_type": "windows",
      "type": "chef-client",
      "server_url": "https://chef-server",
      "chef_environment": "production",
      "run_list": "recipe[example]",
      "encrypted_data_bag_secret_path": "/path/to/secret",
      "validation_client_name": "client",
      "validation_key_path": "/path/to/key"
    },
    {
      "type": "powershell",
      "inline": [
        "C:\\PROGRA~1\\Amazon\\Ec2ConfigService\\Ec2Config.exe -sysprep"
      ]
    }
  ]
}

これで、 packer build example.json を実行する。

Packer Builderというなぞのインスタンスがおもむろに立ち上がり、それに対しprovisionerが適用されていく。

よくあることだが作成途中にダメだと気づいたら、Ctrl-cすれば以下のようにちゃんと後始末してくれる。そしたらレシピを修正するなりpackerのログを見るなりして、またbuildすればよい。

・・・
^C==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: Cleaning up any extra volumes...
==> amazon-ebs: No volumes to clean up, skipping
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' finished.
Cleanly cancelled builds after being interrupted.

terraformとの些細な違いは、自分でdestroyしなくて済むということだが、試行錯誤してる時には、これが体感として非常に利いてくる気がしている。 なんというか、カジュアルさが違う。terraformのように重おもしくない。

さらに、packerには、このように環境構築に対する圧倒的カジュアルさのほかに、非常に便利な機能がある。 それが、ステップ実行である。

packer build -debug example.json だけでそれは起動する。

まさにコードをデバッグするときのあの挙動そのままであり、breakpointは打てないが、各種provisionerとかoptionとかの実行直前でbreakしてくれて、 プロンプトが返るようになっている。

break中に例えば対象のインスタンスssh/rdpして中を確認したりできる。あたかも、コード実行中にデバッガで特定の変数の値を確認しているかのよう。 ターミナルに戻ってEnterすれば後続の処理がされていく。

ちなみにこの時点でCtrl-cしても、やはり先ほど同様後始末して終わってくれる。使いやすさ。

このように、Packerには、個別のインスタンスを作ってプロビジョニングして壊すのに最適な機能がたくさんあることに最近気づいた。

いままで考えもしなかったけど、 Packerは手元でのユニットテストに、TerraformはbakeしたAMIやその他クラウドリソース等の結合テストにというように、テスト工程に無理やりマッピングすると意外としっくりくるように思う。

そう考えると、それぞれにそれぞれの役割の機能がちゃんと備わっているように見えてきた。

すごいぜ、HashiCorp。

しかし、軽くググっても、Chef Server、しかもPackerとかTerraform + Cher Serverという例が全然ないよな。 そもそもChef Serverって世の中的に使われてるのかな。。