引言
在现代IT基础设施管理中,自动化运维已经成为提高效率、减少人为错误的关键手段。Ansible作为一款基于Python开发的自动化运维工具,凭借其简单易用、功能强大的特点,迅速成为运维人员的得力助手。本文将从Ansible的基础概念出发,详细介绍其安装部署、配置使用以及高级功能,帮助读者快速掌握Ansible自动化运维技能。
一、Ansible简介
1. 什么是Ansible
Logo:
Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(如puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。与其他工具不同的是,Ansible采用无客户端架构,通过SSH协议与目标主机通信,无需在被控节点上安装额外的软件。
2. Ansible的工作原理
Ansible的工作原理基于以下几个核心组件:
- 控制节点:安装Ansible的服务器,负责管理和执行自动化任务
- 被控节点:需要被管理的服务器,通过SSH与控制节点通信
- Inventory:主机清单,定义了Ansible需要管理的主机和主机组
- Playbook:任务剧本,定义了一系列要执行的任务
- 模块:Ansible执行具体操作的功能单元

二、Ansible安装部署
1. 环境准备
在开始安装Ansible之前,需要准备以下环境:
| 角色 | IP地址 | 配置 |
|---|---|---|
| Ansible服务器 | 192.168.100.100 | 安装Ansible |
| Ansible客户机 | 192.168.100.101 、 192.168.100.102、192.168.100.103、192.168.100.104 | 无需安装客户端 |
2. 安装步骤(Ansible服务器)
2.1 配置DNS解析
在Ansible服务器上配置主机名解析:
bash
# vim /etc/hosts
192.168.100.100 ansible
192.168.100.101 host1
192.168.100.102 host2
192.168.100.103 host3
192.168.100.104 host4
2.2 安装Ansible
- 安装EPEL源:
bash
# 安装epel源
yum install -y epel-release
# 或使用阿里YUM源
rm -rf /etc/yum.repos.d/*
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
- 安装Ansible:
bash
yum install -y ansible
- 验证安装:
bash
# 列出所有文件
rpm -ql ansible
# 查看配置文件
rpm -qc ansible
# 查看ansible帮助
ansible --help
# 查看所有模块
ansible-doc -l
# 查看yum模块详情
ansible-doc -s yum
3. SSH密钥配置(可选)
为了实现免密码登录,可以配置SSH密钥:
bash
# 生成密钥
ssh-keygen
# 推送公钥到目标主机
ssh-copy-id IP地址
Ansible客户机无需任何操作
三、Ansible基础配置与使用
1. 定义主机清单
编辑/etc/ansible/hosts文件,添加主机信息:
ini
host1
host2
host3
注意此处没有添加host4
2. 测试连通性
使用ping模块测试主机连通性:
bash
# 测试localhost连通性
ansible localhost -m ping
# 测试host1连通性
ansible host1 -m ping
# 简洁输出
ansible host1 -m ping -o
-m 指定模块。 什么功能,ping只是其中一个模块。还有shell,yum等等
3. 解决SSH连接问题
如果遇到SSH连接问题,可以使用以下方法:
bash
# 使用用户名和密码连接
ansible host2 -m ping -u root -k -o
# 去掉yes/no询问
vim /etc/ssh/ssh_config
# 添加:StrictHostKeyChecking no
systemctl restart sshd
# 再次测试
ansible host2 -m ping -u root -k -o
4.错误示范
bash
# 测试host4连通性
ansible host4 -m ping -u root -k -o
# 失败,主机清单未标注host4主机。
[root@ansible ~]# ansible host4 -m ping -u root -k -o
SSH password:
[WARNING]: Could not match supplied host pattern, ignoring: host4
[WARNING]: No hosts matched, nothing to do
5.注意ping和ssh的区别
- 基础概念区分 :系统原生的
ping命令基于ICMP(网际消息管理协议) ,用于测试主机间网络层的连通性;而 Ansible 的ping模块,和 ICMP 协议无关。 - 核心测试结论 :即便关闭目标主机 host1 的 sshd 进程,原生
ping命令仍能完成连通性测试(网络层通畅),但此时用 Ansible 对 host1 做连通测试会失败。 - 这证明Ansible 的 ping 模块,本质是探测目标主机的 SSH 服务 /sshd 进程是否可正常连接、完成认证,是应用层的 SSH 连通性校验,而非网络层的 ICMP ping。
四、Inventory主机清单高级配置
Inventory:清查;存货清单;财产目录;主机清单
1. 增加主机组
ini
vim /etc/ansible/hosts
# 编辑内容如下
[webserver]
host1
host2
host3
host4
测试主机组连通性:
bash
ansible webserver -m ping -o
# 输出结果如下
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
2. 配置用户名和密码
如果你没有做SSH秘钥步骤,也可以在主机配置文件中设置主机登录信息
ini
vim /etc/ansible/hosts
# 配置内容如下
[webserver]
host[1:4] ansible_ssh_user='root' ansible_ssh_pass='666666'
如果你的主机密码之间互不相同可以如下所示配置
bash
[webserver]
host1 ansible_ssh_user='root' ansible_ssh_pass='777777'
host[2:4] ansible_ssh_user='root' ansible_ssh_pass='666666'
测试主机组连通性
bash
ansible webserver -m ping -o
3. 配置端口
如果主机SSH端口不是默认的22,可以这样配置:
ini
[webserver]
host1 ansible_ssh_user='root' ansible_ssh_pass='777777' ansible_ssh_port='2222'
host[2:4] ansible_ssh_user='root' ansible_ssh_pass='666666'
4. 组变量
ansible内部变量可以帮助我们简化主机清单的设置:
ini
[webserver]
host[1:4]
[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='111111'
常用变量

5. 子分组
将不同的分组进行组合:
ini
[apache]
host[1:2]
[nginx]
host[3:4]
[webserver:children]
apache
nginx
[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='666666'
6. 自定义主机列表
创建自定义主机列表文件:
ini
# vim hostlist
[dockers]
host1
host2
[dockers:vars]
ansible_ssh_user='root'
ansible_ssh_pass='111111'
使用自定义主机列表:
bash
[root@ansible ~]# ansible -i hostlist dockers -m ping -o
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
五、Ad-Hoc命令
Ad-Hoc命令是指在ansible中需要快速执行的单条命令,并且不需要保存的命令,适用于快速操作。对于复杂的命令则为 playbook。
1. Shell模块
可以执行ansible-doc shell 语句查看使用说明
模块核心特性 :在目标主机的原生 Shell 环境 中执行命令,支持管道、重定向、通配符、变量等所有 Shell 语法(区别于 command 模块,是运维最常用执行模块)
bash
# 获取主机名
ansible webserver -m shell -a 'hostname' -o
# 指定线程数
ansible webserver -m shell -a 'hostname' -o -f 2
# host2部署apache
ansible host2 -m shell -a 'yum -y install httpd' -o
# 查询host3系统负载
ansible host3 -m shell -a 'uptime' -o
Ansible -f/--forks 参数
- 参数作用 :用于指定 Ansible 执行一次命令时并发运行的进程(线程)数,以此控制同时在多少台目标主机上执行任务。
- 取值要求 :需指定为整数 (
NUM)。 - 默认值 :若不手动指定,默认并发数为 5。
2. 复制模块
帮助:ansible-doc copy
bash
# 复制文件
ansible webserver -m copy -a 'src=/etc/hosts dest=/tmp/2.txt owner=root group=bin mode=777'
# 备份复制
ansible webserver -m copy -a 'src=/etc/hosts dest=/tmp/2.txt owner=root group=bin mode=777 backup=yes'
backup参数:
- 备份位置:
/tmp/(和目标文件2.txt同目录) - 备份名称:
2.txt.时间戳~ - 仅目标文件已存在且内容不同时才备份
3. 用户模块
帮助:ansible-doc user
bash
# 创建用户
ansible webserver -m user -a 'name=zhangsan state=present'
# 生成加密密码
[root@ansible ~]# echo '123456' | openssl passwd -1 -stdin
$1$8IcMZr1b$gHENEoMncluo4mUVhuNZG0
# 修改密码
ansible webserver -m user -a 'name=zhangsan password="$1$8IcMZr1b$gHENEoMncluo4mUVhuNZG0"'
# 修改shell
ansible webserver -m user -a 'name=zhangsan shell=/sbin/nologin append=yes'
# 删除用户
ansible webserver -m user -a 'name=zhangsan state=absent'
4. 软件包管理
帮助:ansible-doc yum
bash
# 升级所有包
ansible host1 -m yum -a 'name="*" state=latest'
# 安装apache
ansible host2 -m yum -a 'name="httpd" state=latest'
5. 服务模块
帮助:ansible-doc service
bash
# 启动服务
ansible host2 -m service -a 'name=httpd state=started'
# 开机启动
ansible host2 -m service -a 'name=httpd state=started enabled=yes'
# 停止服务
ansible host2 -m service -a 'name=httpd state=stopped'
# 重启服务
ansible host2 -m service -a 'name=httpd state=restarted'
# 开机禁止启动
ansible host2 -m service -a 'name=httpd state=started enabled=no'
6. 文件模块
帮助:ansible-doc file
bash
# 创建文件
ansible host1 -m file -a 'path=/tmp/88.txt mode=777 state=touch'
# 创建目录
ansible host1 -m file -a 'path=/tmp/99 mode=777 state=directory'
7. 收集模块
帮助:ansible-doc setup
bash
# 查询所有信息
ansible host3 -m setup
# 过滤查询IP地址
ansible host3 -m setup -a 'filter=ansible_all_ipv4_addresses'
六、Playbook与YAML语法
1. YAML基础语法
YAML是一种非标记语言,语法简洁明了:
列表:
- 键值对用
:分隔,列表用-表示; - 语法简洁,无需多余标签,适合写配置文件。
- 以缩进表示层级关系(禁止使用 Tab,必须用空格);
yaml
fruits:
- Apple
- Orange
- Strawberry
- Mango
格式详解:
- 父级键定义 :
fruits:是一个键(Key) ,表示后续内容是fruits对应的值;- 键名后必须加冒号
:,冒号后可换行(也可直接跟值,但列表通常换行写)。
- 列表项格式 :
- 每个列表项以 连字符
-开头,-后必须加一个空格; - 所有列表项的缩进必须一致(示例中用了 4 个空格,也可用 2 个,只要统一即可);
- 缩进表示 "属于
fruits这个键的子元素"。
- 每个列表项以 连字符
字典:
yaml
martin:
name: Martin D'vloper
job: Developer
skill: Elite
格式详解:
- 父级字典定义 :
martin:是一个键,对应的值是一个 "嵌套字典";- 同样,键名后加冒号
:,后续子元素通过缩进表示层级。
- 键值对格式 :
- 子键(如
name、job)与值用:分隔,:后必须加一个空格; - 同一层级的子键(
name、job、skill)缩进必须一致; - 值可以是字符串(如
Martin D'vloper,包含单引号也无需额外转义)。
- 子键(如
2. 编写Playbook
准备工作
bash
# 清理环境
ansible all -m yum -a 'name=httpd state=removed' -o
# 准备配置文件
yum install -y httpd
mkdir apache
cd apache
cp -rf /etc/httpd/conf/httpd.conf .
#修改端口为8080
[root@ansible apache]# grep '^Listen' httpd.conf
Listen 8080
下面是一个部署Apache的Playbook示例:
vim apache.yaml
yaml
- hosts: host2
tasks:
- name: install apache packages
yum: name=httpd state=present
- name: copy apache conf
copy: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
- name: ensure apache is running
service: name=httpd state=started enabled=yes
3. 执行Playbook
bash
# 检验语法
ansible-playbook apache.yaml --syntax-check
# 列出任务
ansible-playbook apache.yaml --list-tasks
# 列出主机
ansible-playbook apache.yaml --list-hosts
# 执行
ansible-playbook apache.yaml


4. 使用Handlers
Handlers 是 Ansible 中一种特殊的任务,具有以下特点:
- 触发条件 :只有被
notify指令 "通知" 时才会执行; - 触发时机 :在 Playbook 中所有
tasks执行完毕后才运行; - 去重执行 :即使被多个任务多次
notify,同一个 Handler 也只会执行一次; - 典型场景:服务重启(如 Apache、Nginx)、配置重载等 "仅当变化时才需要做" 的操作。
当配置文件发生变化时,自动重启服务:

我们模拟一次运行,看 Ansible 是如何工作的(例如修改端口为9999):
- 执行任务 1(安装 Apache) :
- 如果
host2没装过httpd:安装软件,任务状态标记为changed; - 如果已经装过:不操作,任务状态标记为
ok。
- 如果
- 执行任务 2(复制配置文件) :
- 对比本地 httpd.conf 和远程/etc/httpd/conf/httpd.conf
- 内容不一致 :覆盖远程文件,任务状态
changed→ 发送notify给restart apacheHandler; - 内容一致 :不操作,任务状态
ok→ 不发送notify。
- 内容不一致 :覆盖远程文件,任务状态
- 对比本地 httpd.conf 和远程/etc/httpd/conf/httpd.conf
- 执行任务 3(确保服务运行) :
- 如果
httpd没运行:启动服务,状态changed; - 如果已经在运行:不操作,状态
ok。
- 如果
- 执行 Handlers(仅当被 notify 时) :
- 如果任务 2 发送了
notify:在所有 tasks 执行完后,运行restart apacheHandler → 重启 Apache,让新配置生效; - 如果没收到
notify:跳过 Handler,不重启。
- 如果任务 2 发送了
七、Role角色扮演
1. Role目录结构
Role是Ansible中Playbook的目录组织结构,将代码或文件进行模块化,成为roles的文件目录组织结构,易读,代码可重用,层次清晰。
目标:通过role远程部署nginx并配置
roles/
├── nginx
│ ├── files
│ │ └── index.html
│ ├── handlers
│ │ └── main.yaml
│ ├── tasks
│ │ └── main.yaml
│ ├── templates
│ │ └── nginx.conf.j2
│ └── vars
│ └── main.yaml
└── site.yaml
2. 创建Role
bash
# 创建目录结构
mkdir roles/nginx/{files,handlers,tasks,templates,vars} -p
# 创建必要文件
touch roles/site.yaml roles/nginx/{handlers,tasks,vars}/main.yaml
echo 1234 > roles/nginx/files/index.html
yum install -y nginx && cp /etc/nginx/nginx.conf roles/nginx/templates/nginx.conf.j2
3. 编写Role文件
3.1 任务文件(tasks/main.yaml)
yaml
---
- name: install epel-release packge
yum: name=epel-release state=latest
- name: install nginx packge
yum: name=nginx state=latest
- name: copy index.html
copy: src=index.html dest=/usr/share/nginx/html/index.html
- name: copy nginx.conf template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
notify: restart nginx
- name: make sure nginx service running
service: name=nginx state=started enabled=yes
对迭代项的引用,固定变量名为"item",使用with_item属性给定要迭代的元素;
3.2 模板文件(templates/nginx.conf.j2)
nginx
worker_processes {{ ansible_processor_cores }};
worker_connections {{ worker_connections }};
调用内部已知变量
3.3 变量文件(vars/main.yaml)
yaml
worker_connections: 10240
3.4 处理程序文件(handlers/main.yaml)
yaml
---
- name: restart nginx
service: name=nginx state=restarted
3.5 主剧本文件(site.yaml)
yaml
- hosts: host4
roles:
- nginx
4. 执行Role
bash
# 测试语法
ansible-playbook site.yaml --syntax-check
# 实施剧本
ansible-playbook site.yaml
5.验证

八、常用技巧
1. 不同用户登录不同主机
在主机清单中设置:
ini
[webservers]
asdf.example.com ansible_port=5000 ansible_user=alice ansible_pass=123456
jkl.example.com ansible_port=5001 ansible_user=bob ansible_pass=654321
2. 加密主机清单文件
bash
# 加密文件
ansible-vault encrypt db_hosts
# 使用加密文件
ansible -i db_hosts --ask-vault-pass localhost -m ping
3. 条件执行
根据主机IP地址执行不同任务:
yaml
- hosts: webserver
tasks:
- name: "shut down 10.18.46.37 systems"
command: /usr/sbin/init 0
when: ansible_all_ipv4_addresses == "10.18.46.37"
4. 循环操作
循环创建多个用户:
yaml
- hosts: host2
tasks:
- name: add several users
user: name={{ item }} state=present groups=wheel
with_items:
- testuser1
- testuser2
九、总结
Ansible作为一款强大的自动化运维工具,通过简单的配置和丰富的模块,极大地提高了运维效率。本文从Ansible的基础概念出发,简单介绍了其安装部署、配置使用以及高级功能,包括Inventory配置、Ad-Hoc命令、Playbook编写和Role使用等。根据实际需求编写自动化任务,实现服务器的批量管理和配置,可以进一步探索Ansible的高级特性,如自定义模块、插件开发等,从而构建更加高效、可靠的自动化运维系统。