当前位置: 首页 > news >正文

OpenEuler 24.03 用 Ansible 一键完成 SSH 互信 —— 从踩坑到最终方案

用 Ansible 一键完成 SSH 互信 —— 从踩坑到最终方案

适用读者:需要在多台 Linux 服务器之间快速建立免密登录(SSH 互信)的运维 / 开发人员。
环境:控制节点 + 若干 CentOS 7/8、Rocky、Ubuntu 混合目标机;Ansible 2.9/2.10+。


1. 背景

在批量运维场景里,先手动逐台 ssh-copy-id 太低效。最理想的做法是 一条 Playbook 就把公钥下发到所有服务器。乍一看只需一个 authorized_key 模块,但在真实环境会碰到:

  1. SELinux 依赖:目标机启用 SELinux,却没安装 python{,3}-libselinux,导致模块 abort。

  2. 解释器发现 WarningPlatform linux … discovered Python interpreter at /usr/bin/python3 …

  3. 包名差异:CentOS 7 与 8+、Debian/Ubuntu 的 SELinux 绑定包名不同。

  4. 密钥缺失:控制节点可能还没生成 id_rsa.pub

  5. 密码安全:不想把 ansible_ssh_pass 写死在 Playbook。

本文记录一次“从红到全绿”的完整踩坑与修正过程。


2. 问题与排查

序号现象根因解决思路
1Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!目标机启用 SELinux,但缺少 Python 绑定库先用 raw 命令安装正确的库,再跑正常模块
2No package libselinux-python availableCentOS 8+ / Rocky 没有该包,正确包名是 python3-libselinux根据包管理器自动分支安装
3bash: 行 X: 语法错误:未预期的文件结束符raw 多行脚本缩进 / 换行被拼坏用 YAML 折行字符串 >,每段结尾加 ;
4Platform linux … discovered Python interpreter …解释器自动探测,仅 Warning可在 inventory 指定 ansible_python_interpreter=/usr/bin/python3;也可忽略
5没有公钥导致 lookup('file', '~/.ssh/id_rsa.pub') 报错控制节点无密钥openssh_keypair 预生成,幂等且只运行一次
6Playbook 定义了两个 vars:前后覆盖,易混淆合并为一个 vars

3. 关键技术点

3.1 用 raw 绕过 Ansible 模块依赖
  • 为什么yum/dnf/apt 模块自身也要 import selinux,装库前就会失败。

  • 做法raw 仅走 SSH,不依赖远端 Python 环境,先把依赖装好。

raw: >if command -v dnf >/dev/null; then dnf -y install python3-libselinux;elif command -v yum >/dev/null; then yum -y install libselinux-python3 || yum -y install libselinux-python;elif command -v apt-get >/dev/null; then apt-get update -qq && apt-get install -y python3-selinux;fi
3.2 控制节点自动生成密钥
  • 只在 localhost 执行,且 run_once: true

  • openssh_keypair 幂等:已有密钥就跳过。

- openssh_keypair:path: "{{ local_key_path }}"type: rsasize: 4096state: presentwhen: not key_stat.stat.existsdelegate_to: localhostrun_once: true
3.3 交互输入密码 / 后续免密
  • Playbook 加 vars_prompt;首次执行带 -k

  • 公钥下发后,再运行无需输入密码。


4. 最终 Playbook(ssh_trust.yml)

