You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自动对齐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

随着服务器数量增长,手动维护两者一致的成本越来越高,需要解决两个问题:

  1. 如何自动对齐SSH配置与Ansible清单的主机信息?
  2. 能否让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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 09:52:45