TL;DR 早わかり修正
Ansibleにおけるfatal: [host]: UNREACHABLE!エラーは、ほとんどの場合、AnsibleコントロールノードがターゲットホストとのSSH接続を確立できないことを示しています。まずpingで基本的なネットワーク接続を確認し、次にコントロールノードから問題のホストへの手動SSH接続を試してください。
ping <your_target_host_ip_or_hostname>
ssh <your_ssh_user>@<your_target_host_ip_or_hostname>
これらのいずれかが失敗した場合、それが問題の出発点です:ネットワーク、ファイアウォール、またはSSHサーバーの問題です。手動でSSHが機能する場合は、AnsibleのSSH構成に問題がある可能性が高いです。
詳細な根本原因
Ansibleがfatal: [host]: UNREACHABLE!と報告する場合、それはAnsibleが使用する基盤となる通信メカニズム(通常はSSH)が管理対象ホストへの接続に失敗したことを意味します。Ansibleはモジュールやコマンドを実行するためにターゲットマシンにログインできる必要があります。このエラーは、より低レベルの接続問題のハイレベルな症状です。Ansibleがタスクを実行できないのではなく、そもそもサーバーと通信できないのです。一般的な原因は次のとおりです。
- ネットワークの問題: コントロールノードが管理対象ホストのIPアドレスまたはホスト名に到達できません。
- ファイアウォール制限: ファイアウォール(コントロールノード、管理対象ノード、またはその間のどこか)がSSH接続(デフォルトではポート22)をブロックしています。
- SSHデーモンの問題: 管理対象ノードのSSHサーバー(
sshd)が実行されていない、誤って設定されている、または過負荷になっています。 - 誤った認証情報/認証: Ansibleが誤ったユーザー名、パスワード、またはSSHキーで認証しようとしており、接続拒否につながっています。
- ホストキー検証の問題: SSHが管理対象ノードのホストキーを検証できません。これは、キーが変更された場合や初回接続時によく発生します。
- インベントリの不一致: Ansibleインベントリファイルのホスト名またはIPアドレスが間違っています。
修正アプローチ
1. ネットワーク接続の確認
まず、Ansibleコントロールノードが基本的なネットワークレベルでターゲットホストと実際に通信できることを確認します。
修正方法:
-
ホストにPingを送信する:
ping <your_target_host_ip_or_hostname>
`ping`が失敗した場合、根本的なネットワークルーティングの問題があります。ホストのIPアドレス、ネットワークケーブル、ルーター設定、またはクラウドセキュリティグループを確認してください。
-
**SSHポートの到達可能性を確認する:** `telnet`または`nc`(netcat)を使用して、ポート22(デフォルトのSSHポート)が開いていてリッスンしているかを確認します。
```bash
telnet <your_target_host_ip_or_hostname> 22
SSH-2.0-OpenSSH_...のような出力が表示されるはずです。ハングアップしたり、すぐに接続して切断されたりする場合は、ポートがブロックされているか、SSHサーバーが応答していません。
または、`nc`を使用します:
```bash
nc -vz <your_target_host_ip_or_hostname> 22
`Connection to <host> 22 port [tcp/ssh] succeeded!`のような出力を探してください。
#### 検証:
ネットワークの問題を解決したら、Ansibleプレイブックまたはシンプルなpingモジュールを再実行します。
```bash
ansible <your_inventory_group> -m ping
2. 管理対象ホストのSSHデーモンを検査する
ターゲットマシンのSSHサーバー(sshd)は、実行されており、接続を受け入れるように正しく設定されている必要があります。
修正方法:
管理対象ホストにログインし(可能であれば、コンソールまたは別の機能しているSSHセッション経由で)、SSHデーモンのステータスを確認します。
-
SSHサービスのステータスを確認する:
sudo systemctl status sshd
実行されていない場合は、開始します:
```bash
sudo systemctl start sshd
sudo systemctl enable sshd # 起動時に開始されるようにする
-
SSHデーモンのログを確認する: システムログでSSH関連のエラーを確認します。
sudo journalctl -u sshd -e
または古いシステムの場合
sudo tail -f /var/log/auth.log sudo tail -f /var/log/secure # RedHat/CentOS
接続が失敗する理由を示すメッセージ(例:認証エラー、構成の問題)を探してください。
-
**`/etc/ssh/sshd_config`を確認する:** `Port 22`(またはカスタムSSHポート)がコメントアウトされておらず、`PasswordAuthentication yes`または`PubkeyAuthentication yes`が認証方法に従って設定されていることを確認します。
#### 検証:
コントロールノードから手動SSH接続を試みます。
```bash
ssh <your_ssh_user>@<your_target_host_ip_or_hostname>
成功したら、Ansible pingモジュールを再度試してください。
3. ファイアウォールブロックの解決
ファイアウォールは接続問題の一般的な原因です。Ansibleコントロールノードと管理対象ホストの両方でファイアウォールを確認してください。
修正方法:
-
管理対象ホストの場合:
UFW (Ubuntu/Debian): ```bash sudo ufw status verbose sudo ufw allow OpenSSH # または sudo ufw allow 22/tcp sudo ufw enable
- **firewalld (CentOS/RHEL):**
```bash
sudo firewall-cmd --list-all
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --reload
`
- **iptables (一般的なLinux):** これはより複雑ですが、ポート22をブロックしているルールがないか確認する必要があるかもしれません。既存のルールを簡単に確認するには:
```bash
sudo iptables -L -n | grep 22
SSH接続の受信を許可するルールを追加する必要があるかもしれません:
```bash
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
再起動後もiptablesルールを保持するために保存することを忘れないでください。
-
コントロールノードの場合: アウトバウンド接続ではあまり一般的ではありませんが、AnsibleコントロールノードがSSH接続を開始するのを妨げるローカルファイアウォールルールがないことを確認してください。
-
クラウドプロバイダーのセキュリティグループ/ネットワークACL: ホストがクラウド環境(AWS, Azure, GCP)にある場合、セキュリティグループまたはネットワークACLがコントロールノードのIPアドレスからのポート22でのインバウンドトラフィックを許可していることを確認してください。
`
検証:
ファイアウォールルールを調整したら、再度ポート22へのtelnetまたはncを試み、その後Ansible pingモジュールに進みます。
ansible <your_inventory_group> -m ping
4. 正しいSSH認証情報と認証
Ansibleは認証にSSHを使用します。Ansibleが接続できるものの認証に失敗した場合、このunreachableエラーが発生します。
修正方法:
-
手動SSHテスト: まず、Ansibleが使用する正確なユーザー、キー、またはパスワードを使用して手動でホストにSSH接続できることを確認します。
ssh <ansible_user>@<your_target_host_ip_or_hostname> -i /path/to/your/private_key
これが失敗した場合、まず手動SSHの問題を解決してください。一般的な問題は次のとおりです。
ユーザー名が正しくない。
- 秘密鍵ファイルのパーミッション(`0600`または`0400`である必要があります):`chmod 600 /path/to/your/private_key`。
- 対応する公開鍵が管理対象ホストの`~/.ssh/authorized_keys`にない。
- パスワードが正しくない(パスワード認証を使用している場合)。
-
**Ansibleインベントリと構成:** インベントリファイル(例:`/etc/ansible/hosts`またはプロジェクト固有のもの)と`ansible.cfg`で正しいSSHパラメータを確認します。
**`ansible_host`:** ターゲットマシンのIPアドレスまたはホスト名。
- **`ansible_user`:** Ansibleが接続に使用すべきユーザー名。
- **`ansible_port`:** SSHがポート22以外の場合。
- **`ansible_private_key_file`:** SSH秘密鍵へのパス。
- **`ansible_ssh_pass` / `ansible_password`:** SSHパスワード(一般的には推奨されません。SSHキーまたはAnsible Vaultを使用してください)。
- **`ansible_ssh_common_args`:** カスタムSSH引数用。例:`-o StrictHostKeyChecking=no`(注意して使用してください。初期設定または既知の環境のみ)。
インベントリエントリの例:
```ini
[webservers]
web1 ansible_host=192.168.1.100 ansible_user=deployuser ansible_private_key_file=/home/user/.ssh/id_rsa
-
SSHエージェント: SSHエージェントを使用している場合は、キーが追加されていることを確認します。
eval "$(ssh-agent -s)" ssh-add ~/.ssh/id_rsa
-
**ホストキー検証:** ホストキー検証に関する警告が表示される場合、ホストを`known_hosts`ファイルに追加する必要があるかもしれません。まず手動で接続して:
```bash
ssh <ansible_user>@<your_target_host_ip_or_hostname>
キーを受け入れるか、一時的な環境や管理された環境では、ansible.cfgで:
```ini
[defaults] host_key_checking = False
を使用するか、インベントリで`ansible_ssh_common_args='-o StrictHostKeyChecking=no'`を設定します(これも注意して使用してください)。
#### 検証:
認証の詳細を調整したら、Ansibleコマンドを再度試してください。
```bash
ansible <your_inventory_group> -m ping
5. 間違ったPythonインタープリターパス
UNREACHABLE!エラー自体(通常、Pythonコードが実行される前に発生します)ではあまり一般的ではありませんが、接続が一時的に成功し、その後奇妙なエラーで失敗する場合、Ansibleが管理対象ホストでPythonインタープリターを見つけられないことに関連している可能性があります。
修正方法:
インベントリまたはansible.cfgで正しいPythonインタープリターパスを指定します。
[webservers:vars]
ansible_python_interpreter=/usr/bin/python3
またはansible.cfgでグローバルに設定します。
[defaults]
interpreter_python = auto_silent # Ansibleは自動検出を試みます。またはパスを指定します: /usr/bin/python3
検証:
Pythonインタープリターを必要とするシンプルなAnsibleコマンドを実行します。
ansible <your_inventory_group> -m setup

