一. Ansible 介绍
Ansible是一个配置管理系统configuration management system, python 语言是运维人员必须会的语言, ansible 是一个基于python 开发的自动化运维工具, 其功能实现基于ssh远程连接服务, ansible 可以实现批量系统配置,批量软件部署,批量文件拷贝,批量运行命令等功能, 除了ansible之外,还有saltstack 等批量管理软件.
Ansible能做什么?
ansible可以帮助运维人员完成一些批量任务,或者完成一些需要经常重复的工作。
比如:同时在100台服务器上安装nginx服务,并在安装后启动服务。
比如:将某个文件一次性拷贝到100台服务器上。
比如:每当有新服务器加入工作环境时,运维人员都要为新服务器部署某个服务,也就是说运维人员需要经常重复的完成相同的工作。
这些场景中运维人员都可以使用到ansible。
Ansible软件特点?
- 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作;
- 默认使用SSH协议对设备进行管理;
- 有大量常规运维操作模块,可实现日常绝大部分操作;
- 配置简单、功能强大、扩展性强;
- 支持API及自定义模块,可通过Python轻松扩展;
- 通过Playbooks来定制强大的配置、状态管理;
- 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
- 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。
Ansible是一种agentless(基于ssh),可实现批量配置、命令执行和控制,基于Python实现的自动化运维工具。Ansible的两个特性:
- 模块化:通过调用相关模块,完成指定任务,且支持任何语言编写的自定义模块;
- playbook:剧本,可根据需要一次执行完剧本中的所有任务或某些任务;

Ansible 架构

