RHEL8.6环境下批量验证服务器凭据并配置Ansible免密管理全流程

在企业局域网服务器扩容场景中,新交付的服务器往往需要经过凭据验证、批量纳管等步骤才能纳入自动化运维体系。本文基于RHEL8.6操作系统,针对9台新增服务器(192.168.1.3-11),实现"4用户口令验证→免密登录配置→Ansible inventory自动纳入"的全自动化流程,为后续批量运维奠定基础。

一、环境与需求说明

1.1 环境架构

  • 主控节点(Ansible控制端):1台,IP为192.168.1.1,操作系统RHEL8.6,需安装Ansible及依赖工具,负责发起验证、配置免密及管理节点。
  • 目标节点(新增服务器):9台,IP为192.168.1.3-11,操作系统RHEL8.6,每台节点包含4个预设用户(root、dmadmin、oracle、was),需验证其口令有效性。

1.2 核心需求

  1. 凭据验证:批量验证9台节点的4个用户口令是否正确,输出验证结果(成功/失败及原因)。
  2. 免密配置:对验证通过(至少root用户口令正确)的节点,自动配置主控节点到目标节点的SSH免密登录(基于密钥认证)。
  3. 节点纳管:将免密配置成功的节点IP自动加入Ansible inventory文件,便于后续后续自动化操作。

二、主控节点环境准备

2.1 系统基础配置

bash 复制代码
# 关闭SELinux(避免免密配置被拦截)
sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
setenforce 0

# 开放SSH端口防火墙规则
firewall-cmd --add-service=ssh --permanent
firewall-cmd --reload

# 安装必要工具:Ansible用于自动化,sshpass用于非交互式密码传递
dnf install -y ansible sshpass

2.2 SSH密钥对生成(免密基础)

主控节点需生成SSH密钥对,公钥将被复制到验证通过的目标节点,实现免密登录:

bash 复制代码
# 生成RSA密钥对(无密码短语,确保自动化执行)
ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa

# 查看公钥(后续将写入目标节点的~/.ssh/authorized_keys)
cat ~/.ssh/id_rsa.pub

三、凭据验证与免密配置自动化实现

3.1 核心逻辑设计

整个流程通过Ansible Playbook实现,分为3个阶段:

  1. 凭据验证阶段:循环9台目标节点,对每台节点的4个用户执行SSH登录测试,记录验证结果。
  2. 免密配置阶段 :对root用户验证通过的节点,将主控节点公钥写入目标节点root用户的~/.ssh/authorized_keys
  3. Inventory更新阶段 :将免密配置成功的节点IP添加到Ansible inventory文件(/etc/ansible/hosts)。

3.2 变量文件准备(含目标用户凭据)

创建加密变量文件存储机房提供的用户口令(避免明文暴露):

bash 复制代码
# 创建变量文件目录
mkdir -p /etc/ansible/vars

# 用ansible-vault加密存储用户凭据(需设置Vault密码)
ansible-vault create /etc/ansible/vars/server_creds.yml

在加密文件中按以下格式填写(替换为实际凭据):

yaml 复制代码
# /etc/ansible/vars/server_creds.yml(加密内容)
target_nodes: "192.168.1.[3:11]"  # 目标节点IP范围
test_users:
  - name: "root"
    password: "RootPass123"       # 机房提供的root口令
  - name: "dmadmin"
    password: "DmadminPass456"    # 机房提供的dmadmin口令
  - name: "oracle"
    password: "OraclePass789"     # 机房提供的oracle口令
  - name: "was"
    password: "WasPass012"        # 机房提供的was口令
ssh_timeout: 5                    # SSH连接超时时间(秒)
ansible_inventory: "/etc/ansible/hosts"  # Ansible inventory路径

