問題点
SSHキーやsudo権限を再確認したにもかかわらず、Ansibleプレイブックが即座にクラッシュすることがあります。エラーメッセージは明快です:sudo: sorry, you must have a tty to run sudo。これはコードのバグではありません。リモートホスト側のセキュリティゲートキーパーが、非対話型の自動化処理をブロックしているのです。
これは通常、レガシーなRed Hat環境(RHEL 6やCentOS 6)を管理しているときに発生します。また、実際の対話型ターミナルセッションなしでのsudo実行を禁止するポリシーを持つ、高度にセキュリティ保護されたクラスターでも発生します。
TL;DR: クイックフィックス
最も確実な解決策は、対象サーバーのrequiretty設定を無効にすることです。リモートマシンにログインし、visudoを実行して、以下の行をコメントアウトしてください。
# Defaults requiretty
サーバーのセキュリティポリシーを変更できない場合は、ローカルのansible.cfgでSSH Pipeliningを有効にして、コマンドのストリーミング方法を変更してみてください。
[ssh_connection]
pipelining = True
詳細な原因
Linuxカーネルは対話型セッションに擬似端末(PTY)を使用します。歴史的に、RHEL 5や6のようなディストリビューションでは、/etc/sudoersファイルでDefaults requirettyが有効な状態で出荷されていました。この設定により、ユーザーが物理的または仮想的にターミナルで「タイプ」している場合にのみsudoが機能するようになります。
Ansibleは速度を優先します。デフォルトでは、PTYを割り当てずにSSH経由でストリーミングすることでモジュールを実行します。これにより自動化は高速化されますが、セキュリティチェックに引っかかります。Ansibleがbecome: yesを試行した際、リモートシステムはTTYの代わりに対話型ではないストリームを検出し、即座にプロセスを強制終了します。
現代のセキュリティ基準では、一般的にrequirettyのセキュリティ上の価値は低いと考えられています。その結果、Ubuntu、Debian、RHEL 7+などの最新のディストリビューションの多くでは、この制限は完全に削除されています。
解決策1: Sudoersファイルの修正(推奨)
根本的な原因に対処するのが最もクリーンな方法です。visudoツールを使用して、この変更を安全に適用する方法は2つあります。
1. グローバルに無効化する
対象マシンでsudo visudoを実行します。requirettyの行を見つけ、先頭に#文字を付けます。
# この行を見つける:
Defaults requiretty
# 以下のように変更する:
# Defaults requiretty
2. Ansibleユーザーに対してのみ無効化する
他のユーザーに対するポリシーは維持しつつ、自動化アカウント(例:ansible_user)のみを除外したい場合もあります。その場合は、ファイルの末尾に以下の特定のルールを追加してください。
Defaults:ansible_user !requiretty
解決策2: SSH Pipeliningの有効化
500台以上のレガシーサーバーを管理している場合、手動での編集は現実的ではありません。pipeliningを有効にすると、モジュールの実行に必要なSSH操作の回数が削減されます。これにより、コマンドのペイロードがリモートシェルに配信される方法が変わり、TTY要件をバイパスできることがよくあります。
プロジェクトルートにあるansible.cfgファイルを編集します。
[ssh_connection]
pipelining = True
注意: Pipeliningにより、実行速度が30%以上向上する可能性があります。ただし、sudoの設定で(NOPASSWDではなく)パスワードが必要な場合、pipeliningによってタスクがハングする可能性があります。必ず最初にステージング環境でテストしてください。
解決策3: TTYを強制する(最終手段)
Ansibleに擬似端末を強制的に割り当てさせることで、リモートホストを騙すことができます。これは実際のユーザーセッションを模倣します。SSH引数の中で-ttフラグを使用します。
ansible.cfgにて:
[ssh_connection]
ssh_args = -C -o ControlMaster=auto -o ControlPersist=60s -tt
最終手段である理由: TTYを強制すると、クリーンなデータストリームを期待するモジュールが破損することがよくあります。TTYは隠れた制御文字を注入したり、出力の長い行を折り返したりすることがあり、Ansibleでの予測不可能なパースエラーにつながる可能性があります。
検証: 修正の確認
修正を適用したら、簡単なアドホックコマンドを実行します。これにより、インベントリ全体で特権昇格が機能するようになったことを確認できます。
ansible all -m shell -a "whoami" --become
コマンドがTTYエラーの代わりに、ホストに対してrootを返せば、障害は解消されています。
まとめ
- 原因:
/etc/sudoers内のレガシーなrequiretty設定が、非対話型のsudo呼び出しをブロックしている。 - 最善の策:
visudoを使用してDefaults requirettyをコメントアウトする。 - 大規模向けの策: 接続を効率化するために、Ansible設定で
pipelining = Trueを有効にする。