---
- name: 自动生成 SSH 密钥并配置免密登录hosts: allgather_facts: novars_prompt:- name: ansible_ssh_passprompt: "请输入目标主机 SSH 密码"private: yesvars:ansible_user: rootlocal_key_path: "{{ lookup('env', 'HOME') + '/.ssh/id_rsa' }}"pre_tasks:- name: 检查控制节点是否已有公钥ansible.builtin.stat:path: "{{ local_key_path }}.pub"register: key_statdelegate_to: localhostrun_once: true- name: 如果没有就生成密钥对(控制节点)ansible.builtin.openssh_keypair:path: "{{ local_key_path }}"type: rsasize: 4096state: presentwhen: not key_stat.stat.existsdelegate_to: localhostrun_once: truetasks:- name: 安装 SELinux Python 依赖(raw)raw: >if command -v dnf >/dev/null; then dnf -y install python3-libselinux;elif command -v yum >/dev/null; then yum -y install libselinux-python3 || yum -y install libselinux-python;elif command -v apt-get >/dev/null; then apt-get update -qq && apt-get install -y python3-selinux;fibecome: true- name: 确保远端 .ssh 目录存在ansible.builtin.file:path: "/root/.ssh"state: directorymode: '0700'owner: rootgroup: rootbecome: true- name: 部署公钥到目标主机ansible.posix.authorized_key:user: rootstate: presentkey: "{{ lookup('file', local_key_path + '.pub') }}"

5. 使用方法

# hosts.ini 里列出所有目标 IP
ansible-playbook -i hosts.ini ssh_trust.yml -k
  • 首次:输入密码,下发公钥。

  • 再次运行:已免密,无需 -k

  • 若想彻底消除解释器 Warning,在 inventory 加:

    ansible_python_interpreter=/usr/bin/python3
    

6. 收获与最佳实践

  1. SELinux 依赖先装再用,必要时用 raw

  2. 包名与发行版强相关,写脚本时用分支判断。

  3. 密钥生成与部署保持幂等run_once + authorized_key

  4. 敏感信息交互输入或用 Vault,避免明文密码。

  5. 读报错要抓关键字,一次定位核心问题。

至此,一份可跨发行版的“一键互信” Playbook 就完成了。希望本文能帮你少走弯路,快速把绿色 ok=… failed=0 留在终端。祝运维愉快!

http://www.lryc.cn/news/579569.html

相关文章:

  • 站在 Java 程序员的角度如何学习和使用 AI?从 MVC 到智能体,范式变了!
  • 渗透测试中 phpinfo() 的信息利用分析
  • Part 0:射影几何,变换与估计-第三章:3D射影几何与变换
  • 工作中用到过哪些设计模式?是怎么实现的?
  • Robot---能打羽毛球的机器人
  • Linux操作系统之文件(二):重定向
  • 物联网MQTT协议与实践:从零到精通的硬核指南
  • 【王阳明代数】基于Perplexica二次开发的道装资源标识符与重定向知识路由系统
  • 使用HAProxy搭建Web群集:原理、步骤与实战总结
  • Node.js特训专栏-实战进阶:12. 数据库事务处理与并发控制
  • 基于 alpine 构建 .net 的基础镜像
  • 基于MATLAB的风力发电机无人机巡检路径优化研究
  • 利用人名语言分类案例演示RNN、LSTM和GRU的区别(基于PyTorch)
  • Go调度器的抢占机制:从协作式到异步抢占的演进之路|Go语言进阶(7)
  • Android Profiler 丢帧分析教程及案例
  • WPF学习笔记(22)项面板模板ltemsPanelTemplate与三种模板总结
  • 【Git】同时在本地使用多个github账号进行github仓库管理
  • 两级缓存 Caffeine + Redis 架构:原理、实现与实践
  • locate 命令更新机制详解
  • 小红书自动化操作:使用本地Chrome和User Data实现高效反检测
  • Linux系统(信号篇):信号的处理
  • spring6合集——spring概述以及OCP、DIP、IOC原则
  • MongoDB Memory Server与完整的MongoDB的主要区别
  • CANFD芯片在工控机数据采集和测量中的应用分析
  • 重新学习Vue中的按键监听和鼠标监听
  • PDF的图片文字识别工具
  • 110道Python面试题(真题)
  • Spring AI ETL Pipeline使用指南
  • 01_前后端打包发布、API接口调试
  • Stata如何做机器学习?——SHAP解释框架下的足球运动员价值驱动因素识别:基于H2O集成学习模型