今天给大家带来一个运维手上都有的工具 —— Ansible。
一、入门
Ansible是一款基于Python开源的自动化工具,结合了许多运维工具的优点。可以实现批量系统设置、批量程序部署运行命令。不过ansible是基于模块工作,本身没有批量部署能力。真正具有批量部署的是ansible所运行的模块,ansible只是一个框架。
相比于市场上的运维工具,都有什么差别:
| 软件名称 | 语言 | 实现形式 | 缺点 |
|---|---|---|---|
| puppet | ruby | c/s(client/server) | 配置太复杂了! |
| saltstack | python | c/s(client/server) | 需要核心服务器 |
| ansible | python | 无核心服务器 |
Ansible具有什么特性?:选自@千峰教育
- no agents:不需要在被管控主机上安装任何客户端,更新时,只需在操作机上进行一次更新即可
- no server:无服务器端,使用时直接运行命令即可
- modules in any languages:基于模块工作,可使用任意语言开发模块
- yaml,not code:使用yaml语言定制剧本playbook
- ssh by default:基于SSH工作
- strong multi-tier solution:可实现多级指挥
贴一张 Ansible 的架构:

二、安装和基本使用
1、安装
如何安装?我这边用的是Debian系统,直接输入以下命令即可:
apt -y install ansible安装完成之后验证安装是否成功:
ansible --version
其他系统的安装方式可以看:Ansible 社区文档
当你验证安装完后你会发现一个问题,就是我的配置文件为什么是None?:
config file = None我也不知道为什么没生成,理论上应该会自动生成一个配置文件夹的,但是没关系,你可以手动生成一个:
ansible-config init --disabled > ansible.cfg输入此命令后,会在你当前的目录下生成配置文件:

当我们打开之后就可以看见默认配置了:


2、主机清单使用
①主机分类
打开主机清单,或者自行创建一个主机清单:
vim /etc/ansible/hosts接下来给大家介绍一下这个基本的使用方式,可以看见配置文件的注释给我们介绍了一个最简单的分组:
[web] # [] 内填写一个名字,就算是一个分组了
#组内填写受控主机的IP地址或者主机名
服务器IP地址
或者主机名 (/etc/hosts 里面设置的)
[dba]
#第二组
[web]
192.168.1.1
test
[servers]
test # 在哪里都可以 重复也可以②主机名范围指定
配置文件中还有一种方式,可以指定范围内的主机名,就不需要打很多主机名了:
www[001:003].example.com这个东西相当于:
www001.example.com
www002.example.com
www003.example.com欸,对的!你不需要再写这么多的主机名来划定范围了,这样的话可以减少不必要的麻烦!也不一定要001 002 这样子,我们正常的写法也是可以的:
www[99:101].example.com以上就是主机清单比较基本的内容,也是我们经常用到的。当然主机清单的基本使用还是很多的,详细的话可以看这个:Ansible 社区文档
3、基本使用
①查看主机清单生效
首先的话,我们先查看自己设置的主机清单是否生效:
ansible <主机清单分类名> --list-hosts
ansible all --list-hosts
我们前面都说,Ansible是一个框架,你能所了解到的功能,都是因为它的模块。输入以下命令可以展示出Ansible的所有模块:
ansible-doc -l
这些都是Ansible允许各个公司根据它的准则去开发自己的模块,这些都是第三方模块,被叫做collections。这些模块都有一个统一的官方库,叫做galaxy
我们现在的话可以通过以下命令,来下载一个 windows的 Galaxy:
ansible-galaxy collection install community.windows
Installing 'ansible.windows:3.3.0' to '/root/.ansible/collections/ansible_collections/ansible/windows'同时你也会在所有模块中发现 Windows 的 Galaxy。然后…你会发现你卡了,因为模块太多了…我也发现莫名其妙卡了,还不能清屏…
②测试基本功能
好的,接下来的话我们来进行一个功能的基础测试,大概的语法内容如下:
ansible <主机名> -m <模块名字> -a <传递给模块的参数>| 参数 | 备注 |
|---|---|
| 主机名 | 是主机清单定义的主机组名,主机名,IP,别名,all为所有主机。 支持通配符&正则: : — 多个组,组名之间用冒号隔开 *web* — 组名或主机名中包含 web 的 webservers[0] — webservers组中的第一台主机 |
| 模块名字 | 不填写默认为 command 模块。 最常用的模块为:command 和 shell |
| 传递给模块的参数 | 比如说,你用 command 模块,那传过去的参数即为被控主机所需要输入的命令。 |
那我们以 command 这个最基础的模块来给大家来一个测试,首先的话我们对刚刚所增加的 test 服务器发送一个 ls 命令输入的请求:
ansible test -m command -a "ls"
ssh-copy-id 用户名@test如果输入此命令时,出现:

