1 Ansible基本架构
1.1 Ansible工作模式
Ansible是基于模块工作的,本身没有批量部署的能力,真正具有批量部署能力的是Ansible所运行的模块,Ansible只是提供一种框架。
1.2 Ansible组件
- Ansible:Ansible核心程序
- Play books:任务剧本(任务集),编排定义Ansible任务集的配置文件,由Ansible依次执行多个任务,通常是JSON格式的YML文件
- Host inventory:Ansible管理主机的清单,记录由Ansible管理的主机信息,包括端口、密码、IP等
- Modules:核心模块,主要操作是通过调用核心模块来完成管理任务
- CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言
- Connection plugins:基于连接插件连接到各个主机上,即Ansible和Host通信使用,默认是使用SSH
- Plugins:模块功能的补充,如连接类型插件、循环插件、变量插件等,可借助于插件完成更丰富的功能
- Playbooks:批量的命令文件
用户请求发送给Ansible核心模块,Ansible核心模块通过Host inventory模块寻找需要运行的主机,然后通过Connection plugins连接远程的主机,并发送命令。Ansible使用插件来连接每一个被控制端Host,此外,也通过插件来记录日志等信息。
1.3 Ansible生成的主要文件
/etc/ansible
- /etc/ansible/ansible.cfg :配置文件
- /etc/ansible/hosts :主机库(host inventory),管理被监控的主机
- /usr/bin/ansible:主程序
- /usr/bin/ansible-doc:文档
- /usr/bin/ansible-playbook:剧本
2 Ansible任务执行模式
2.1 Ansible任务执行模式
Ansible任务执行模式分为2种:
- ad-hoc模式(点对点模块):使用单个模块,支持批量执行单条命令,相当与在bash中执行一句Shell命
- playbook模式(剧本模式):Ansible主要的管理方式,通过多个task的集合完成一类功能,可以理解为多个ad-hoc的配置文件
2.2 Ansible任务执行流程

