2. 使用Ansible Playbook配置SSH密钥认证

任务目标

编写一个Ansible Playbook,在控制节点上生成SSH密钥对(若不存在),并将公钥追加到受管主机的 ~/.ssh/authorized_keys 文件中,最终实现从控制节点到受管主机的免密SSH登录。

前置条件

  • 控制节点已安装Ansible,并配置好指向受管主机的inventory文件。
  • 控制节点当前能够通过密码或已有密钥SSH登录受管主机(用于首次分发)。
  • 受管主机已安装Python 2.7或Python 3(Ansible执行所需)。

Playbook实现

创建 ssh_key_auth.yml 文件,内容如下:

---
- name: 配置SSH密钥认证
  hosts: all
  gather_facts: no
  vars:
    ssh_key_comment: "ansible-managed"
    ssh_key_type: "ed25519"
    ssh_key_bits: ""

  tasks:
    - name: 在控制节点生成SSH密钥对(若不存在)
      community.crypto.openssh_keypair:
        path: "{{ lookup('env', 'HOME') }}/.ssh/id_{{ ssh_key_type }}"
        type: "{{ ssh_key_type }}"
        size: "{{ ssh_key_bits | default(omit) }}"
        comment: "{{ ssh_key_comment }}"
        state: present
      connection: local
      become: no
      run_once: yes
      delegate_to: localhost

    - name: 读取控制节点公钥内容
      slurp:
        src: "{{ lookup('env', 'HOME') }}/.ssh/id_{{ ssh_key_type }}.pub"
      connection: local
      become: no
      run_once: yes
      delegate_to: localhost
      register: control_pubkey

    - name: 将公钥分发到受管主机
      authorized_key:
        user: "{{ ansible_user | default('root') }}"
        state: present
        key: "{{ control_pubkey['content'] | b64decode }}"

运行方式

ansible-playbook -i inventory ssh_key_auth.yml -k

其中 -k 提示输入SSH密码(首次分发时使用)。若inventory中已配置 ansible_ssh_pass 或已有其他免密通道,可省略此参数。

验证方法

  1. Playbook执行完毕后,在控制节点直接执行:ssh 受管主机IP,若无需输入密码即可登录,则配置成功。
  2. 也可在受管主机上检查 ~/.ssh/authorized_keys 文件末尾是否包含控制节点对应的公钥内容。

关键说明

  • 使用 community.crypto 集合中的 openssh_keypair 模块生成密钥对,需提前安装:ansible-galaxy collection install community.crypto。
  • 密钥类型默认使用 ed25519,如需改为RSA,可将 ssh_key_type 改为 rsa 并设置 ssh_key_bits: 2048。
  • 若受管主机使用非root用户登录,需确保该用户目录下存在 .ssh 目录且权限正确(authorized_key 模块会自动处理目录创建与权限设置)。
  • Playbook中 delegate_to: localhost 确保密钥生成和读取仅在控制节点执行一次,公钥内容通过 register 传递给后续任务。