ssh-keygen -t ed25519


| 模块 | 区别 | 缺点 |
|---|---|---|
| Command | 只能执行那么一条命令 | |
| Shell | 支持管道符号 | 等内容 | 性能比 Command差点 |
到目前为止的话,你基本上已经掌握了 Ansible 的最基本的内容,但是我们要学习的内容其实很多。比如说因为 Shell 的性能问题,我们总不能说直接通过 Shell 脚本搞一个 SCP 来复制文件呀,因为 Ansible 有一个模块叫做 Copy,有更高的效率为什么不用高效率的模块。你说是不是?
但是话说回来,咱尽量能用 Command 就用Command模块,因为 Shell 本身会多 fork 个新的 Bash 进程出来。什么情况下得用 Shell 模块?只有当你需要管道、重定向、环境变量或其他 Shell 语法时,才使用 Shell 模块。

三、常用组件
1、补充
①关于SSH指定用户问题
基于上面的内容,这边的话有几个点/几个功能,要给大家补充一下,一个是使用指定的 ssh账户和密码,参数如下:
- -u <用户名> # 指定ssh账户
- -k # 指定使用 ssh 密码
示例代码:
ansible test1 -a "uptime" -u w -k注意:这个命令还未经考证能否使用,建议小伙伴们在自己的操作系统中进行测试。@千锋教育 中测试 Centos Stream 10 中 -k无效,不管密码是否正确都可以使用。
②重定向补充
我们可以将被控主机执行的内容通过重定向来输出到本地文件当中,示例代码:
ansible test1 -a "df -h" > a.txt
2、Ping组件
使用 Ping 模块来测试 Ansible 节点可用性,示例代码:
ansible test1 -m ping

ansible test1,test2,test3 -m ping3、Ad-Hoc
这只是一个临时的用法,谈不上什么模块,相当于临时的“文档”。下列命令可以获取模块列表:
ansible-doc -l获取指定模块的使用信息:
ansible-doc -s yum那如果说,我们要一口气配置100台主机,比如说我要让100台主机同时安装 Nginx,这要怎么操作?难道要一个一个发公钥吗?

