第三章 安装与配置:在主流Linux发行版上安装Ansible,配置ansible.cfg、hosts文件、SSH免密登录与基础连通性测试
Ansible作为一款无代理(Agentless)的自动化运维工具,其核心优势在于通过SSH协议直接管理目标主机,无需在受管节点上预装任何客户端程序。这一设计哲学极大地降低了部署门槛,但同时也意味着控制端(Control Node)的安装质量与配置文件合理性,将直接决定后续所有Playbook执行的稳定性与效率。本章将聚焦于Ansible控制端的完整搭建流程,涵盖在主流Linux发行版上的安装方法、核心配置文件的语义解析、基于SSH密钥的信任体系构建,以及通过Ad-Hoc命令验证基础连通性的标准操作。我们将从原理出发,逐步深入到实战配置,帮助读者建立起一套健壮、可扩展的自动化管理基础环境。
上图清晰地展示了Ansible控制端从安装到验证的完整工程链路。控制端是整个自动化体系的“大脑”,所有Playbook的执行、任务下发和结果汇总都在此完成。受管节点仅需支持SSH和Python解释器即可被纳管。在开始安装之前,我们需要明确一个核心概念:控制端通常不承担业务负载,它应当是一台独立、稳定的服务器或容器,拥有足够的网络带宽和文件处理能力。接下来,我们将按照“安装—配置—验证”的顺序,逐步构建这套环境。
3.1 核心原理:无代理架构与配置生效机制
Ansible之所以能在众多配置管理工具(如Puppet、Chef、SaltStack)中脱颖而出,其“无代理”架构功不可没。这意味着我们不需要在受管节点上安装任何Ansible相关的守护进程(Daemon)或客户端软件。控制端通过SSH协议连接到目标主机,将模块(Module)的Python代码或Shell命令传输过去,执行完毕后返回结果并断开连接。这种模式带来了几个显著优势:
- 低侵入性:受管节点无需预装软件,降低了被攻击面,也减少了资源占用。
- 易上手:只要目标主机支持SSH,即可被管理,无需复杂的PKI(公钥基础设施)或证书签发流程。
- 幂等性:大多数Ansible模块设计为幂等,即多次执行与一次执行的效果相同,这为自动化运维提供了安全保障。
然而,无代理架构也意味着控制端必须能够稳定、高效地与所有受管节点建立SSH连接。因此,SSH免密登录的配置质量直接决定了Ansible任务执行的效率与成功率。此外,Ansible的配置生效遵循一个严格的优先级顺序,理解这一点对于排查“为什么我的配置没生效”至关重要。其优先级从高到低依次为:环境变量(ANSIBLE_CONFIG) > 当前目录下的ansible.cfg > 用户家目录下的~/.ansible.cfg > 系统全局的/etc/ansible/ansible.cfg。默认情况下,Ansible会优先使用当前工作目录下的配置文件,这为不同项目使用不同配置提供了便利。
3.2 安装方法:主流发行版与Python环境管理
Ansible是基于Python开发的,因此控制端必须拥有可用的Python解释器(Python 3.8+是推荐版本)。在主流Linux发行版上,安装Ansible通常有三种途径:系统包管理器、Python包管理器(pip)以及源码安装。对于生产环境,我们强烈推荐使用系统包管理器,因为它能自动处理依赖关系,并方便后续的版本升级与卸载。
3.2.1 基于RHEL/CentOS/Rocky/AlmaLinux的安装
在Red Hat系发行版上,Ansible位于EPEL(Extra Packages for Enterprise Linux)仓库中。首先需要启用EPEL仓库,然后直接安装。以Rocky Linux 9为例:
# 1. 安装EPEL仓库
sudo dnf install -y epel-release
# 2. 更新缓存并安装Ansible
sudo dnf makecache
sudo dnf install -y ansible
# 3. 验证安装版本
ansible --version
安装完成后,ansible --version命令会输出Ansible核心版本、Python版本以及配置文件搜索路径。如果系统默认的Python版本较低(如2.7),建议使用dnf module或手动安装Python 3.11,并确保ansible命令指向正确的Python解释器。
3.2.2 基于Debian/Ubuntu的安装
Debian/Ubuntu系的官方源中通常包含Ansible,但版本可能较旧。为了获取最新稳定版,我们推荐使用Ansible官方提供的PPA(Personal Package Archive)源。以Ubuntu 22.04 LTS为例:
# 1. 更新软件包列表并安装基础依赖
sudo apt update
sudo apt install -y software-properties-common
# 2. 添加Ansible官方PPA源
sudo add-apt-repository --yes --update ppa:ansible/ansible
# 3. 安装Ansible
sudo apt install -y ansible
# 4. 验证
ansible --version
对于Debian系统,可能需要先安装lsb-release和gnupg才能顺利添加PPA。如果网络环境受限,无法访问PPA,则可以直接使用apt install ansible安装系统自带版本,但需注意版本兼容性。
3.2.3 使用pip安装(适用于macOS或特殊环境)
当系统包管理器不可用或需要特定版本时,可以使用pip安装。但需要注意,pip安装的Ansible会覆盖系统包管理器安装的版本,且依赖管理较为松散,不建议在生产环境使用。
# 使用pip3安装指定版本
pip3 install ansible==9.2.0
# 或者安装最新版
pip3 install ansible
ansible --version输出中的python version字段。如果显示为Python 2.x,请立即升级Python环境,因为Ansible 2.10+已完全放弃对Python 2的支持。同时,建议使用虚拟环境(如python3 -m venv)来隔离不同项目的依赖,避免全局环境混乱。
3.3 配置ansible.cfg:定义控制端行为
ansible.cfg是Ansible控制端的核心配置文件,它决定了Inventory文件位置、SSH连接参数、模块运行方式、日志记录等关键行为。虽然Ansible提供了默认配置,但在实际项目中,我们几乎总是需要自定义此文件。一个典型的ansible.cfg文件结构如下:
[defaults]
# 指定Inventory文件路径,可以是相对路径或路径
inventory = ./inventory/hosts
# 指定使用哪个Python解释器执行模块(受管节点上的)
interpreter_python = /usr/bin/python3
# 是否在第一次连接时自动接受主机密钥(建议设为True,配合SSH密钥使用)
host_key_checking = False
# 默认并发执行任务的主机数量
forks = 20
# 连接超时时间(秒)
timeout = 30
# 日志文件路径(可选)
log_path = /var/log/ansible.log
# 默认模块使用的用户(如果不指定,则使用当前SSH登录用户)
remote_user = root
[privilege_escalation]
# 是否启用become(权限提升)
become = True
# 提升方式:sudo / su / pbrun 等
become_method = sudo
# 提升到的用户
become_user = root
# 是否需要密码(如果配置了NOPASSWD,则设为False)
become_ask_pass = False
[ssh_connection]
# SSH连接类型:smart / paramiko / ssh
transport = smart
# 是否启用SSH复用(加速多次连接)
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
# 指定SSH私钥文件路径(如果不使用默认的~/.ssh/id_rsa)
private_key_file = ~/.ssh/id_rsa_ansible
在上述配置中,有几个参数需要特别关注:
- inventory:这是最基础的配置,指向我们的主机清单文件。建议使用相对路径,以便项目整体迁移。
- host_key_checking:在首次连接新主机时,SSH会提示确认主机指纹。在自动化环境中,我们通常将其设为
False,以避免交互式确认导致任务挂起。 - forks:控制Ansible并发执行任务的主机数量。默认值为5,对于管理大量主机(如100台以上)的场景,建议调高至20-50,但需注意控制端的CPU和网络带宽。
- remote_user:指定默认的SSH登录用户。如果使用root直接登录,则无需配置become;如果使用普通用户,则必须配置
[privilege_escalation]段落。 - ssh_args:启用SSH连接复用(ControlMaster和ControlPersist),可以显著减少多次SSH握手的开销,提升Playbook执行速度。
--ask-pass或ansible_become_password变量传递密码,但这种方式极易泄露。生产环境必须使用SSH密钥认证,并配合sudoers文件中的NOPASSWD配置,实现全自动免密执行。
3.4 配置hosts文件:构建动态与静态Inventory
Inventory文件(通常命名为hosts)是Ansible管理主机的“通讯录”。它定义了哪些主机属于哪个组,以及每台主机的连接变量。Inventory支持静态文件(INI或YAML格式)和动态脚本(从云平台API拉取主机列表)。对于初学者,掌握静态INI格式是基础。
3.4.1 静态Inventory的INI格式
# 文件路径:/etc/ansible/hosts 或 项目目录下的inventory/hosts
# 定义一组Web服务器
[web_servers]
192.168.1.10
192.168.1.11 ansible_user=deploy ansible_ssh_private_key_file=/home/deploy/.ssh/id_rsa
web01.example.com
# 定义一组数据库服务器,并设置通用变量
[db_servers]
db01.example.com
db02.example.com
[db_servers:vars]
ansible_user=admin
ansible_become=true
ansible_become_method=sudo
# 定义子组与父组的关系
[production:children]
web_servers
db_servers
# 为所有主机设置全局变量
[all:vars]
ansible_python_interpreter=/usr/bin/python3
ansible_ssh_common_args='-o StrictHostKeyChecking=no'
在上述示例中,我们定义了web_servers和production的父组,它包含这两个子组。通过:vars后缀,我们可以为组内所有主机统一设置变量,如SSH用户、become方式等。这种分层结构使得Inventory文件清晰且易于维护。
3.4.2 主机变量的优先级
Ansible的变量优先级遵循一个复杂的规则链。简单来说,主机变量 > 组变量 > Playbook变量 > 全局变量。这意味着,如果我们在web_servers组中设置了ansible_user=deploy,但在192.168.1.11这一行单独指定了ansible_user=root,那么对于该主机,最终生效的是root。理解这一优先级有助于我们精准控制不同主机的连接行为。
[cloud_ubuntu]
ubuntu-cloud-01 ansible_host=203.0.113.5
ubuntu-cloud-02 ansible_host=203.0.113.6
[internal_centos]
centos-01 ansible_host=192.168.10.21
[cloud_ubuntu:vars]
ansible_user=ubuntu
ansible_become=true
ansible_become_method=sudo
ansible_become_pass=!vault | $ANSIBLE_VAULT;1.1;AES256
...
[internal_centos:vars]
ansible_user=centos
ansible_become=true
ansible_become_method=sudo
注意,我们使用了Ansible Vault加密了ansible_become_pass变量,避免明文密码出现在文件中。这是生产环境必须遵循的安全实践。
3.5 SSH免密登录配置与基础连通性测试
SSH免密登录是Ansible自动化执行的前提。如果每次连接都需要输入密码,那么自动化就无从谈起。配置免密登录的核心是生成密钥对,并将公钥分发到受管节点的~/.ssh/authorized_keys文件中。
3.5.1 生成密钥对与分发
# 1. 在控制端生成密钥对(如果已有则跳过)
ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa_ansible -N ""
# 2. 使用ssh-copy-id将公钥复制到受管节点(需要输入一次密码)
ssh-copy-id -i ~/.ssh/id_rsa_ansible.pub deploy@192.168.1.10
# 3. 验证免密登录
ssh -i ~/.ssh/id_rsa_ansible deploy@192.168.1.10 'hostname'
在批量分发密钥时,可以使用sshpass工具配合循环脚本,但更推荐使用Ansible自身的authorized_key模块来管理。不过,在初始环境尚未配置好Ansible时,我们通常使用ssh-copy-id手动完成。对于大规模环境(超过50台),建议使用sshpass结合脚本,或者通过配置管理工具(如JumpServer)统一分发。
3.5.2 使用Ansible Ad-Hoc命令测试连通性
配置完成后,我们使用Ansible自带的ping模块来测试控制端与所有受管节点的连通性。注意,这里的ping模块并非ICMP ping,而是检查目标主机是否能够运行Python并返回响应。
# 测试所有主机
ansible all -m ping
# 测试特定组
ansible web_servers -m ping
# 测试单台主机
ansible 192.168.1.10 -m ping
如果一切正常,输出结果将显示每台主机的SUCCESS状态以及返回的pong响应。如果出现UNREACHABLE,则需要检查网络连通性、SSH端口、用户名或密钥路径是否正确。
ansible all -m ping仍然失败,原因往往是inventory路径配置错误,或者host_key_checking = False未生效。请务必使用ansible --list-hosts all命令来验证Inventory是否被正确加载。另外,如果受管节点的Python路径不是/usr/bin/python3,需要在Inventory或ansible.cfg中通过ansible_python_interpreter变量指定。
3.6 案例拆解:从零搭建一个多环境自动化管理平台
为了将上述知识融会贯通,我们模拟一个真实的运维场景。假设某公司有一个小型互联网产品,包含3台Web服务器(Ubuntu 22.04)、2台数据库服务器(CentOS 7)和1台缓存服务器(Rocky Linux 9)。运维团队需要在这6台服务器上统一执行命令、分发配置和部署应用。我们的任务是搭建Ansible控制端,并确保所有主机纳管成功。
3.6.1 环境准备与约束
- 控制端:一台独立的Ubuntu 22.04服务器,IP为10.0.0.10,用户名为
ops。 - 受管节点:均使用内网IP,SSH端口为22,但Web服务器使用
ubuntu用户,DB服务器使用centos用户,缓存服务器使用rocky用户。 - 安全约束:禁止root直接SSH登录,所有用户均通过sudo提权。
3.6.2 操作步骤与关键参数
# 1. 在控制端安装Ansible(使用PPA源)
sudo apt update && sudo apt install -y software-properties-common
sudo add-apt-repository --yes --update ppa:ansible/ansible
sudo apt install -y ansible
# 2. 创建项目目录结构
mkdir -p ~/ansible-project/{inventory,playbooks,roles}
cd ~/ansible-project
# 3. 编写ansible.cfg
cat > ansible.cfg << 'EOF'
[defaults]
inventory = ./inventory/hosts
host_key_checking = False
forks = 10
timeout = 30
remote_user = ops
interpreter_python = /usr/bin/python3
[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
EOF
# 4. 编写Inventory文件
cat > inventory/hosts << 'EOF'
[web_servers]
10.0.0.11 ansible_user=ubuntu
10.0.0.12 ansible_user=ubuntu
10.0.0.13 ansible_user=ubuntu
[db_servers]
10.0.0.21 ansible_user=centos
10.0.0.22 ansible_user=centos
[cache_servers]
10.0.0.31 ansible_user=rocky
[all:vars]
ansible_become=true
ansible_become_method=sudo
EOF
# 5. 生成SSH密钥并分发(使用sshpass循环)
sudo apt install -y sshpass
for host in 10.0.0.11 10.0.0.12 10.0.0.13 10.0.0.21 10.0.0.22 10.0.0.31; do
sshpass -p 'InitialPass123' ssh-copy-id -i ~/.ssh/id_rsa.pub -o StrictHostKeyChecking=no ops@$host
done
# 6. 测试连通性
ansible all -m ping
3.6.3 结果分析与复盘
执行ansible all -m ping后,如果所有主机均返回pong,则说明环境搭建成功。如果某台主机失败,我们通过-vvv参数查看详细日志,发现是sudo密码错误。由于我们在Inventory中设置了ansible_become=true,但未提供密码,而受管节点的sudoers文件要求输入密码。解决方案有两种:一是为ops用户配置NOPASSWD权限,二是使用Ansible Vault加密密码并传递。我们选择了第一种方案,在受管节点上执行echo 'ops ALL=(ALL) NOPASSWD:ALL' | sudo tee /etc/sudoers.d/ops,问题解决。
这个案例揭示了几个关键点:Inventory变量的精确控制、SSH密钥分发的自动化技巧以及sudo提权策略的适配。在实际生产中,我们还需要考虑密钥的定期轮换、Inventory的动态更新以及Ansible Vault对敏感信息的保护。
3.7 常见误区与总结复盘
在安装与配置Ansible的过程中,以下误区是初学者最容易踩的坑:
| 误区描述 | 后果 | 正确做法 |
|---|---|---|
| 使用root用户直接SSH登录 | 安全风险极高,且无法审计操作者身份 | 使用普通用户+sudo提权,并配置NOPASSWD |
| 忽略host_key_checking配置 | 首次连接时任务挂起,等待用户确认指纹 | 在ansible.cfg中设置host_key_checking = False |
| Inventory中硬编码明文密码 | 密码泄露,违反安全合规要求 | 使用SSH密钥认证,或使用Ansible Vault加密变量 |
| 未指定ansible_python_interpreter | 受管节点Python路径不一致导致模块执行失败 | 在Inventory的[all:vars]中统一指定/usr/bin/python3 |
| 并发数forks设置过大 | 控制端网络或CPU过载,导致任务超时 | 根据控制端性能合理设置,一般不超过50 |
总结而言,本章的核心在于构建一个“干净、安全、高效”的控制端环境。安装只是第一步,真正的挑战在于配置的精细化和SSH信任链的建立。建议读者在完成本章学习后,立即动手搭建一个至少包含3台虚拟机的实验环境,反复练习Inventory的编写和SSH密钥的分发。只有将基础打牢,后续的Playbook编写才能事半功倍。记住,一个配置良好的控制端,是Ansible自动化运维成功的基石。在下一阶段,我们将深入探讨Playbook的语法与编写技巧,届时,本章搭建的环境将成为我们演练的舞台。