Troubleshooting and Fixing 'UNREACHABLE!' Errors
Now that we understand what causes 'UNREACHABLE!' errors, let's learn how to troubleshoot and fix them. We'll use a variety of approaches to diagnose and resolve connectivity issues.
Fixing Inventory Issues
One of the most common causes of 'UNREACHABLE!' errors is incorrect inventory information. Let's fix our inventory file:
cd ~/project/ansible-lab
First, let's update our inventory file to include a valid host. In this lab environment, we'll focus on using localhost
with different connection methods to demonstrate troubleshooting techniques:
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[ssh_local]
local-ssh ansible_host=127.0.0.1 ansible_connection=ssh
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
We've added a new group ssh_local
with a host that will attempt to connect to localhost via SSH instead of the local connection method.
Testing SSH Connectivity Directly
Before using Ansible, it's always a good idea to test SSH connectivity directly:
ssh 127.0.0.1
You might be prompted for a password or see a message about the host key. This is a good sign as it means SSH connectivity is working, but you might need to configure SSH properly for Ansible.
Press Ctrl+C to exit if you get stuck at the password prompt.
Setting Up SSH Keys for Passwordless Authentication
Ansible typically uses SSH keys for authentication. Let's set up passwordless SSH access to localhost:
## Generate an SSH key if you don't have one
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
## Add the key to authorized_keys
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
## Set proper permissions
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
Now try connecting to localhost via SSH:
ssh 127.0.0.1
You should be able to connect without being prompted for a password. Type exit
to return to your original session.
Testing Ansible with SSH Connection
Now, let's test Ansible with the SSH connection to localhost:
ansible ssh_local -m ping
If the SSH setup is correct, you should see a successful response:
local-ssh | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
If you still see an 'UNREACHABLE!' error, let's add more connection parameters to our inventory file:
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[ssh_local]
local-ssh ansible_host=127.0.0.1 ansible_connection=ssh ansible_user=labex ansible_ssh_private_key_file=~/.ssh/id_rsa
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
Try the ping command again:
ansible ssh_local -m ping
Using Ansible with a Custom SSH Configuration
Sometimes, you need more complex SSH configurations. Let's create a custom SSH config file:
mkdir -p ~/.ssh
cat > ~/.ssh/config << 'EOF'
Host local-ssh
HostName 127.0.0.1
User labex
IdentityFile ~/.ssh/id_rsa
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
EOF
## Set proper permissions
chmod 600 ~/.ssh/config
Update the inventory to use the SSH config entry:
cat > inventory << 'EOF'
[local]
localhost ansible_connection=local
[ssh_local]
local-ssh
[virtual]
virtual-host ansible_host=10.10.10.10
EOF
Test the connection again:
ansible ssh_local -m ping
Creating a Playbook to Test All Connections
Let's create a comprehensive playbook to test all our connections:
cat > connection_test.yml << 'EOF'
---
- name: Test Local Connection
hosts: local
gather_facts: no
tasks:
- name: Ping local
ping:
register: local_ping
- name: Display local ping result
debug:
var: local_ping
- name: Test SSH Connection
hosts: ssh_local
gather_facts: no
tasks:
- name: Ping via SSH
ping:
register: ssh_ping
- name: Display SSH ping result
debug:
var: ssh_ping
EOF
Run the playbook:
ansible-playbook connection_test.yml
You should see successful connections to both the local and SSH hosts:
PLAY [Test Local Connection] ********************************************
TASK [Ping local] ******************************************************
ok: [localhost]
TASK [Display local ping result] ****************************************
ok: [localhost] => {
"local_ping": {
"changed": false,
"ping": "pong"
}
}
PLAY [Test SSH Connection] **********************************************
TASK [Ping via SSH] ****************************************************
ok: [local-ssh]
TASK [Display SSH ping result] *****************************************
ok: [local-ssh] => {
"ssh_ping": {
"changed": false,
"ping": "pong"
}
}
PLAY RECAP *************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
local-ssh : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
The successful output confirms that we've fixed the 'UNREACHABLE!' errors for our valid hosts. The only host that remains unreachable is virtual-host
, which is intentional since it doesn't exist.
You have now successfully diagnosed and fixed 'UNREACHABLE!' errors by:
- Testing direct SSH connectivity
- Setting up SSH keys for passwordless authentication
- Configuring Ansible inventory with proper connection parameters
- Using a custom SSH configuration
- Verifying connectivity with a comprehensive playbook