首先的话先生成公钥:
ssh-keygen -t rsa -P "" -f ~/.ssh/id rsa取消掉我们 yes/no :
vim /etc/ssh/sshd_config
给每一台主机发公钥(可以用 for 循环的形式进行发放):
ssh-copy-id 100台主机然后你就可以开始发放安装 Nginx 的命令了,但是你发现效率很低,基本上是一台台主机慢慢执行操作。以下参数可以设置并行进程数(默认为5个):
-f <并行数量>4、Copy
Copy 模块的用途很明显了,就是把 Ansible及其上的文件复制到远程被控的服务器上。基础命令如下:
ansible <服务器名称> -m copy -a "src=/etc/hosts dest=/etc/hosts owner=root group=root mode=644 backup=yes"当然 dest 之外的后面部分都是可省略选项,没有这么多东西,那我们来分析下这些可选参数的作用:
| 参数名称 | 作用 | 选项 |
|---|---|---|
| src | Absible本地机器上的文件路径 | 必选 |
| dest | 被控服务器的粘贴路径 | 必选 |
| owner | 用户名 | 可选 |
| group | 组 | 可选 |
| mode | 权限 | 可选 |
| backup | 当被控服务器粘贴路径有同名文件是否备份? | 可选(yes/no) |
| remote_src | 如果想复制被控服务器上的文件就用这个选项 | 可选(yes/no) |
5、User
也很明显,这玩意就是用户管理,直接展示代码内容,首先先生成密码为 123 的密钥:
echo '123' | openssl passwd -1 -stdin
接下来添加用户:
ansible test1 -m user -a 'name=user1 password="$1$W5j0Iln/$IVzm7xTCalORzn9hbbPNg/"'注意:单引号和双引号的位置,否则会出现不用密码就可以登录上去的漏洞!额外补充使用命令替换需要用双引号:
ansible test1 -m user -a "name=user1 password='echo '1234' | openssl passwd -1 stdin'"你可以通过以下命令确认是否有该用户创建成功:
id <用户名>
接下来就是删除用户:
ansible test1 -m user -a "name=user1 state=absent"6、Apt
软件包管理,就是我们常用的 apt -y install <软件包名称>,当然在 CentOS 系统中叫做 yum,首先的话展示删除软件:
ansible test1 -m apt -a 'name=nginx state=removed'安装软件:
ansible test1 -m apt -a 'name=nginx state=latest'
7、Service
服务管理,就是我们常用的 Systemctl <状态> <软件名> ,接下来展示示例:
ansible test1 -m service -a 'name=nginx state=started'这个基础的命令即为对 nginx 服务进行启动操作,具体参数如下:
| 参数名称 | 参数 |
|---|---|
| state | 服务状态: started:启动 reloaded:重启 stopped:关闭 |
| enabled | 是否开机自启动,选项 yes:是 no:否 |
8、Facts
facts其实算是一个组件,不算是一个模块。那他的主要作用是用于采集被管理主机信息的一个功能,通过 setup 模块查看主机的有的 facts 信息。以下是它的一个基础命令:
ansible test1 -m setup
ansible test1 -m setup -a 'filter=ansible_all_ipv4_addresses'
四、Paybook
1、入门
Paybook是什么东西,他是一个由一个或多个“play”组成的列表。讲明白点,其实就是将你要执行的 Ansible 任务集成成一个 YAML 文件来执行。关于 YAML 是什么东西,详情可以移步到:菜鸟教程,接下来给大家带来最基本的写法。
首先的话我们在需要的工作路径下创建一个 yaml 文件:
vim test.yaml里面可以写上最基本的内容:
- name: test # 整个文件名称标识
hosts: test1 # 主机清单的主机名称
user: root # 用户名
tasks: # 任务列表
- name: test01 # 任务描述
command: ls # 模块 + 参数
tags: douxing # 这是一个任务标记,可用来单独执行此任务当然可以写出多任务,多模块:
- name: test # 整个文件名称标识
hosts: test1 # 主机清单的主机名称
user: root # 用户名
tasks: # 任务列表
- name: test01 # 任务描述
command: ls # 模块 + 参数
tags: douxing # 这是一个任务标记,可用来单独执行此任务
#第二个任务
- name: test02
file: name="/tmp/test02.txt" state=touch
tags: suibiannila也可以将具体的参数拆分开来:
- name: test # 整个文件名称标识
hosts: test1 # 主机清单的主机名称
user: root # 用户名
tasks: # 任务列表
- name: test02
file:
# 展开参数
name: "/tmp/test02.txt"
state: touch
tags: suibiannila设置好之后保存即可,执行以下命令就可以执行任务了:
ansible-playbook test.yaml
2、详解
①核心元素&补充
接下来就是给大家详解 Playbooks 的核心元素了:
- Variables:变量元素,可传递给 Tasks/Templates使用
- Tasks:任务元素,由模块定义的操作的列表,即调用模块完成任务
- Templates:模块元素,使用了模块语法的文本文件,可根据变量动态生成配置文件
- Handlers:处理器元素,通常指在某事件满足时触发的操作
- Roles:角色元素
接下来详细补充一下上部分的 YAML 文件的具体内容,来自:@千锋教育


②命令补充
以下的命令可以对 YAML 进行一个语法检测(感觉很少用):
ansible-playbook --syntax-check test.yaml

