PackerのAnsible Provisioner利用時につまづいたところのメモ

PackerがリモートホストへのAnsible実行に対応しましたね!リリースノート。これまでもAnsible LocalというProvisionerはありましたが、構成管理の対象になるホストにAnsibleがインストールされてしまう問題がありました。今回追加されたAnsible Provisionerでは、そのような問題はありません。

この記事はAnsible ProvisionerでAMIを作成しようとした時につまづいたところのメモです。基本的な使い方を知りたい場合は、こちらの記事が参考になると思います。

次の環境で試しました。

  • Ansible 2.0.0.2
  • Packer 0.9.0
  • ベースにするAMI Ubuntu 14.04

SSHに失敗する1

最初は、次のようなSSHエラーでつまづきました。

amazon-ebs: PLAY ***************************************************************************
amazon-ebs:
amazon-ebs: TASK [setup] *******************************************************************
amazon-ebs: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ERROR! SSH encountered an unknown error during the connection. We recommend you re-run the command using -vvvv, which will enable SSH debugging output to help diagnose the issue", "unreachable": true}
amazon-ebs:
amazon-ebs: PLAY RECAP *********************************************************************
amazon-ebs: default                    : ok=0    changed=0    unreachable=1    failed=0

-vvvvオプションを付けろとのことです。 Ansible Provisionerに次のパラメータを渡します。

"extra_arguments" : "-vvvv"

結果は次のようになりました。ディレクトリ名は一部書き換えてます。

amazon-ebs: PLAY ***************************************************************************
amazon-ebs:
amazon-ebs: TASK [setup] *******************************************************************
amazon-ebs: <127.0.0.1> ESTABLISH SSH CONNECTION FOR USER: packer-ansible
amazon-ebs: <127.0.0.1> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=57406 -o 'IdentityFile="/var/folders/9_/qdkghd2x2q5bw2hxyv1f0n7h0000gn/T/ansible-key551882343"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=packer-ansible -o ConnectTimeout=10 -o 'ControlPath=/Users/yagami/src/XXX/$HOME/.ansible/cp/ansible-ssh-%h-%p-%r' -tt 127.0.0.1 '( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1456648870.02-189603518951689 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1456648870.02-189603518951689 )" )'
amazon-ebs: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ERROR! SSH encountered an unknown error. The output was:\nOpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011\ndebug1: Reading configuration data /Users/yagami/.ssh/config\r\ndebug1: Reading configuration data /etc/ssh_config\r\ndebug1: /etc/ssh_config line 20: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\nControlPath too long\r\n", "unreachable": true}
amazon-ebs:
amazon-ebs: PLAY RECAP *********************************************************************
amazon-ebs: default                    : ok=0    changed=0    unreachable=1    failed=0

ControlPath too longと言われてます。Ansible provisionerはSSH接続を共有して実行を高速化しているようです。このとき、接続の共有につかうUnixドメインソケットのパス名に108文字の上限があり、その上限に引っかかっているようです。

この問題はAnsibleのドキュメントにも書かれていて、control_path設定を変更すればいいようです。Ansible Provisionerに次のパラメータを渡します。

"ansible_env_vars": [ "ANSIBLE_HOST_KEY_CHECKING=False", "ANSIBLE_CONTROL_PATH=%(directory)s/%%h-%%r" ]

ANSIBLE_HOST_KEY_CHECKING=Falseansible_env_varsのデフォルト値なので、一緒に付けておきます。

amazon-ebs: PLAY ***************************************************************************
amazon-ebs:
amazon-ebs: TASK [setup] *******************************************************************
amazon-ebs: <127.0.0.1> ESTABLISH SSH CONNECTION FOR USER: packer-ansible
amazon-ebs: <127.0.0.1> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=58075 -o 'IdentityFile="/var/folders/9_/qdkg
hd2x2q5bw2hxyv1f0n7h0000gn/T/ansible-key173226644"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o Passwor
dAuthentication=no -o User=packer-ansible -o ConnectTimeout=10 -o ControlPath=/Users/yagami/.ansible/cp/ansible-ssh-%h-%p-%r -tt 127.0.0.1 '( umask 22 && mkdir -p "$( echo $H
OME/.ansible/tmp/ansible-tmp-1456650315.25-37408588369242 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1456650315.25-37408588369242 )" )'
amazon-ebs: SSH proxy: accepted connection

無事にSSH接続できたようです。

SSHに失敗する2

こちらの失敗をする人はあまりいないと思うのですが、一度つまづくと問題を見つけるのがなかなか大変な気がするので、残しておきます。

Ansibleはタスクを実行するとき、SFTPでモジュールを転送します。その転送がなぜか失敗する問題がありました。

次のようなエラーです。

amazon-ebs: PLAY ***************************************************************************
amazon-ebs:
amazon-ebs: TASK [setup] *******************************************************************
amazon-ebs: <127.0.0.1> ESTABLISH SSH CONNECTION FOR USER: packer-ansible
amazon-ebs: <127.0.0.1> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=58241 -o 'IdentityFile="/var/folders/9_/qdkghd2x2q5bw2hxyv1f0n7h0000gn/T/ansible-key726237014"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=packer-ansible -o ConnectTimeout=10 -o ControlPath=/Users/yagami/.ansible/cp/ansible-ssh-%h-%p-%r -tt 127.0.0.1 '( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1456650679.34-272153885545980 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1456650679.34-272153885545980 )" )'
amazon-ebs: SSH proxy: accepted connection
==> amazon-ebs: authentication attempt from 127.0.0.1:58242 to 127.0.0.1:58241 as packer-ansible using none
==> amazon-ebs: authentication attempt from 127.0.0.1:58242 to 127.0.0.1:58241 as packer-ansible using publickey
amazon-ebs: <127.0.0.1> PUT /var/folders/9_/qdkghd2x2q5bw2hxyv1f0n7h0000gn/T/tmp3kAuoj TO /home/ubuntu/.ansible/tmp/ansible-tmp-1456650679.34-272153885545980/setup
amazon-ebs: <127.0.0.1> SSH: EXEC sftp -b - -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=58241 -o 'IdentityFile="/var/folders/9_/qdkghd2x2q5bw2hxyv1f0n7h0000gn/T/ansible-key726237014"' -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=packer-ansible -o ConnectTimeout=10 -o ControlPath=/Users/yagami/.ansible/cp/ansible-ssh-%h-%p-%r '[127.0.0.1]'
==> amazon-ebs: starting sftp subsystem
amazon-ebs: fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "ERROR! SSH Error: data could not be sent to the remote host. Make sure this host can be reached over ssh", "unreachable": true}
amazon-ebs:
amazon-ebs: PLAY RECAP *********************************************************************
amazon-ebs: default                    : ok=0    changed=0    unreachable=1    failed=0

あまり参考にならないエラーメッセージですね。。

かなりハマった末に、Packerに渡すjsonファイルを一行ずつ消してみる、という方法を試したところ、amazon-ebs builderに渡している次のパラメータが問題になっていました。

"ssh_pty": true

以前、Shell Provisionerを使っていたAmazon Linuxを使っていた時の名残のコードです。この行を消すと、問題なく動きました。。。

まとめ

Ansible Provisionerを使った時につまづいたところのメモでした。お役に立てば幸いです。間違い等ありましたらコメントお願いします。