PackerでAMIを作ろうとしたら吐かれたsudoエラーについて

久々にPackerを使ってみて遭遇したエラーについてメモしておく。

環境

動作環境はMac Book AirOSX 10.8 Mountain Lion。Packerはv0.8.6を使用。
AMIにはAmazon Linux AMI 2015.09.1 (HVM), SSD Volume Type - ami-383c1956を選択。

Packerテンプレート

単純にAmazon LinuxのEC2インスタンスsudo yum update -yしたAMIを作るだけのものである。

{
  "variables": {
    "aws_access_key": "",
    "aws_secret_key": ""
  },

  "builders": [{
    "type": "amazon-ebs",
    "access_key": "{{user `aws_access_key`}}",
    "secret_key": "{{user `aws_secret_key`}}",
    "region": "ap-northeast-1",
    "source_ami": "ami-383c1956",
    "instance_type": "t2.micro",
    "ami_name": "wps-web-ami {{timestamp}}",
    "ssh_username": "ec2-user",
    "ssh_timeout": "5m",
    "tags": {
      "Name": "WordPress Server"
    }
  }],

  "provisioners": [{
    "type": "shell",
    "inline": [
      "sudo yum update -y"
    ]
  }]
}

エラーメッセージ

上記のテンプレートでビルドしたら以下の様なメッセージを吐いてコケた。

$ packer build ami.json 
amazon-ebs output will be in this color.

==> amazon-ebs: Prevalidating AMI Name...
==> amazon-ebs: Inspecting the source AMI...
==> amazon-ebs: Creating temporary keypair: packer 5655d9e2-b5e7-8a86-9f64-33936ce5add0
==> amazon-ebs: Creating temporary security group for this instance...
==> amazon-ebs: Authorizing access to port 22 the temporary security group...
==> amazon-ebs: Launching a source AWS instance...
    amazon-ebs: Instance ID: i-ed34aa48
==> amazon-ebs: Waiting for instance (i-ed34aa48) to become ready...
==> amazon-ebs: Waiting for SSH to become available...
==> amazon-ebs: Connected to SSH!
==> amazon-ebs: Provisioning with shell script: /var/folders/_p/5nbnyk0n5x599chrtk9vswqc0000gn/T/packer-shell560434101
    amazon-ebs: sudo: sorry, you must have a tty to run sudo
==> amazon-ebs: Terminating the source AWS instance...
==> amazon-ebs: No AMIs to cleanup
==> amazon-ebs: Deleting temporary security group...
==> amazon-ebs: Deleting temporary keypair...
Build 'amazon-ebs' errored: Script exited with non-zero exit status: 1

==> Some builds didn't complete successfully and had errors:
--> amazon-ebs: Script exited with non-zero exit status: 1

==> Builds finished but no artifacts were created.

原因と解決方法

エラーメッセージの赤く着色した部分が問題なのだが、読んだ通りで仮想端末を使わなければsudoできませんよと言われている。
一年くらい前にPackerで同じ様にAMIを作っていた時には、この設定内容で問題無かったような気がしたのだが、どういうことだろうと思い調べてみたところ、PackerのChangeLogにその答えが書いてあるのを見つけた。

core: SSH connection will no longer request a PTY by default. This can be enabled per builder.

Packerは2015年6月23日にv0.8.0へとアップデートしたのだが、その際、標準ではSSH接続にPTYを要求しなくなったそうだ。要するに、リモートマシンに仮想端末でログインせず、直接コマンドを投げているので、sudoersに外部からのコマンド実行を遮断されている訳である。
この問題を解決するのは簡単で、SSH接続にPTYを要求するよう設定してやれば良い。v0.8.2から追加されたCommunicatorのオプションであるssh_ptytrueを設定し、上記テンプレートのBuilder部分に追記してやると、SSH接続に仮想端末を使うようになるので、Provisionerのsudoコマンドが実行されるようになる。
なお、他の解決方法として、AMI Builderのuser_dataを利用し、sudoersの設定内容を書き換えてしまうということも可能ではあるのだが、当然、セキュリティ的に問題があるのでおすすめはしない。素直にssh_ptyを使った方が手間が無いし安全だろう。