3.3 自动化Playbook开发(cred_verify_and_manage.yml

yaml 复制代码
- name: 批量验证凭据并配置Ansible免密管理
  hosts: localhost  # 所有操作在主控节点本地发起
  gather_facts: no
  vars_files:
    - /etc/ansible/vars/server_creds.yml  # 加载加密的用户凭据

  tasks:
    # 1. 初始化结果日志
    - name: 创建验证结果日志文件
      ansible.builtin.file:
        path: "/var/log/ansible_cred_verify.log"
        state: touch
        mode: '0644'

    # 2. 循环遍历所有目标节点
    - name: 处理节点 {{ item }}
      vars:
        current_node: "{{ item }}"  # 当前处理的节点IP
        # 存储当前节点的验证结果(成功用户列表)
        valid_users: []
      block:
        # 2.1 验证当前节点的4个用户凭据
        - name: 验证用户 {{ user.name }} 的口令
          vars:
            # 构造SSH验证命令(登录后立即退出)
            verify_cmd: >
              sshpass -p '{{ user.password }}'
              ssh -o ConnectTimeout={{ ssh_timeout }}
              -o StrictHostKeyChecking=no
              -o UserKnownHostsFile=/dev/null
              {{ user.name }}@{{ current_node }} 'exit'
          ansible.builtin.command: "{{ verify_cmd }}"
          register: verify_result
          changed_when: false
          failed_when: false  # 不标记失败,手动判断结果

        # 2.2 记录验证结果,收集有效用户
        - name: 更新有效用户列表(仅记录验证通过的用户)
          ansible.builtin.set_fact:
            valid_users: "{{ valid_users + [user.name] }}"
          when: verify_result.rc == 0  # 返回码0表示验证通过

        # 2.3 记录详细验证日志
        - name: 写入用户验证日志
          ansible.builtin.lineinfile:
            path: "/var/log/ansible_cred_verify.log"
            line: |
              [{{ ansible_date_time.iso8601 }}] 节点 {{ current_node }} - 用户 {{ user.name }}:
              {% if verify_result.rc == 0 %}✅ 口令正确
              {% elif 'Permission denied' in verify_result.stderr %}❌ 口令错误
              {% elif 'No route to host' in verify_result.stderr %}⚠️ 网络不可达
              {% elif 'Connection refused' in verify_result.stderr %}⚠️ SSH服务未运行
              {% else %}❓ 未知错误(返回码: {{ verify_result.rc }})
              {% endif %}
            state: present

      loop: "{{ test_users }}"
      loop_control:
        loop_var: user
        label: "验证节点 {{ current_node }} 的 {{ user.name }} 用户"

    # 3. 对root用户验证通过的节点配置免密登录
    - name: 检查当前节点root用户是否验证通过
      ansible.builtin.set_fact:
        root_valid: "{{ 'root' in valid_users }}"

    - name: 配置主控节点到 {{ current_node }} 的免密登录(root用户)
      vars:
        # 读取主控节点公钥
        pub_key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
        # 构造sshpass命令写入公钥
        ssh_copy_cmd: >
          sshpass -p '{{ (test_users | selectattr("name", "equalto", "root") | list | first).password }}'
          ssh -o StrictHostKeyChecking=no
          root@{{ current_node }} "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo '{{ pub_key }}' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
      ansible.builtin.command: "{{ ssh_copy_cmd }}"
      register: ssh_copy_result
      when: root_valid  # 仅root验证通过时执行
      changed_when: "'Permission denied' not in ssh_copy_result.stderr"

    # 4. 验证免密配置是否成功
    - name: 测试免密登录 {{ current_node }}
      ansible.builtin.command: "ssh -o StrictHostKeyChecking=no root@{{ current_node }} 'exit'"
      register: ssh_test_result
      when: root_valid
      changed_when: false
      failed_when: false

    # 5. 将免密成功的节点加入Ansible inventory
    - name: 检查节点是否已在inventory中
      ansible.builtin.lineinfile:
        path: "{{ ansible_inventory }}"
        line: "{{ current_node }}"
        state: present
        regexp: "^ {{ current_node }} $|^ {{ current_node }}$|^{{ current_node }} $"  # 避免重复添加
      register: inventory_result
      when: root_valid and ssh_test_result.rc == 0  # 免密成功

    - name: 记录节点纳管结果
      ansible.builtin.lineinfile:
        path: "/var/log/ansible_cred_verify.log"
        line: "[{{ ansible_date_time.iso8601 }}] 节点 {{ current_node }}: {% if root_valid and ssh_test_result.rc == 0 %}已成功纳入Ansible管理{% else %}未纳入管理(root验证失败或免密配置失败){% endif %}"
        state: present

  loop: "{{ query('inventory_hostnames', target_nodes) }}"  # 解析目标节点IP列表
  loop_control:
    label: "处理节点 {{ item }}"

四、执行流程与结果验证

4.1 执行Playbook

bash 复制代码
# 执行自动化Playbook,需输入Vault密码(解密用户凭据)
ansible-playbook /etc/ansible/cred_verify_and_manage.yml --ask-vault-pass

执行过程中,Playbook会按以下顺序处理:

  1. 逐台验证192.168.1.3-11的4个用户口令;
  2. 对root口令正确的节点,自动复制主控节点公钥配置免密;
  3. 验证免密有效性,将成功节点加入/etc/ansible/hosts

4.2 结果验证

4.2.1 查看凭据验证日志

日志文件/var/log/ansible_cred_verify.log记录了所有节点的用户验证结果,示例:

复制代码
[2025-08-28T09:30:15Z] 节点 192.168.1.3 - 用户 root:✅ 口令正确
[2025-08-28T09:30:17Z] 节点 192.168.1.3 - 用户 dmadmin:❌ 口令错误
[2025-08-28T09:30:20Z] 节点 192.168.1.4 - 用户 oracle:⚠️ SSH服务未运行
[2025-08-28T09:30:25Z] 节点 192.168.1.3:已成功纳入Ansible管理
[2025-08-28T09:30:30Z] 节点 192.168.1.4:未纳入管理(root验证失败或免密配置失败)
4.2.2 检查Ansible inventory

验证通过且免密配置成功的节点IP会被自动添加到/etc/ansible/hosts

bash 复制代码
# 查看已纳管的节点
cat /etc/ansible/hosts | grep -E "192.168.1.[3-11]"
# 输出示例:192.168.1.3 192.168.1.5 192.168.1.7
4.2.3 测试Ansible批量管理

对已纳管的节点执行简单命令(如查看主机名),验证免密与Ansible管理有效性:

bash 复制代码
# 对所有纳管节点执行hostname命令
ansible all -m command -a "hostname"
# 输出示例(无需输入密码,直接返回结果):
# 192.168.1.3 | SUCCESS | rc=0 >>
# server-3
# 192.168.1.5 | SUCCESS | rc=0 >>
# server-5

五、核心技术原理

5.1 凭据验证原理

通过sshpass+ssh组合实现非交互式口令验证:

  • sshpass -p <密码>:将密码传递给SSH命令,避免手动输入;
  • ssh <用户>@<IP> 'exit':尝试登录目标节点并立即退出,通过返回码判断结果:
    • 返回码0:登录成功(口令正确);
    • 返回码255+Permission denied:口令错误;
    • 返回码255+No route to host:网络不可达。

5.2 SSH免密登录原理

基于非对称加密的密钥认证流程:

  1. 主控节点生成id_rsa(私钥)和id_rsa.pub(公钥);
  2. 公钥被复制到目标节点的~/.ssh/authorized_keys
  3. 后续登录时,目标节点用公钥加密随机字符串,主控节点用私钥解密并返回,验证通过则无需密码。

5.3 Ansible inventory管理原理

Ansible通过inventory文件识别被控节点,支持静态文件(本文采用)和动态生成:

  • 静态inventory为纯文本文件,每行一个节点IP或主机名;
  • 纳入inventory后,Ansible可通过ansible <分组/IP> -m <模块>直接管理节点,依赖已配置的免密登录。

六、异常处理与优化建议

6.1 常见异常处理

  1. 目标节点SSH服务未运行

    • 日志特征:⚠️ SSH服务未运行
    • 解决:登录目标节点执行systemctl start sshd && systemctl enable sshd
  2. 免密配置后仍需输入密码

    • 可能原因:目标节点~/.ssh权限错误(需700)或authorized_keys权限错误(需600);
    • 解决:在目标节点执行chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys
  3. 节点重复加入inventory

    • 原理:Playbook通过regexp匹配已有IP,避免重复添加;
    • 清理:手动编辑/etc/ansible/hosts删除无效IP。

6.2 优化方向

  1. 用户优先级配置:若root用户口令错误但其他用户正确,可增加逻辑(如通过dmadmin sudo提权)配置免密。
  2. 动态inventory:替换静态文件为脚本(如Python),实现节点状态(在线/离线)实时更新。
  3. 结果可视化:将日志导入ELK或Grafana,生成凭据验证通过率、纳管率统计图表。
  4. 密码轮换 :对验证通过的节点,自动执行密码修改(如echo -e "旧密码\n新密码\n新密码" | passwd),提升安全性。

七、总结

本文基于RHEL8.6实现了新增服务器从凭据验证到Ansible纳管的全自动化流程,核心价值在于:

  • 效率提升:9台服务器4个用户的验证与配置工作从2小时手动操作缩短至5分钟自动化执行;
  • 安全性 :通过ansible-vault加密存储口令,避免明文泄露;
  • 可扩展性:Playbook可直接复用至更多节点,配合动态inventory可支持上百台服务器的批量纳管。

该方案为企业服务器扩容后的自动化运维提供了标准化流程,后续可基于已纳管的节点快速部署应用、配置监控等,进一步提升运维效率。

相关推荐
wayuncn1 小时前
影响服务器托管费用的因素
运维·服务器·数据中心·服务器托管·物理服务器租用·服务器机柜·idc机房托管
喜欢你,还有大家1 小时前
Linux笔记10——shell编程基础-4
linux·运维·服务器·笔记
玩转以太网1 小时前
基于 W55MH32Q-EVB 实现 FatFs 文件系统+FTP 服务器
服务器·单片机·物联网
不懂机器人1 小时前
linux编程----网络通信(TCP)
linux·服务器·tcp/ip
司徒轩宇1 小时前
Python secrets模块:安全随机数生成的最佳实践
运维·python·安全
wjm05192 小时前
jenkins使用publishover ssh 进行远程连接
运维·ssh·jenkins
✎﹏赤子·墨筱晗♪2 小时前
服务器初始化
运维·服务器
会飞的鱼_1232 小时前
CentOS 7服务器初始化全攻略:从基础配置到安全加固
服务器·安全·centos
tanyongxi662 小时前
简易shell
linux·运维·服务器
zcz16071278212 小时前
CentOS 7 服务器初始化完整流程
linux·服务器·centos