接下来介绍的命令是测试运行:
ansible-playbook -C test.yaml
运行指定任务:
ansible-playbook -t test test.yaml
跳过指定任务:
ansible-playbook --skip-tags=标记名称 test.yaml从指定任务开始往下执行:
ansible-playbook --start-at-task test05 test.yaml③PlayBook模板
Ⅰ多个PlayBook模板
接下来的话给大家一个多个 Playbook 的模板:
- hosts: test1
remote_user: root
tasks:
- name: install a group
group: name=mygrp system=true
# 下面是第二个 play
- hosts: test2
remote_user: root
tasks:
- name: install a group
group: name=mygrp system=trueⅡ变量使用模板
下面是变量使用的模板:
- hosts: test1
remote_user: root
# 变量在这里
vars:
user: "root"
tasks:
- name: install a group
group: name={{ user }} # 应用变量
# 下面是第二个 play
- hosts: test2
remote_user: root
tasks:
- name: install a group
group: name=mygrp system=trueⅢ条件执行模板
条件执行模板:
- hosts: test2
remote_user: root
tasks:
- name: install a group
shell: shutdown -h now
when: ansible_menfree_mb <= 114514 # 当内存小于 114514 MB的时候执行也有 == 的条件,比如说:
ansible_architecture == "x86_64"也支持二级变量:
ansible_selinux.status == "disabled"
ansible_lo.ipv4[0] # 这个就是第一个元素 address当然有些情况肯定要指定第几个元素,比如说同时有好几个 address ,这种肯定要指定了
Ⅳhandlers模板
这是什么东西?接下来给大家一个模板,解释一下就通了!
- name: 123
hosts: test1
remote_user: root
tasks:
- name: install a group
shell: shutdown -h now
notify: test # 注意名字要一样
handlers:
- name: test
shell: echo "OK!"说明:只有当 Shell 模块真正运行时,才会调用 notify 所描述的 handlers 一样的任务的相关操作,追加内容。适合那些保存文件后需要重启服务的操作。
ⅤPause模板
这是一个暂停服务,在 PlayBook 执行的过程中暂停一定时间或者提示用户进行的某些操作。示例模板:
- name: 123
hosts: test1
remote_user: root
tasks:
- name: wait on user input
pause: prompt="你好,任意按键继续运行"
- name: timed wait
pause: seconds=30常用参数:
| 参数名 | 作用 |
|---|---|
| minutes | 暂停多少分钟 |
| seconds | 暂停多少秒 |
| prompt | 打印一串信息提示用户操作 |
五、变量
1、在命令行补充参数
接下来的话给大家补充一个关于 Vars 变量的有关内容,在 YAML 的 PlayBook 文件当中,我们将某些值设置为变量,可以从命令行中传递变量值:
- hosts: '{{ hosts }}'
remote_user: '{{ user }}'可以在命令行中进行传值:
ansible-playbook test.yaml --extra-vars "hosts=test1 user=root"也可以用 JSON 的格式进行传递:
ansible-playbook test.yaml --extra-vars "{'hosts':'test1', 'user':'root'}"还可以将参数放在文件里面:
ansible-playbook test.yaml --extra-vars "@vars.json"2、在主机清单中设置变量
直接在主机清单设置独一的变量,仅限该主机有效:
[web]
test1 hostname=web1这样的话就为主机 test1 设置了独一的变量 hostname
六、Roles
1、入门
Roles的话是 Playbook 的一部分,这玩意就是让 Playbook 这个模块变成更有组织。它将层级目录分成了以下:
- role_name/
- files/ : 存储 copy 或 script 等模块调用的文件(也就是你想要复制粘贴的内容)
- tasks/ : 此目录至少要有一个 main.yml 文件,用于定义每个 task
- handlders/ : 此目录至少要有一个 main.yml 文件,用于定义每个 handler
- vars/ : 此目录至少要有一个 main.yml 文件,用于定义各 variable
- templates/ : 存储由 template 模块调用的模块文本
- meta/ : 此目录至少要有一个 main.yml 文件,定义当前角色的特殊设定及其依赖关系
- default/ : 此目录至少要有一个 main.yml 文件,用于设定默认变量
那具体如何调用这些呢?方法如下:
- hosts: HOSTS
remote_user: USERNAME
roles:
- ROLE1
- ROLE2
- { role: ROLE3, VARIABLE: VALUE, ...}
- { role: ROLE4, when: CONDITION}这是一个标准的文件结构:

可以直接输入以下命令快捷创建:
mkdir {files,tasks,handlers,vars,templates}2、案例展示
我们现在想要安装一个 Nginx 并且要部署好一个 index.html 的测试网站,我们首先在 site.yaml(随便一个名字),先补充好主机的基本信息:
- hosts: test1
roles:
- nginx # 如上我们所阐述的 role_name接着在 nginx/templates 中放入我们常规的 nginx.conf 的配置文件(不懂就是 nginx 配置网站的基本配置就行)。注意:模板的文件格式是 .j2
在 nginx/task 中创建一个 main.yml 基本任务:
# 先安装 nginx
- name: install nginx
apt: name=nginx state=latest
# 将配置文件送到被控主机的 nginx 当中
- name: copy nginx.conf template
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf # src 就是直接引用 roles 中的模板 不需要指定具体的本机文件路径,其次 dest 是送到被控主机的路径
notify: restart nginx # 丢到 handlers 记得重启 nginx
# 将 index.html 网站送到被控主机中
- name: copy index.html
copy: src=index.html dest=/usr/share/nginx/html/index.html
# 确保 nginx 在运行状态中
- name: make sure nginx service running
service: nginx=nginx state=started在 nginx/handlers 中创建一个 main.yml:
- name: restart nginx
service: name=nginx state=restarted
# 就是委托 notify 过来的重启 nginx在 nginx/vars 创建一个 main.yml :
worker_connections: 1024因为模板 j2 当中是存在一些变量的(也是 {{ worker_connections }} 的格式),因此我们需要设置变量。至此,我们 nginx 安装到部署网站这一套流程就到这结束,最后只需要输入以下命令即可开始:
ansible-playbook site.yaml流程顺利运行,网站成功部署!
我们的 Ansible 的基础教程就给大家介绍到这里!感谢各位的阅读和支持,有问题欢迎提出!希望本教程能够帮助到各位~