3 Ansible应用
3.1 定义主机列表(Inventory)
Ansible主要功能在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory中将主机进行分组命名。默认的inventory file为/etc/ansible/hosts。inventory文件可以有多个,也可以通过Dynamic Inventory来动态生成。
Inventory文件格式:
- Inventory文件遵循ini文件风格,中括号[]中的字符为组名
- 可以将同一个主机同时放到不同的组当中
- 如果主机采用的是非ssh默认端口时,可以在主机名称之后采用冒号加具体端口号来注明
- 如果主机名遵循相似的命名模式,可以使用列表的形式来表示主机名
- 主机变量可以在Inventory中定义主机时进行添加,便于在playbook中进行使用
示例:
1.Inventory文件遵循ini文件风格,中括号[]中的字符为组名可以将同一个主机同时放到不同的组当中
[webservers]
node1
[dbservers]
node1
2.如果主机采用的是非ssh默认端口时,可以在主机名称之后采用冒号加具体端口号来注明
[webservers]
node1:2022
[dbservers]
node1
2.如果主机名遵循相似的命名模式,可以使用列表的形式来表示主机名
[webservers]
node[1:3]
[dbservers]
node[1:2]
3.主机变量可以在Inventory中定义主机时进行添加,便于在playbook中进行使用
[webservers]
node1 http_port=80 maxRequestsPerChild=808
node2 http_port=8080 maxRequestsPerChild=909
**Inventory参数:**Ansible在基于ssh连接Inventory中指定的远程主机时,可以通过指定参数来指定其交互方式,常用参数如下:
- ansible_ssh_host:远程主机
- ansible_ssh_user:指定远程主机ssh端口
- ansible_ssh_pass:连接远程主机使用的密码
- ansible_sudo_pass:sudo密码,建议使用--ask-sudo-pass命令
- ansible_connection:指定连接类型,类型包括:local、ssh、paramiko
- ansible_shell_type:指定连接对端的shell类型,默认支持sh
- ansible_ssh_private_key_file:ssh连接使用的私钥
- ansible_python_interpreter:指定对端使用的python编译器路径
示例:
根据定义的Inventory调用ping检测网络是否可达:
检测Inventory中定义的所有主机:ansible all -m ping
[root@node2 ~]# ansible all -m ping
192.168.10.32 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.10.30 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.10.31 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[root@node2 ~]#
检测Inventory中定义的dbservers组的主机:ansible dbservers -m ping
[root@node2 ~]# ansible dbservers -m ping
192.168.10.30 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[root@node2 ~]#
检测指定单台主机:ansible 192.168.10.30 -m ping
[root@node2 ~]# ansible 192.168.10.30 -m ping
192.168.10.30 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[root@node2 ~]#
3.2 基于ad-hoc模式运行
Ansible通过ssh实现目标主机的配置管理、应用部署、任务执行等操作,故而需要事先配置Ansible端能基于秘钥认证的方式连接各被管理节点。
基本语法:
ansible <pattern> -m <module_name> -a <module_arguments> [options]
解释:
<pattern>:目标主机或主机组,可以是Inventory中的主机名、IP地址、主机组或关键字(如all)
-m <module_name>:指定要使用的模块(如ping、shell、copy等)
-a <module_arguments>:传递给模块的参数
[options]:可选参数,用于控制Ansible行为
3.2.1 常用选项
|---------------|------------------------------------------------|
| 模块 | 描述 |
| -i | 指定自定义的Inventory文件 |
| --private-key | 指定SSH私钥文件 |
| -u | 指定SSH用户 |
| -k | 提示输入SSH密码 |
| -K | 提示输入become(提权)密码(如sudo密码) |
| -b | 使用become(提权)执行任务(如sudo) |
| --become-user | 指定提权后的用户(默认为root) |
| -v | 输出详细信息(-vvv或-vvvv可增加调试信息) |
| --check | 模拟运行(不实际执行任何更改) |
| --diff | 显示文件的差异(适用于文件相关模块,如copy、template) |
| --ask-pass | 提示输入SSH密码 |
| --limit | 限制运行的主机范围(如limit webservers只对webservers组的主机生效) |
示例:使用shell模块检查/etc/passwd文件中是否包含 root
ansible all -m shell -a 'grep root /etc/passwd'
[root@node2 ~]# ansible all -m shell -a 'grep root /etc/passwd'
192.168.10.30 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.10.32 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
192.168.10.31 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@node2 ~]#
3.2.2 常用模块
|---------|-----------------------------|
| 选项 | 解释 |
| ping | 目标主机连通性测试 |
| command | 在远程主机上执行命令,不支持管道 |
| shell | 在目标远程主机上调用shell解释器,支持管道命令 |
| copy | 复制文件到目标远程服务器主机上,支持设定内容和修改权限 |
| file | 创建文件、链接文件以及删除文件等操作 |
| yum | 服务安装 |
| fetch | 从远程目标主机复制文件到本地 |
| cron | crontab计划任务管理 |
| service | 服务管理 |
| user | 用户管理 |
| group | 用户组管理 |
| setup | 主要是收集信息 |
| script | 将本地脚本在目标远端服务器主机上运行 |
示例:使用file模块在目标远程主机上创建文件
ansible all -m file -a "path=/tmp/tmp.txt state=touch"
[root@node2 ~]# ansible all -m file -a "path=/tmp/tmp.txt state=touch"
192.168.10.31 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/tmp/tmp.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"secontext": "unconfined_u:object_r:user_tmp_t:s0",
"size": 0,
"state": "file",
"uid": 0
}
192.168.10.32 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/tmp/tmp.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"size": 0,
"state": "file",
"uid": 0
}
192.168.10.30 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"dest": "/tmp/tmp.txt",
"gid": 0,
"group": "root",
"mode": "0644",
"owner": "root",
"size": 0,
"state": "file",
"uid": 0
}
3.3 基于playbook模式执行
Playbook模式是一种通过编写YAML格式的脚本文件(称为 playbook)来定义和执行自动化任务的方式,playbook是由一个或者多个play组成的列表,play主要功能是将事先归并为一组的主机装扮成事先通过task定义好角色,task就是调用的AnsiBle的一个模块(module)。
playbook的组成部分:
- hosts:用于指定要执行的指定任务的主机组,其可以是一个或者多个由冒号组成的主机组
- user:指定远程主机上执行任务的用户,也可以自定sudo的用户
- variable:用于定义playbook运行时使用的变量
- tasks:用于定义在远程目标主机上执行的任务列表,包括
1)name:任务的名称,建议描述任务执行步骤
2)module:options:调用Ansible的模块module和传入的参数- handler:用于定义task完成后需要调用的任务,包括
1)notify:在每个paly的最后触发,调用在handler中定义的操作
2)handler:task的列表
playbook示例:
---
- hosts: web # 目标主机组
become: yes # 使用提权(如 sudo)
tasks:
- name: Ensure Apache is installed
yum:
name: httpd
state: present
- name: Ensure Apache is running
service:
name: httpd
state: started
3.3.1 playbook核心组件
-
hosts
作用:指定目标主机或主机组(在Inventory)中定义
示例:
hosts: webserver -
tasks
作用:定义要执行的任务列表
每个任务包含内容:
name:任务描述(可选,推荐使用)
模块名称(如yum、copy、service等)
模块参数示例:
tasks:- name: Ensure Apache is installed
yum:
name: httpd
state: present
- name: Ensure Apache is installed
-
vars
作用:定义变量
示例:
vars:
http_port: 80 -
handlers
作用:定义处理器,通常用于重启服务
示例:
handlers:- name: Restart Apache
service:
name: httpd
state: restarted
- name: Restart Apache
-
become
作用:是否使用提权(如sudo)
示例:
become: yes
3.3.2 playbook的执行
ansible-playbook playbook.yml
常用选项:
|-------------|-----------------------------------|
| 选项 | 描述 |
| -i | 指定自定义的Inventory文件 |
| --limit | 限制运行的主机范围 |
| --check | 模拟运行(不实际执行任何更改) |
| --diff | 显示文件的差异(适用于文件相关模块,如copy、template) |
| --tags | 只运行指定标签的任务 |
| --skip-tags | 跳过指定标签的任务 |
| -v | 输出详细信息(-vvv或-vvvv可增加调试信息) |
3.3.3 playbook高级用法
1.条件判断
使用when关键字根据条件执行任务
示例:
tasks:
- name: Install Apache on CentOS
yum:
name: httpd
state: present
when: ansible_os_family == "RedHat"
-
循环
使用loop关键字实现循环
示例:
tasks:- name: Ensure users are present
user:
name: "{{ item }}"
state: present
loop:- alice
- name: Ensure users are present
-
模版
使用template模块生成动态配置文件
示例:
tasks:- name: Configure Apache
template:
src: templates/httpd.conf.j2
dest: /etc/httpd/httpd.conf
- name: Configure Apache
-
角色
将Playbook分解为可重用的角色
示例:
roles:- common
- webserver
3.3.4 案例:安装httpd
1.创建playbook相关目录
[root@node2 ansible]# mkdir apache-playbook
[root@node2 ansible]# cd apache-playbook
[root@node2 ansible]# mkdir files
[root@node2 ansible]# mkdir templates
2.编辑Inventory文件,增加主机组web
[root@node2 ansible]# echo "[web]" >>/etc/ansible/hosts
[root@node2 ansible]# echo "192.168.10.32" >>/etc/ansible/hosts
[root@node2 ansible]#
3.创建plalybook.yml文件,增加如下内容
---
- hosts: web # 目标主机组
become: yes # 使用提权(如 sudo)
vars:
http_port: 80 # 定义 HTTP 端口
html_content: "Hello, Ansible!" # 定义 HTML 页面内容
tasks:
# 1. 安装 Apache
- name: Ensure Apache is installed
yum:
name: httpd
state: present
# 2. 配置 Apache
- name: Configure Apache
template:
src: templates/httpd.conf.j2 # 模板文件
dest: /etc/httpd/conf/httpd.conf # 目标配置文件
notify: Restart Apache # 触发处理器
# 3. 部署 HTML 页面
- name: Deploy HTML page
copy:
content: "{{ html_content }}"
dest: /var/www/html/index.html
# 4. 启动 Apache 并设置开机自启
- name: Ensure Apache is running and enabled
service:
name: httpd
state: started
enabled: yes
handlers:
# 定义处理器,用于重启 Apache
- name: Restart Apache
service:
name: httpd
state: restarted
4.创建模版文件,在templates目录下创建httpd.conf.j2文件,并增加如下内容
# {{ ansible_managed }} - DO NOT EDIT MANUALLY
Listen {{ http_port }}
<VirtualHost *:{{ http_port }}>
DocumentRoot "/var/www/html"
ServerAdmin webmaster@localhost
ErrorLog /var/log/httpd/error.log
CustomLog /var/log/httpd/access.log combined
</VirtualHost>
5.运行playbook
ansible-playbook -i /etc/ansible/hosts playbook.yml
[root@node2 apache-playbook]# ansible-playbook -i /etc/ansible/hosts playbook.yml
PLAY [web] **********************************************************************************************************************************************************************
TASK [Gathering Facts] **********************************************************************************************************************************************************
ok: [192.168.10.32]
TASK [Ensure Apache is installed] ***********************************************************************************************************************************************
ok: [192.168.10.32]
TASK [Configure Apache] *********************************************************************************************************************************************************
ok: [192.168.10.32]
TASK [Deploy HTML page] *********************************************************************************************************************************************************
ok: [192.168.10.32]
TASK [Ensure Apache is running and enabled] *************************************************************************************************************************************
ok: [192.168.10.32]
PLAY RECAP **********************************************************************************************************************************************************************
192.168.10.32 : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
[root@node2 apache-playbook]#
6.验证结果
[root@node2 apache-playbook]# curl http://192.168.10.30
Hello, Ansible!
[root@node2 apache-playbook]#