如何自动对齐SSH配置与Ansible清单?能否让SSH读取Ansible清单?
解决SSH配置与Ansible清单同步及SSH直接读取Ansible清单的问题
场景说明
我有多台通过SSH连接的远程服务器,主机信息分别维护在SSH配置文件和Ansible清单中:
现有SSH配置文件
Host node1 HostName 192.168.0.1 Host node2 HostName 192.168.0.2 Host node3 HostName 192.168.0.3 IdentityFile ~/.ssh/id_rsa Host node4 HostName 192.168.0.4 Port 9900 User joe
现有Ansible清单文件
[nginx_servers] node1 ansible_ssh_host=192.168.0.1 node2 ansible_ssh_host=192.168.0.2 [webservers] node3 ansible_host=192.168.0.3 ansible_ssh_private_key_file=~/.ssh/id_rsa node4 ansible_host=192.168.0.4 ansible_port=9900 ansible_user=joe
随着服务器数量增长,手动维护两者一致的成本越来越高,需要解决两个问题:
- 如何自动对齐SSH配置与Ansible清单的主机信息?
- 能否让SSH直接从Ansible清单读取主机信息,不再依赖SSH配置文件?
一、自动对齐SSH配置与Ansible清单
核心思路是以Ansible清单作为唯一的主机信息数据源,通过脚本自动生成或更新SSH配置文件,避免手动双向修改。
1. 用脚本从Ansible清单生成SSH配置
Ansible自带的ansible-inventory工具可以将清单导出为结构化数据(JSON/YAML格式),我们可以基于这个输出编写脚本,提取对应字段生成SSH配置:
示例Python脚本(生成SSH配置)
import json import subprocess import os # 调用ansible-inventory导出所有主机的JSON数据 inventory_output = subprocess.check_output( ["ansible-inventory", "--list", "--json"], text=True ) inventory_data = json.loads(inventory_output) # 生成的SSH配置文件放在config.d目录,避免覆盖原有配置 ssh_config_path = os.path.expanduser("~/.ssh/config.d/ansible_hosts") os.makedirs(os.path.dirname(ssh_config_path), exist_ok=True) with open(ssh_config_path, "w") as f: for host_name, host_vars in inventory_data["_meta"]["hostvars"].items(): f.write(f"Host {host_name}\n") # 映射Ansible变量到SSH配置项 if "ansible_host" in host_vars: f.write(f" HostName {host_vars['ansible_host']}\n") elif "ansible_ssh_host" in host_vars: f.write(f" HostName {host_vars['ansible_ssh_host']}\n") if "ansible_port" in host_vars: f.write(f" Port {host_vars['ansible_port']}\n") if "ansible_user" in host_vars: f.write(f" User {host_vars['ansible_user']}\n") if "ansible_ssh_private_key_file" in host_vars: f.write(f" IdentityFile {host_vars['ansible_ssh_private_key_file']}\n") f.write("\n")
说明
- 脚本会自动读取Ansible清单的所有主机变量,映射为SSH配置的对应字段;
- 在主SSH配置文件
~/.ssh/config中添加Include config.d/*,即可加载生成的配置,不影响原有手动配置。
2. 定时自动同步
用系统cron定时任务定期运行脚本,实现自动更新:
# 编辑cron任务 crontab -e # 添加每日凌晨同步的任务 0 0 * * * /usr/bin/python3 /path/to/your/script.py
二、让SSH直接从Ansible清单读取主机信息
通过自定义脚本配合SSH的ProxyCommand配置,让SSH发起连接时动态从Ansible清单查询主机信息:
1. 编写查询脚本
创建ansible-ssh-lookup.sh脚本,接受主机名作为参数,输出SSH连接所需的参数:
#!/bin/bash HOST=$1 # 从Ansible清单查询主机变量 HOST_VARS=$(ansible-inventory --host "$HOST" --yaml) # 提取对应字段 HOSTNAME=$(echo "$HOST_VARS" | grep -E '^(ansible_host|ansible_ssh_host):' | awk '{print $2}') PORT=$(echo "$HOST_VARS" | grep 'ansible_port:' | awk '{print $2}') USER=$(echo "$HOST_VARS" | grep 'ansible_user:' | awk '{print $2}') KEY=$(echo "$HOST_VARS" | grep 'ansible_ssh_private_key_file:' | awk '{print $2}') # 构建SSH命令参数 SSH_CMD="ssh" [ -n "$USER" ] && SSH_CMD="$SSH_CMD -l $USER" [ -n "$PORT" ] && SSH_CMD="$SSH_CMD -p $PORT" [ -n "$KEY" ] && SSH_CMD="$SSH_CMD -i $KEY" [ -n "$HOSTNAME" ] && SSH_CMD="$SSH_CMD $HOSTNAME" || SSH_CMD="$SSH_CMD $HOST" # 执行SSH连接 exec $SSH_CMD
2. 配置SSH使用脚本
给脚本添加执行权限:
chmod +x ansible-ssh-lookup.sh
在~/.ssh/config中添加配置,让SSH通过该脚本查询主机信息:
Host * ProxyCommand /path/to/ansible-ssh-lookup.sh %h %p
3. 使用方式
直接执行ssh node1,脚本会自动从Ansible清单查询node1的主机信息,并发起正确的SSH连接。
内容的提问来源于stack exchange,提问作者Roberto Jobet
相关产品推荐
相关产品推荐

