読者です 読者をやめる 読者になる 読者になる

絶品ゆどうふのタレ

ふと気づいたことを綴るだけのメモ

Ubuntu 12.04 LTS のinstance-store AMIをpackerで使おうとしたらハマった話

ubuntu ami aws ec2 packer

誰得。

とはいえ、ubuntuのAMI全般で問題出る場合もある箇所も有るので、ブログにしとく。ほぼ個人メモ。

なお、packerのバージョンはv0.7.2

経緯

お仕事でUbuntu 12.04 LTSのAMIイメージをカスタムする必要があったので、packerを使ってゴールデンイメージを作ることにした。 しかし、あちこち細かい所でハマってしまって苦労したのでメモ。

利用したbase AMI

Ubuntu公式で配布しているAMIを利用。 今回は、instance-storeのAMIを利用したが、これは完全に趣味・・・これもハマる一因だったかもね。

普通に、ドキュメントの項目に従ってjsonを書いて実行してみたところ、ポロポロとエラーに遭遇。

ec2-bundle-vol: command not found

調べてみると、サーバ内にec2-ami-toolsが存在しなかった。

Ubuntuから標準で提供されるAMIなのになんで?という気持ちになりつつ、対応。 12.04のパッケージリポジトリにはそのままだと無いので、sources.listを書き換えてインストールするようにprovisionersを記述する。

  "provisioners": [{   
    "type": "shell",
    "inline": [
      "sudo sed -i.dist 's,universe$,universe multiverse,' /etc/apt/sources.list",
      "sudo apt-get update",
      "sudo apt-get install -y ec2-ami-tools"
    ]   
  }]

として、インストール完了。直ったーと思ったら。。。

E: Unable to locate package ec2-ami-tools

手動や-debug付きでステップ実行だとうまくいくのに、普通に実行するとinstallで失敗。 調べてみたところ、置き換え対象のsources.listsed実行時に存在しないことが問題だった。

このファイルはリージョン情報が書き込まれるため、都度生成されているようだった。 起動後のprovisonsersの実行が早すぎたため、まだsources.listがないうちにsedが走ってしまい、結果として正しく変更が適用できなかった。

そのため、sedの前にsleep 3を入れて解消。嬉しくないが。

が。。。

invalid option: --no-filter

今度は、次のステップでec2-bundle-volがこのエラーを吐く。 これは、リポジトリにあるec2-ami-toolsが通常と異なる(詳しくは調べていないが、バージョン違い?)ようで、--no-filterオプションがないためだった。

このコマンドを標準と差し替えるために、buildersの項にbundle_vol_commandを設定。 packerドキュメントBundle Volume Commandをベースに。

  "builders": [{
    ...

    "bundle_vol_command": "sudo -n ec2-bundle-vol -k {{.KeyPath}} -u {{.AccountId}} -c {{.CertPath}} -r {{.Architecture}} -e {{.PrivatePath}}/* -d {{.Destination}} -p {{.Prefix}} --batch",
    ...

invalid option: --region

で、さらにec2-upload-bundleのエラー。これもさっきと同じ理由。 --regionオプションではなく、代わりに--locationという名前のオプションがあるので、これに変更。

やはりドキュメントのBundle Upload Commandの項を参考に、bundle_upload_commandを追加。

  "builders": [{
    ...

    "bundle_upload_command": "sudo -n ec2-upload-bundle -b {{.BucketName}} -m {{.ManifestPath}} -a {{.AccessKey}} -s {{.SecretKey}} -d {{.BundleDirectory}} --batch --location {{.Region}} --retry"
    ...

最終的に出来たもの

このへんまでやっつけてできるようになった。 というわけで、Ubuntu 12.04 LTS ベースのinstance_storeのAMIを作成するpacker用jsonが出来ましたとさ。

{
  "variables": {
    "aws_access_key": "",
    "aws_secret_key": "",
    "aws_account_id": "",
    "my_source_ami": "ami-8d9cb48c",
    "ami_s3_bucket": "",
    "cert_path": "",
    "key_path": ""
  },  
  "builders": [{
    "type": "amazon-instance",
    "access_key": "{{user `aws_access_key`}}",
    "secret_key": "{{user `aws_secret_key`}}",
    "account_id": "{{user `aws_account_id`}}",
    "region": "ap-northeast-1",
    "s3_bucket": "{{user `ami_s3_bucket`}}/{{timestamp}}",
    "source_ami": "{{user `my_source_ami`}}",
    "instance_type": "m3.medium",
    "ssh_username": "ubuntu",
    "ami_name": "packer-ubuntu-precise {{timestamp}}",
    "x509_cert_path": "{{user `cert_path`}}",
    "x509_key_path": "{{user `key_path`}}",
    "bundle_vol_command": "sudo -n ec2-bundle-vol -k {{.KeyPath}} -u {{.AccountId}} -c {{.CertPath}} -r {{.Architecture}} -e {{.PrivatePath}}/* -d {{.Destination}} -p {{.Prefix}} --batch",
    "bundle_upload_command": "sudo -n ec2-upload-bundle -b {{.BucketName}} -m {{.ManifestPath}} -a {{.AccessKey}} -s {{.SecretKey}} -d {{.BundleDirectory}} --batch --location {{.Region}} --retry"
  }], 
  "provisioners": [
    {   
      "type": "shell",
      "inline": [
        "sleep 3",
        "sudo sed -i.dist 's,universe$,universe multiverse,' /etc/apt/sources.list",
        "sudo apt-get update",
        "sudo apt-get install -y ec2-ami-tools"
      ]   
    }   
  ]
}