- 核心模块(core modules) 连接主机实现操作, 它依赖于具体的模块来做具体的事情。
- 插件(plugins) 完成模块功能的补充。
- 剧本(playbooks)ansible的配置文件,将多个任务定义在剧本中,由ansible自动执行。
- 主机清单(host inventory)定义ansible需要操作主机的范围。
最重要的一点: ansible是模块化的, 它所有的操作都依赖于模块, 不需要单独安装客户端(no agents),基于系统自带的sshd服务,sshd就相当于ansible的客户端, 不需要服务端(no sever),需要依靠大量的模块实现批量管理, 配置文件 /etc/ansible/ansible.cfg (前期不用配置)。
ansible任务执行模式
Ansible 系统由控制主机对被管节点的操作方式可分为两类,即adhoc和playbook:
- ad-hoc模式(点对点模式)
使用单个模块,支持批量执行单条命令。ad-hoc 命令是一种可以快速输入的命令,而且不需要保存起来的命令。就相当于bash中的一句话shell。 - playbook模式(剧本模式)
是Ansible主要管理方式,也是Ansible功能强大的关键所在。playbook通过多个task集合完成一类功能,如Web服务的安装部署、数据库服务器的批量备份等。可以简单地把playbook理解为通过组合多条ad-hoc操作的配置文件。
ansible任务执行过程
- 加载自己的配置文件,默认
/etc/ansible/ansible.cfg; - 查找对应的主机配置文件,找到要执行的主机或者组;
- 加载自己对应的模块文件,如 command;
- 通过ansible将模块或命令生成对应的临时py文件(python脚本), 并将该文件传输至远程服务器;
- 对应执行用户的家目录的
.ansible/tmp/XXX/XXX.PY文件; - 给文件 +x 执行权限;
- 执行并返回结果;
- 删除临时py文件,
sleep 0退出;
二. Ansible语法及配置参数
语法格式:
ansible <pattern_goes_here> -m <module_name> -a <arguments>
也就是:
ansible 匹配模式 -m 模块 -a '需要执行的内容'
解释说明:
匹配模式:即哪些机器生效 (可以是某一台, 或某一组, 或all) , 默认模块为command , 执行常规的shell命令.
-m name, --module-name=name: 指定执行使用的模块。
-u username, --user=username: 指定远程主机以username运行命令。
-s, --sudo: 相当于linux系统下的sudo命令。
-u sudo_username, --sudo-user=sudo_username: 使用sudo, 相当于linux系统下的sudo命令。
-C, --check: 只检查不实际执行。
-e, 即extra_vars: 引用外部参数。
-i, 即inventory: 指定仓库列表, 默认/etc/ansible/hosts。
--list-host: 列出执行主机列。
###### ansible配置文件常用参数 ########
[defaults] #inventory = /etc/ansible/hosts # 主机列表配置文件 #library = /usr/share/my_modules/ # 库文件存放目录 #remote_tmp = ~/.ansible/tmp # 临时py命令文件存放在远程主机的目录路径 #local_tmp = ~/.ansible/tmp # 本机的临时命令执行目录 #forks = 5 # 默认并发数 #sudo_user = root # 默认sudo用户 #ask_sudo_pass = True # 每次执行ansible命令是否询问SSH密码 #ask_pass = True #remote_port = 22 # 默认ssh远程端口 #roles_path = /etc/ansible/roles # 默认角色存放路径 #host_key_checking = False # 检查对应服务器的host_key,推荐取消注释,实现第一次连接自动信任目标主机 #log_path = /var/log/ansible.log # ansible执行日志文件,推荐开启
#module_name = command # 默认使用的模块,可以修改为shell等 #private_key_file = /path/to/file # 配置远程ssh私钥存放路径 [privilege_escalation] # 普通用户提权配置 #become=True #become_method=sudo #become_user=root #become_ask_pass=False
四. Ansible配置说明
1) 实验环境准备
主控节点 系统centos7.9 IP:192.168.200.21 受控节点1 系统centos7.9 IP:192.168.200.22 受控节点2 系统centos7.9 IP:192.168.200.23 受控节点3 系统centos7.9 IP:192.168.200.24 受控节点4 系统centos7.9 IP:192.168.200.25 受控节点5 系统centos8 IP:192.168.200.51 受控节点6 系统centos8 IP:192.168.200.52 受控节点7 系统centos8 IP:192.168.200.53 设置主控节点到受控节点的ssh无密码信任关系 (ansible应用环境下, 主控节点必须要设置ssh无密码跳转到受控节点的信任关系) 添加主控节点到受控节点的认证! 首先主控节点必须要生成公私密钥对, 否则不能进行免密信任关系设置!! ssh-keygen -t rsa #一直回车即可 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.22 #回车, 输入远程登录的密码即可 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.23 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.24 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.25 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.51 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.52 ssh-copy-id -i /root/.ssh/id_rsa.pub -p22 root@192.168.200.53 如果受控节点数量比较多的话, 可以使用expect进行远程ssh连接的免密信任关系
2) Ansible安装部署
Ansible有两种安装方式: yum 和 pip 安装方式 Ansible在epel的yum中有提供,所以配置好epel源,直接使用yum命令安装即可. CentOS系统, 可以使用默认的yum源直接安装ansible [root@server01 ~]# yum install -y ansible 配置文件目录:/etc/ansible/ 执行文件目录:/usr/bin/ Lib库依赖目录:/usr/lib/pythonX.X/site-packages/ansible/ Help文档目录:/usr/share/doc/ansible-X.X.X/ Man文档目录:/usr/share/man/man1/ ================================================ pip安装方式 # yum -y install python-pip python-devel # pip install ansible ================================================ ansible程序文件 /usr/bin/ansible: 命令行工具 ansible命令通用格式: ansible <host-pattern> [options] [-m module_name] [-a args] /usr/bin/ansible-doc: 帮助文档 /usr/bin/ansible-playbook: 剧本执行工具 /etc/ansible/ansible.cfg: 主配置文件 /etc/ansible/hosts: 管理的主机清单 /etc/ansible/roles: 角色存放处 查看ansible命令帮助 [root@server01 ~]# ansible -h 查看支持的模块 [root@server01 ~]# ansible -l [root@server01 ~]# ansible-doc -l |grep shell #查看shell模块 shell Execute shell commands on targets vmware_vm_shell Run commands in a VMware guest operating system win_shell Execute shell commands on target hosts 查看ansible的支持的模块个数 [root@server01 ~]# ansible-doc -l |wc -l 3387 查看ansible版本 [root@server01 ~]# ansible --version ansible 2.9.27 config file = /etc/ansible/ansible.cfg configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python2.7/site-packages/ansible executable location = /usr/bin/ansible python version = 2.7.5 (default, Jun 28 2022, 15:30:04) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
3) Ansible清单
inventory文件通常用于定义要管理主机的认证信息, 例如ssh登录用户名、密码以及key相关信息。默认inventory文件为/etc/hostsweb-nodes, ansible模块操作命令中可以省去默认inventory (即可以省去"-i /etc/hostsweb-nodes"), 如果inventory文件定义了其他路径,则在ansible模块操作命令中不能省去, 要加上"-i inventory路径".如何配置Inventory文件?
主控节点:
- 支持主机名通配以及正则表达式,例如web[1:3].oldboy.com;
- 支持基于非标准的ssh端口,例如web1.oldboy.com:6666;
- 支持指定变量,可对个别主机的特殊配置,如登陆用户,密码等;
受控节点
- 支持嵌套组,例如[game:children],那么在game模块下面的组都会被game所包含;
- 支持指定变量,例如[game:vars]在下面指定变量;
ansible的inventory清单文件(/etc/ansible/hosts)中配置说明:
[ ] 中的名字代表组名
主机(hosts)部分可以使用域名、主机名、IP地址表示, 一般此类配置中多使用IP地址;
组名下的主机地址就是ansible可以管理的地址;
下面是/etc/ansible/hosts 文件中清单的配置示例:
[root@server01 ~]# cat /etc/ansible/hosts #可以使用受控节点的ip, 下面表示centos7_test组包括192.168.200.22~25四台机器 #被管理的机器IP D段如果是连续的就可以写为下面的方式,如果是单个的,需要单独写 [centos7_test] 192.168.200.[22:25] #192.168.200.200 #www.dingmr.com [centos8_test] 192.168.200.[51:53] #也可以使用受控节点的主机名, 前提是主控节点要能跟受控节点的主机名正常通信 #[servers] #server02 #server03 简单测试,可设置是否生效 查看ansible清单里所有节点的uptime情况 [root@server01 ~]# ansible all -m command -a "uptime" 192.168.200.23 | CHANGED | rc=0 >> 04:43:04 up 48 min, 1 user, load average: 0.00, 0.01, 0.05 192.168.200.24 | CHANGED | rc=0 >> 04:43:04 up 48 min, 1 user, load average: 0.00, 0.01, 0.05 192.168.200.22 | CHANGED | rc=0 >> 04:43:04 up 48 min, 1 user, load average: 0.00, 0.01, 0.05 192.168.200.25 | CHANGED | rc=0 >> 04:43:04 up 48 min, 1 user, load average: 0.00, 0.01, 0.05 192.168.200.53 | CHANGED | rc=0 >> 04:43:04 up 48 min, 1 user, load average: 0.00, 0.00, 0.00 192.168.200.52 | CHANGED | rc=0 >> 04:43:05 up 48 min, 1 user, load average: 0.00, 0.00, 0.00 192.168.200.51 | CHANGED | rc=0 >> 04:43:05 up 48 min, 1 user, load average: 0.00, 0.00, 0.00 查看ansible清单里centos7_test组的节点的主机名 [root@server01 ~]# ansible centos7_test -m command -a "hostname" 192.168.200.23 | CHANGED | rc=0 >> server03 192.168.200.25 | CHANGED | rc=0 >> server05 192.168.200.24 | CHANGED | rc=0 >> server04 192.168.200.22 | CHANGED | rc=0 >> server02
ansible 命令详解
命令的具体格式如下: ansible <host-pattern> [-f forks] [-m module_name] [-a args] 也可以通过ansible -h来查看帮助,下面我们列出一些比较常用的选项,并解释其含义: -a MODULE_ARGS #模块的参数,如果执行默认COMMAND的模块,即是命令参数,如: “date”,“pwd”等等 -k,--ask-pass #ask for SSH password。登录密码,提示输入SSH密码而不是假设基于密钥的验证 --ask-su-pass #ask for su password。su切换密码 -K,--ask-sudo-pass #ask for sudo password。提示密码使用sudo,sudo表示提权操作 --ask-vault-pass #ask for vault password。假设我们设定了加密的密码,则用该选项进行访问 -B SECONDS #后台运行超时时间 -C #模拟运行环境并进行预运行,可以进行查错测试 -c CONNECTION #连接类型使用 -f FORKS #并行任务数,默认为5 -i INVENTORY #指定主机清单的路径,默认为/etc/ansible/hosts --list-hosts #查看有哪些主机组 -m MODULE_NAME #执行模块的名字,默认使用 command 模块,所以如果是只执行单一命令可以不用 -m参数 -o #压缩输出,尝试将所有结果在一行输出,一般针对收集工具使用 -S #用 su 命令 -R SU_USER #指定 su 的用户,默认为 root 用户 -s #用 sudo 命令 -U SUDO_USER #指定 sudo 到哪个用户,默认为 root 用户 -T TIMEOUT #指定 ssh 默认超时时间,默认为10s,也可在配置文件中修改 -u REMOTE_USER #远程用户,默认为 root 用户 -v #查看详细信息,同时支持-vvv,-vvvv可查看更详细信息
4) Ansible 常用模块
#ansible-doc -l #查看所有模块
#ansible-doc -s MODULE_NAME #查看指定模块的详细帮助
1. ping模块
检查指定节点机器是否还能连通,用法很简单,不涉及参数. 主机如果在线,则回复pong. 测试连通性的模块
#查看所有机器的连通性
[root@server01 ~]# ansible all -m ping
192.168.200.25 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.200.22 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.200.24 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.200.23 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
192.168.200.53 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.200.51 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.200.52 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
#查看centos8_test组机器的连通性
[root@server01 ~]# ansible centos8_test -m ping
192.168.200.53 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.200.52 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
192.168.200.51 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
2、command模块
#这个模块可以直接在远程主机上执行命令,并将结果返回本主机。 #命令模块接受命令名称,后面是空格分隔的列表参数。给定的命令将在所有选定的节点上执行。它不会通过shell进行处理,比如$HOME和操作如"<",">","|",";","&" 工作(需要使用(shell)模块实现这些功能)。注意,该命令不支持| 管道命令。 command模块包含如下选项: creates:一个文件名,当该文件存在,则该命令不执行 free_form:要执行的linux指令 chdir:在执行指令之前,先切换到该指定的目录 removes:一个文件名,当该文件不存在,则该选项不执行 executable:切换shell来执行指令,该执行路径必须是一个绝对路径 示例: #查看centos8_test组所有机器的时间 [root@server01 ~]# ansible centos8_test -m command -a 'date' 192.168.200.53 | CHANGED | rc=0 >> 2023年 07月 13日 星期四 05:04:43 CST 192.168.200.51 | CHANGED | rc=0 >> 2023年 07月 13日 星期四 05:04:43 CST 192.168.200.52 | CHANGED | rc=0 >> 2023年 07月 13日 星期四 05:04:43 CST #先切换到/tmp/ 目录,再执行“ls”命令 [root@server01 ~]# ansible centos8_test -m command -a 'chdir=/tmp ls -l' 192.168.200.53 | CHANGED | rc=0 >> 总用量 0 drwx------ 2 root root 41 7月 13 05:08 ansible_command_payload_b_9t9s29 drwx------ 2 root root 41 7月 12 02:38 ansible_command_payload_skhplam1 drwx------ 3 root root 17 7月 13 03:54 systemd-private-05dfb89a051841c79ab0a3b7ed833f9c-chronyd.service-bHNPf1 drwx------ 2 root root 6 7月 13 03:54 vmware-root_865-3980167289 drwx------ 2 root root 6 7月 12 02:39 vmware-root_881-4013198953 drwx------ 2 root root 6 7月 12 02:30 vmware-root_882-2688685109 drwx------ 2 root root 6 7月 12 02:26 vmware-root_891-3988228581 drwx------ 2 root root 6 7月 12 02:41 vmware-root_904-2697008433 192.168.200.51 | CHANGED | rc=0 >> 总用量 16 drwx------ 2 root root 41 7月 12 02:38 ansible_command_payload_9pryhft6 drwx------ 2 root root 41 7月 13 05:08 ansible_command_payload_un5g2bs1 -rw-r--r-- 1 dm dm 158 7月 12 01:41 hosts srwxrwxrwx 1 mysql mysql 0 7月 13 03:54 mysql.sock -rw------- 1 mysql mysql 5 7月 13 03:54 mysql.sock.lock srwxrwxrwx 1 mysql mysql 0 7月 13 03:54 mysqlx.sock -rw------- 1 mysql mysql 5 7月 13 03:54 mysqlx.sock.lock drwxr-xr-x 3 root root 18 7月 4 18:59 pear srw-rw-rw- 1 www www 0 7月 13 03:54 php-cgi.sock drwx------ 3 root root 17 7月 13 03:54 systemd-private-1eaaba22d3e942b493053a834a9cb2dd-chronyd.service-aM6ouy drwxrwxrwt 16 root root 4096 7月 12 01:59 tmp drwx------ 2 root root 6 7月 13 03:54 vmware-root_845-4021653450 drwx------ 2 root root 6 7月 11 23:52 vmware-root_849-4013723217 drwx------ 2 root root 6 7月 4 17:49 vmware-root_852-2689078282 drwx------ 2 root root 6 7月 5 14:24 vmware-root_867-3988621819 drwx------ 2 root root 6 7月 12 02:39 vmware-root_874-2689078315 drwx------ 2 root root 6 7月 4 17:51 vmware-root_881-4013198953 drwx------ 2 root root 6 7月 4 17:54 vmware-root_891-3988228581 192.168.200.52 | CHANGED | rc=0 >> 总用量 16 drwx------ 2 root root 41 7月 12 02:38 ansible_command_payload_enoeeht4 drwx------ 2 root root 41 7月 13 05:08 ansible_command_payload_n_28gtsr -rw-r--r-- 1 dm dm 158 7月 12 01:41 hosts srwxrwxrwx 1 mysql mysql 0 7月 13 03:54 mysql.sock -rw------- 1 mysql mysql 5 7月 13 03:54 mysql.sock.lock srwxrwxrwx 1 mysql mysql 0 7月 13 03:54 mysqlx.sock -rw------- 1 mysql mysql 5 7月 13 03:54 mysqlx.sock.lock drwxr-xr-x 3 root root 18 7月 4 18:56 pear srw-rw-rw- 1 www www 0 7月 13 03:54 php-cgi.sock drwx------ 3 root root 17 7月 13 03:54 systemd-private-a0a3d0621bce4f60a69dd5204cd65bac-chronyd.service-xHmMsH drwxrwxrwt 16 root root 4096 7月 12 01:59 tmp drwx------ 2 root root 6 7月 4 17:51 vmware-root_845-4021653450 drwx------ 2 root root 6 7月 13 03:54 vmware-root_860-2722763268 drwx------ 2 root root 6 7月 5 14:24 vmware-root_862-2731217798 drwx------ 2 root root 6 7月 4 17:53 vmware-root_863-3980167256 drwx------ 2 root root 6 7月 4 17:54 vmware-root_872-2697532841 drwx------ 2 root root 6 7月 12 02:39 vmware-root_882-2688685109 drwx------ 2 root root 6 7月 11 23:52 vmware-root_885-4021784556 #如果/tmp/hosts文件存在,则不执行“ls”命令 [root@server01 ~]# ansible centos8_test -m command -a 'creates=/tmp/hosts ls' 192.168.200.53 | CHANGED | rc=0 >> anaconda-ks.cfg modify_hostname_and_ips_8.sh sys_opt_centos8.sh 192.168.200.51 | SUCCESS | rc=0 >> skipped, since /tmp/hosts exists 192.168.200.52 | SUCCESS | rc=0 >> skipped, since /tmp/hosts exists #说明:53这台机器上不存在hosts文件 所以执行了ls命令 #如果/tmp/hosts存在,则执行“cat /tmp/hosts”命令 [root@server01 ~]# ansible centos8_test -m command -a 'removes=/tmp/hosts cat /tmp/hosts' 192.168.200.53 | SUCCESS | rc=0 >> skipped, since /tmp/hosts does not exist 192.168.200.52 | CHANGED | rc=0 >> 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6 192.168.200.51 | CHANGED | rc=0 >> 127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4 ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
3、shell模块