事象
久々に packer + ansible で AWS の AMI を作成しようとしたら次のようなエラーでコケてしまいました。
fatal: [default]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via scp: bash: /usr/lib/sftp-server: No such file or directory\nscp: Connection closed\r\n", "unreachable": true}
実行環境
Packer を実行したのは python:3.12.4-slim-bookworm
を base image として Packer を追加したコンテナの中です。
Packer は 1.11.0, Ansible は community package 9.6.1 (ansible-core 2.16.7) です。
対処
Packer の ansible provisioner では sftp_command
がデフォルトでは /usr/lib/sftp-server -e
になっているようです。また、接続元の OpenSSH が version 9 以降の場合、scp を実行してもデフォルトでは内部的に sftp が使われるらしいのです。
そこで、この内部的な sftp への切り替えを抑制するために extra_arguments
にそのためのオプションを指定しろという対策が次の Issue にありました。
build {
provisioner "ansible" {
playbook_file = "ansible/playbook.yml"
user = "ec2-user"
extra_arguments = ["--scp-extra-args", "'-O'"]
}
}
👆 こんな感じ。
scp の man page では -O
は次のように書かれています。
Use the legacy SCP protocol for file transfers instead of the SFTP protocol. Forcing the use of the SCP protocol may be necessary for servers that do not implement SFTP, for backwards-compatibility for particular filename wildcard patterns and for expanding paths with a ‘~’ prefix for older SFTP servers.
でも、個人的にこれはなんだか気に入らなかったので別の方法を探してみました。
sftp_command
をサーバー上に存在する path にすれば良いのではないかと /usr/libexec/openssh/sftp-server -e
にしてみましたが、これだけではダメで、use_sftp
を true
とし、scp からの sftp ではなく最初から sftp を使うようにすることで解消されました。
build {
provisioner "ansible" {
playbook_file = "ansible/playbook.yml"
user = "ec2-user"
use_sftp = true
sftp_command = "/usr/libexec/openssh/sftp-server -e"
}
}
Packer の設定ファイルがいつの間にか json から HCL に変わってたり、plugin 機構が導入されていたり Ansible 2.17 からは yum が使えなくなっていたり、しばらく触らない間にいろいろ変わってました。Amazon Linux 2 では dnf が使えないため yum のサポートが消えてしまった最新の Ansible は使えない。