エラーの内容
become: true を指定してプレイブックを実行すると、Ansibleがフリーズします。12秒後に以下のエラーが表示されます:
fatal: [web01]: FAILED! => {
"msg": "Timeout (12s) waiting for privilege escalation prompt: "
}
または短縮版:
Timeout (12s) waiting for privilege escalation prompt
プレイが完全に停止します。SSHは正常に動作しており、タスクは一切実行されません。
原因の解説
become: true は、リモートホスト上で権限昇格を行うようAnsibleに指示します。通常は sudo を使用します。sudoがパスワードを要求するよう設定されているにもかかわらず、Ansibleがパスワードを提供しない場合、12秒のタイムアウトが切れるまでパスワードプロンプトを待ち続けます。
このエラーを引き起こす原因は6つあります。どれに該当するかによって対処法が異なります。
根本原因と対処法
1. becomeパスワードが未指定(最も一般的)
リモートユーザーのsudoにパスワードが必要なのに、Ansibleにパスワードが設定されていません。
簡単な対処法 — 実行時にパスワードを入力する:
ansible-playbook site.yml -i inventory --ask-become-pass
Ansibleが一度パスワードを確認し、実行中のすべてのホストで再利用します。
より良い対処法 — group_varsに保存する:
# inventory/group_vars/all.yml
ansible_become_password: "your_sudo_password_here"
平文パスワードは絶対にコミットしないでください。Ansible Vaultでファイルを暗号化しましょう:
ansible-vault encrypt inventory/group_vars/all.yml
実行時は以下のコマンドを使用します:
ansible-playbook site.yml -i inventory --ask-vault-pass
2. リモートホストでパスワードなしsudoが設定されていない
自動化では通常、パスワードなしのsudoが必要です。各管理対象ホストに専用のsudoersファイルを追加します。/etc/sudoers を直接編集しないでください:
sudo visudo -f /etc/sudoers.d/ansible
以下の行を追加し、deploy を実際のAnsibleユーザーに置き換えます:
deploy ALL=(ALL) NOPASSWD: ALL
より厳密に制御したい場合は、特定のコマンドに限定できます:
deploy ALL=(ALL) NOPASSWD: /usr/bin/apt, /bin/systemctl
Ansibleを触る前に動作確認をしておきましょう:
ssh deploy@web01 sudo whoami
パスワードプロンプトなしで root と表示されれば、Ansibleも正常に動作します。
3. sudoがTTYを要求している(sudoersのrequiretty)
古いRHEL/CentOSには /etc/sudoers に Defaults requiretty が設定されています。AnsibleはデフォルトでTTYを割り当てないため、sudoが拒否します。
以下のコマンドで確認できます:
ssh deploy@web01 "sudo -n whoami" 2>&1
sudo: sorry, you must have a tty to run sudo と表示された場合、これが原因です。
対処法A — Ansibleユーザーのみ requiretty を無効化する:
Defaults:deploy !requiretty
対処法B — Ansibleに疑似TTYを割り当てるよう指示する:
# プレイ単位で設定
- hosts: all
become: true
vars:
ansible_ssh_extra_args: '-tt'
重要な制約として、-tt と pipelining = true は共存できません。どちらか一方を選択してください。
4. パイプラインが有効だがbecomeパスワードが必要
pipelining = true は大規模なインベントリでプレイブックの実行速度を30〜50%向上させますが、インタラクティブなパスワードプロンプトが機能しなくなります。この2つの機能は根本的に互換性がありません。
# ansible.cfg
[ssh_connection]
pipelining = true # ← インタラクティブなbecomeパスワードをブロックする
対処法は、パイプラインを無効にするか、Ansibleがプロンプトを表示しないようパスワードなしsudoを設定するかです。後者がほぼ常に優れた選択です。
5. become_methodが間違っている
Ansibleのデフォルトは sudo です。ホストが su、doas、または pbrun を使用している場合、Ansibleが誤った昇格コマンドを送信し、プロンプトが期待値と一致しません。
# プレイブック
- hosts: bsd_servers
become: true
become_method: doas # ホストが実際に使用している方法に合わせる
グローバルに設定する場合:
[privilege_escalation]
become_method = su
6. 低速なホストに対してタイムアウトが短すぎる
CPU使用率が90%に達しているホストや、大陸間のSSH接続など、高負荷の状況ではsudoの応答に12秒以上かかることがあります。タイムアウトを延長しましょう:
# ansible.cfg
[defaults]
timeout = 30
[privilege_escalation]
become_timeout = 30
プレイ単位での上書き:
- hosts: all
become: true
vars:
ansible_timeout: 30
動作確認
対処後は、以下のワンライナーで最も素早く確認できます:
ansible web01 -i inventory -m command -a "whoami" --become
期待される出力:
web01 | CHANGED | rc=0 >>
root
まだタイムアウトする場合は -vvvv を追加して、どこで止まっているか確認します:
ansible-playbook site.yml -i inventory --become -vvvv 2>&1 | grep -A5 "privilege"
推奨するansible.cfgの設定
この設定により、上記の原因のほとんどを回避できます。リモートホストでパスワードなしsudoを設定すれば完了です:
[defaults]
timeout = 30
host_key_checking = false
[privilege_escalation]
become = true
become_method = sudo
become_user = root
become_ask_pass = false
[ssh_connection]
pipelining = true
# インタラクティブなbecomeパスワードが必要な場合のみパイプラインを無効化
予防策
- ホストをプロビジョニングする際に、Ansibleサービスアカウント用のパスワードなしsudoを設定しておきましょう。後から追加するのは余計な手間がかかります。
- becomeパスワードはAnsible Vaultに保存してください。インベントリファイルに平文の認証情報を記述すると、gitの履歴に残ってしまう可能性があります。
- 新しいホストに対してプレイブックを実行する前に、
ssh deploy@host sudo whoamiを手動で実行して確認しましょう。Ansible外でsudoの問題を把握しておくと、デバッグがはるかに簡単になります。 - チームで
ansible.cfgを共有している場合は、パイプラインの有効・無効とその理由をコメントで説明しましょう。パイプラインとパスワードベースのbecomeを混在させると、ドキュメント化されていないプロジェクトでは必ず混乱が生じます。

